/* A self-contained weather surface: the sky carries condition, not alert severity. */
.wx-panel {
  --wx-top: #164776;
  --wx-bottom: #487faa;
  position: relative;
  isolation: isolate;
  overflow: hidden;
  margin: 18px 0 0;
  border: 1px solid #ffffff24;
  border-radius: 22px;
  background: linear-gradient(145deg, var(--wx-top), var(--wx-bottom));
  color: #fff;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  box-shadow: inset 0 1px 0 #ffffff17, 0 10px 30px #00000015;
  text-align: left;
  container-type: inline-size;
}
.wx-condition-cloudy { --wx-top: #272e34; --wx-bottom: #505b64 }
.wx-condition-rain { --wx-top: #182d41; --wx-bottom: #4b687b }
.wx-condition-night-cloudy { --wx-top: #192439; --wx-bottom: #42506c }
.wx-condition-night { --wx-top: #101a34; --wx-bottom: #354768 }
.wx-panel button { font-family: inherit; color: inherit; cursor: pointer }
.wx-panel button:focus-visible { outline: 2px solid white; outline-offset: -3px }
.wx-sky { position: absolute; inset: 0; overflow: hidden; pointer-events: none; z-index: -1 }
.wx-content { position: relative; padding: 20px 23px 18px }
.wx-heading, .wx-heading-tools, .wx-eyebrow, .wx-current, .wx-details, .wx-condition-label, .wx-hourly-intro, .wx-forecast-heading, .wx-footer { display: flex; align-items: center }
.wx-heading { justify-content: space-between; gap: 12px }
.wx-eyebrow { gap: 7px; font-size: 12px; font-weight: 600; letter-spacing: .1em; color: #e6effa }
.wx-heading-tools { gap: 12px }
.wx-sample { font-size: 12px; color: #e1ebf5 }
.wx-motion { width: 32px; height: 32px; border: 1px solid #ffffff32; border-radius: 50%; background: #10315333; display: grid; place-items: center }
.wx-motion:disabled { opacity: .5; cursor: default }
.wx-current { justify-content: space-between; gap: 25px; padding: 10px 0 16px }
.wx-panel .wx-location h3 { margin: 0; padding: 0; font-size: 25px; font-weight: 500; letter-spacing: -.04em; line-height: 1.25; color: #fff }
.wx-temperature { display: flex; align-items: flex-start; width: fit-content; font-size: 80px; font-weight: 200; letter-spacing: -.065em; line-height: 1.1; margin-top: 1px; text-shadow: 0 2px 24px #14345626; font-variant-numeric: tabular-nums }
.wx-temperature>span { font-size: 72px; font-weight: 200; line-height: 1.1; margin-top: 5px }
.wx-condition-label { gap: 7px; font-size: 16px; margin: 0; line-height: 1.5 }
.wx-condition-label>span { color: #e0eaf5; font-size: 14px }
.wx-symbol { width: 31px; height: 31px; overflow: visible; flex-shrink: 0 }
.wx-condition-label .wx-symbol { width: 25px; height: 25px }
.wx-range { font-size: 14px; margin: 5px 0 0; color: #f3f6fc }
.wx-range>span { margin-left: 9px; color: #d5e3f3 }
.wx-details { gap: 30px; align-self: flex-end; margin-bottom: 8px; padding: 16px 20px; border: 1px solid #ffffff20; border-radius: 16px; background: #10284130; backdrop-filter: blur(12px) }
.wx-details>div { display: flex; flex-direction: column; gap: 5px }
.wx-details>div>span { font-size: 11px; letter-spacing: .06em; font-weight: 600; color: #dbe7f4 }
.wx-details strong { display: flex; align-items: baseline; gap: 3px; font-size: 30px; font-weight: 400; line-height: 1.1; font-variant-numeric: tabular-nums; color: #fff }
.wx-details strong>small { font-size: 16px }
.wx-details strong>svg { margin-left: 5px; align-self: center }
.wx-details>div>small { font-size: 12px; color: #dbe7f4 }
.wx-hourly { overflow: hidden; border-radius: 15px; background: #10274455; border: 1px solid #ffffff29; box-shadow: inset 0 1px 0 #ffffff0d; backdrop-filter: blur(18px) }
.wx-hourly-intro { gap: 9px; padding: 10px 17px; border-bottom: 1px solid #ffffff20; color: #f0f5fc }
.wx-hourly-intro>svg { flex-shrink: 0 }
.wx-hourly-intro p { margin: 0; font-size: 14px; line-height: 1.5 }
.wx-forecast-heading { justify-content: space-between; gap: 10px; padding: 10px 17px 6px; color: #c8d9eb; font-size: 11px; letter-spacing: .06em; font-weight: 500 }
.wx-forecast-heading>span:last-child { letter-spacing: 0; font-size: 12px }
.wx-hourly-scroll { overflow-x: auto; scrollbar-width: thin; scrollbar-color: #ffffff45 transparent; overscroll-behavior-x: contain }
.wx-chart-track { min-width: 560px; position: relative; display: grid; grid-template-columns: repeat(8, minmax(0, 1fr)); padding: 0 0 2px }
.wx-chart { position: absolute; inset: 99px 0 auto; width: 100%; height: 55px; pointer-events: none }
.wx-hour { position: relative; display: flex; align-items: center; flex-direction: column; gap: 8px; padding: 10px 0 7px; border: 1px solid transparent; border-radius: 11px; background: transparent; min-height: 176px; transition: background .2s, border-color .2s; font-variant-numeric: tabular-nums }
.wx-hour.is-selected { background: linear-gradient(#ffffff1d, #ffffff06); border-color: #ffffff30 }
.wx-hour-time { font-size: 13px; line-height: 20px; color: #e9f0fa }
.wx-hour strong { font-size: 21px; font-weight: 500; line-height: 26px; color: #fff }
.wx-hour .wx-symbol { width: 29px; height: 29px }
.wx-hour-rain { margin-top: auto; font-size: 12px; color: #b2d7fb; line-height: 20px }
.wx-footer { justify-content: space-between; gap: 10px; padding: 7px 17px 9px; color: #c8d9eb; font-size: 11px }
.wx-sun { position: absolute; width: 350px; height: 350px; top: -75px; right: 4%; animation: wx-sun-breathe 9s ease-in-out infinite alternate }
.wx-sun-disc { position: absolute; width: 62px; height: 62px; top: 144px; left: 144px; border-radius: 50%; background: #fff9dc; box-shadow: 0 0 20px 7px #fff4c77a, 0 0 75px 32px #ffdb7855, 0 0 135px 65px #ffdc6426 }
.wx-sun-rays { position: absolute; inset: -70px; border-radius: 50%; background: repeating-conic-gradient(from 10deg, transparent 0deg 18deg, #fff3b809 22deg 26deg, transparent 30deg 45deg); mask-image: radial-gradient(circle, transparent 8%, black 30%, transparent 70%); animation: wx-sun-turn 100s linear infinite }
.wx-atmosphere { position: absolute; inset: 0; background: radial-gradient(ellipse at 85% 32%, #c4e9ff18, transparent 60%), linear-gradient(0deg, #0b233644, transparent 75%) }
/* Real cloud silhouettes and internal shading, with independent drift for depth. */
.wx-clouds { position: absolute; inset: 0; opacity: .55; mask-image: linear-gradient(90deg, transparent, #00000055 28%, #000 58%) }
/* Other scenes retain their original subdued atmosphere, without cloud images. */
.wx-cloud-haze { mask-image: none }
.wx-cloud-haze>span { position: absolute; width: 65%; height: 145px; right: -10%; top: 70px; filter: blur(19px); background: radial-gradient(ellipse at 25% 75%, #e9f4ff55 0 24%, transparent 57%), radial-gradient(ellipse at 60% 50%, #e9f4ff77 0 20%, transparent 55%), radial-gradient(ellipse at 85% 80%, #e9f4ff55 0 22%, transparent 55%); animation: wx-cloud-drift 35s ease-in-out infinite alternate }
.wx-cloud-haze>span:nth-child(2) { top: -75px; right: 30%; width: 75%; opacity: .55; animation-duration: 49s; animation-delay: -19s }
.wx-cloud-haze>span:nth-child(3) { top: 145px; right: 0; width: 85%; opacity: .28; animation-duration: 42s; animation-delay: -12s }
.wx-cloud-layer { position: absolute; display: block; width: 72%; max-width: none; height: auto; right: -8%; top: -52px; opacity: .95; animation: wx-cloud-drift 38s ease-in-out -8s infinite alternate }
.wx-cloud-layer:nth-child(2) { top: -110px; right: 29%; width: 57%; opacity: .45; scale: -1 1; animation-duration: 57s; animation-delay: -28s }
.wx-cloud-layer:nth-child(3) { top: 82px; right: -17%; width: 57%; opacity: .55; animation-duration: 46s; animation-delay: -18s }
.wx-condition-cloudy .wx-details, .wx-condition-partly-cloudy .wx-details { background: #142d49c9 }
.wx-sky-sunny .wx-clouds { opacity: .22 }
.wx-sky-cloudy .wx-clouds { opacity: 1 }
.wx-sky-rain .wx-clouds { opacity: .65; filter: brightness(.65) }
.wx-sky-night-cloudy .wx-clouds { opacity: .35 }
.wx-moon { position: absolute; right: 18%; top: 64px; width: 54px; height: 54px; border-radius: 50%; box-shadow: inset 13px -6px 0 0 #e7edff; transform: rotate(-20deg); filter: drop-shadow(0 0 22px #c8d9ff55) }
.wx-stars { position: absolute; inset: 0 }
.wx-stars i { position: absolute; width: 2px; height: 2px; border-radius: 50%; background: #eff3ff; box-shadow: 0 0 4px #ffffff66; animation: wx-star-glow 5s ease-in-out var(--delay) infinite alternate }
.wx-rain { position: absolute; inset: -70px -40px 0; overflow: hidden }
.wx-rain i { position: absolute; top: -15%; width: 1px; height: 52px; background: linear-gradient(transparent, #d1e8ff); opacity: var(--opacity); animation: wx-rain-fall var(--duration) linear var(--delay) infinite }
.wx-paused *, .wx-paused *::before, .wx-paused *::after { animation-play-state: paused !important }
@keyframes wx-sun-breathe { from { opacity: .7; transform: scale(.96) } to { opacity: 1; transform: scale(1.05) } }
@keyframes wx-sun-turn { to { transform: rotate(360deg) } }
@keyframes wx-cloud-drift { from { transform: translateX(-9%) } to { transform: translateX(12%) } }
@keyframes wx-rain-fall { from { transform: translate3d(60px, -70px, 0) rotate(14deg) } to { transform: translate3d(-85px, 650px, 0) rotate(14deg) } }
@keyframes wx-star-glow { from { opacity: .35 } to { opacity: .95 } }
@container (max-width: 530px) {
  .wx-content { padding: 17px 15px 15px }
  .wx-eyebrow { font-size: 10px; letter-spacing: .07em }
  .wx-heading-tools { gap: 7px }
  .wx-sample { font-size: 10px }
  .wx-current { flex-wrap: wrap; padding: 19px 0; gap: 18px }
  .wx-panel .wx-location h3 { font-size: 24px }
  .wx-temperature { font-size: 80px }
  .wx-details { width: 100%; justify-content: space-between; gap: 15px; margin: 0; padding: 12px 16px }
  .wx-details strong { font-size: 24px }
  .wx-details>div { gap: 4px }
  .wx-sun { right: -75px; top: -45px }
  .wx-moon { right: 17%; top: 90px }
  .wx-cloud-layer { width: 110%; right: -36%; top: 24px }
  .wx-cloud-layer:nth-child(2) { width: 95%; right: 9%; top: -18px }
  .wx-cloud-layer:nth-child(3) { width: 95%; right: -38%; top: 113px }
  .wx-footer { font-size: 10px; padding-inline: 12px }
  .wx-hourly-intro { padding: 12px }
  .wx-hourly-intro p { font-size: 13px }
  .wx-forecast-heading { padding-inline: 12px }
}
@media (prefers-reduced-motion: reduce) {
  .wx-panel *, .wx-panel *::before, .wx-panel *::after { animation: none !important; transition: none !important }
  .wx-rain i { top: calc(var(--opacity) * 160%); transform: rotate(14deg) }
}

/* Forecast scenes for the selected flight. */
.wx-condition-snow { --wx-top: #415d78; --wx-bottom: #7794aa }
.wx-condition-thunderstorm { --wx-top: #182339; --wx-bottom: #3d5066 }
.wx-condition-partly-cloudy { --wx-top: #315575; --wx-bottom: #69899e }
.wx-flight-context { margin: 6px 0 2px; font-size: 12px; color: #e0eaf5; line-height: 1.5 }
.wx-flight-context strong { font-weight: 500 }
.wx-sky-snow .wx-clouds { opacity: .65 }
.wx-sky-thunderstorm .wx-clouds { opacity: 1; filter: brightness(.5) }
.wx-snow { position: absolute; inset: -40px -20px 0; overflow: hidden }
.wx-snow i { position: absolute; top: -28px; display: block; width: var(--size); height: var(--size); color: #f2f8ff; opacity: var(--opacity); animation: wx-snow-fall var(--duration) linear var(--delay) infinite }
.wx-snow i>svg { display: block; width: 100%; height: 100% }
@keyframes wx-snow-fall { 0% { transform: translate3d(0,-25px,0) rotate(var(--rotation)) } 45% { transform: translate3d(35px,300px,0) rotate(calc(var(--rotation) + 35deg)) } 100% { transform: translate3d(-15px,760px,0) rotate(calc(var(--rotation) + 80deg)) } }
@media (prefers-reduced-motion: reduce) {
  .wx-snow i { top: calc(var(--opacity) * 100%); animation: none !important }
}

/* Each generated discharge lights the whole sky, with a localized bloom at
   its source. A slower second pulse sometimes illuminates the same channel. */
.wx-storm-lightning, .wx-storm-strike, .wx-cloud-flash { position: absolute; inset: 0; pointer-events: none }
.wx-storm-strike { opacity: var(--strike-intensity) }
.wx-cloud-flash { opacity: 0; background: radial-gradient(ellipse at var(--strike-origin) 0%, #f0edffeb 0%, #bacaff99 23%, #9cb9ed33 57%, transparent 85%), linear-gradient(180deg, #b9caff70, #a7c4ee35 65%, #98b6e51a); animation: wx-storm-illumination var(--strike-duration) linear both }
.wx-lightning-bolt { position: absolute; top: 0; left: 0; width: 100%; height: 80%; overflow: visible; opacity: 0; filter: drop-shadow(0 0 6px #9fbaff); animation: wx-lightning-strike var(--strike-duration) linear both }
.wx-bolt-halo { stroke: #a8baff; stroke-width: 10; opacity: .65; filter: blur(5px) }
.wx-bolt-edge { stroke: #bbceff; stroke-width: 3 }
.wx-bolt-core { stroke: #fff; stroke-width: 1.25 }
.wx-bolt-branch { stroke: #dfebff }
.wx-strike-echo .wx-cloud-flash { animation-name: wx-storm-illumination-echo }
.wx-strike-echo .wx-lightning-bolt { animation-name: wx-lightning-echo }
.wx-sky-thunderstorm .wx-rain i { height: 70px }
@keyframes wx-lightning-strike {
  0% { opacity: 0 }
  3%, 9% { opacity: 1 }
  18% { opacity: .45 }
  38%, 100% { opacity: 0 }
}
@keyframes wx-storm-illumination {
  0% { opacity: 0 }
  2% { opacity: .85 }
  12% { opacity: .65 }
  35% { opacity: .2 }
  85%, 100% { opacity: 0 }
}
@keyframes wx-lightning-echo {
  0%, 38%, 51%, 90%, 100% { opacity: 0 }
  3%, 9% { opacity: 1 }
  20% { opacity: .3 }
  54%, 60% { opacity: .85 }
  72% { opacity: .2 }
}
@keyframes wx-storm-illumination-echo {
  0%, 48%, 100% { opacity: 0 }
  2% { opacity: .85 }
  15% { opacity: .5 }
  35% { opacity: .08 }
  54% { opacity: .7 }
  65% { opacity: .35 }
  88% { opacity: .04 }
}
.wx-paused .wx-storm-strike { opacity: 0 !important }
@media (prefers-reduced-motion: reduce) {
  .wx-storm-lightning { display: none }
}

/* Keep labels readable even when a bright cloud passes behind the glass. */
.wx-condition-cloudy .wx-heading-tools, .wx-condition-partly-cloudy .wx-heading-tools { padding: 3px 4px 3px 10px; border-radius: 22px; background: #142d49b8 }
.wx-condition-cloudy .wx-hourly, .wx-condition-partly-cloudy .wx-hourly { background: #10274499 }

/* Overcast is a low, gray cloud ceiling; fair-weather clouds stay sunlit. */
.wx-sky-cloudy .wx-atmosphere { background: linear-gradient(180deg, #10161d44, #222b3333 55%, #111c2944) }
.wx-sky-cloudy .wx-cloud-layer { width: 112%; right: -7%; top: -60px; scale: 1 .62; transform-origin: top right; filter: saturate(.05) brightness(.58) contrast(.85) }
.wx-sky-cloudy .wx-cloud-layer:nth-child(2) { width: 95%; right: 28%; top: -86px; scale: -1 .54; opacity: .9 }
.wx-sky-cloudy .wx-cloud-layer:nth-child(3) { width: 115%; right: -30%; top: 70px; scale: 1 .6; opacity: .65 }
.wx-sky-partly-cloudy .wx-clouds { opacity: .9 }
.wx-condition-cloudy .wx-details { background: #202b35cf }
.wx-condition-cloudy .wx-hourly { background: #1b2635b8 }
.wx-condition-cloudy .wx-heading-tools { background: #202b35c9 }
.wx-symbol-cloudy>path { fill: #bac3cc }
@container (max-width: 530px) {
  .wx-sky-cloudy .wx-cloud-layer { width: 175%; right: -55%; top: 20px }
  .wx-sky-cloudy .wx-cloud-layer:nth-child(2) { width: 155%; right: 8%; top: -35px }
  .wx-sky-cloudy .wx-cloud-layer:nth-child(3) { width: 170%; right: -65%; top: 125px }
}

/* ==========================================================================
   Fair weather — sunlit cumulus over a clear blue sky
   Same photographic cloud bank the overcast scene uses, but kept white and
   sunlit rather than flattened and desaturated, drifting a little faster so the
   movement reads at a glance. Plain `sunny` is untouched and still renders a
   cloudless sky, so both the clear and the cumulus reading stay available.
   ========================================================================== */
.wx-condition-sunny-clouds { --wx-top: #1a5486; --wx-bottom: #5b95bd }
.wx-sky-sunny-clouds .wx-clouds { opacity: .82 }
.wx-sky-sunny-clouds .wx-cloud-layer { filter: brightness(1.07) saturate(.92); animation-duration: 26s }
.wx-sky-sunny-clouds .wx-cloud-layer:nth-child(2) { opacity: .5; animation-duration: 38s }
.wx-sky-sunny-clouds .wx-cloud-layer:nth-child(3) { opacity: .6; animation-duration: 31s }
.wx-sky-sunny-clouds .wx-atmosphere { background: radial-gradient(ellipse at 85% 30%, #d7f0ff26, transparent 62%), linear-gradient(0deg, #0e2c4440, transparent 78%) }

/* A bright cloud passing behind the glass would wash the labels out, so the same
   scrim the cloudy scenes use, tinted to this sky rather than to grey. */
.wx-condition-sunny-clouds .wx-details { background: #10446fc4 }
.wx-condition-sunny-clouds .wx-heading-tools { padding: 3px 4px 3px 10px; border-radius: 22px; background: #10446fb0 }
.wx-condition-sunny-clouds .wx-hourly { background: #0d3c6494 }
/* The services checklist.
 *
 * Normal recedes: a card with nothing outstanding sits on the plain surface with a
 * dim green mark, never a filled green panel. Only amber and red tint their chrome,
 * so a glance at the grid lands on the work and nowhere else — which is the same
 * thing the supplied frames do by leaving every settled card blue and colouring
 * only the one that needs attention.
 */

.visually-hidden {
   position: absolute;
   width: 1px;
   height: 1px;
   padding: 0;
   margin: -1px;
   overflow: hidden;
   clip: rect(0 0 0 0);
   white-space: nowrap;
   border: 0
}

.aircraft-panes {
   display: flex;
   flex-direction: column;
   gap: 18px
}

.aircraft-pane-switch {
   display: flex;
   gap: 8px;
   flex-wrap: wrap
}

.aircraft-pane-button {
   display: inline-flex;
   align-items: center;
   gap: 7px;
   padding: 9px 15px;
   font-size: 13px;
   font-weight: 500;
   color: var(--muted-strong);
   background: transparent;
   border: 1px solid var(--line);
   border-radius: 7px;
   cursor: pointer;
   transition: background var(--dur-fast, .16s) var(--ease-standard), color var(--dur-fast, .16s) var(--ease-standard), border-color var(--dur-fast, .16s) var(--ease-standard)
}

/* Affordance is luminance, not hue: the selected pane is the brightest thing in
   the row. The tone below it is state, and it survives selection. */
.aircraft-pane-button.active {
   background: var(--ink);
   border-color: var(--ink);
   color: #fff
}

.aircraft-pane-button.tone-amber {
   border-color: #e8bf7c;
   color: #8a5100
}

.aircraft-pane-button.tone-amber.active {
   background: #8a5100;
   border-color: #8a5100;
   color: #fff
}

.aircraft-pane-button.tone-red {
   border-color: #e8a79f;
   color: #a32b23
}

.aircraft-pane-button.tone-red.active {
   background: #9c2820;
   border-color: #9c2820;
   color: #fff
}

.aircraft-pane-mark {
   display: grid;
   place-items: center
}

.services-grid {
   display: grid;
   grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
   gap: 14px
}

.service-card {
   display: flex;
   flex-direction: column;
   gap: 12px;
   padding: 15px 16px 16px;
   background: #fff;
   border: 1px solid var(--line);
   border-top: 3px solid var(--line);
   border-radius: var(--radius);
   animation: surfaceEnter var(--dur-base, .3s) var(--ease-entrance, var(--ease-standard)) both
}

/* The top accent is the card-level cue the frames carry in their coloured header
   bar, kept as an edge so the card body stays readable. The tint is a flat colour
   rather than a gradient so `docs/hover-contrast-audit.js` can resolve the controls
   sitting on it instead of reporting them as unjudgeable. */
.service-card.tone-amber {
   border-color: #f1dab4;
   border-top-color: #c98a16;
   background: #fffaf1
}

.service-card.tone-red {
   border-color: #eec4bf;
   border-top-color: #c0392f;
   background: #fff6f5
}

.service-card-heading {
   display: flex;
   align-items: center;
   gap: 9px
}

.service-card-heading h4 {
   margin: 0;
   font-size: 14px;
   font-weight: 600;
   color: var(--ink);
   flex: 1;
   min-width: 0
}

.service-card-heading>.status-badge {
   flex-shrink: 0
}

.service-card-icon {
   display: grid;
   place-items: center;
   width: 30px;
   height: 30px;
   border-radius: 8px;
   background: #f3f3f3;
   color: #5f5f5f;
   flex-shrink: 0
}

.service-card.tone-amber .service-card-icon {
   background: #fdf0da;
   color: #8a5100
}

.service-card.tone-red .service-card-icon {
   background: #fbe6e3;
   color: #a32b23
}

.service-item-list {
   list-style: none;
   margin: 0;
   padding: 0;
   display: flex;
   flex-direction: column;
   gap: 9px
}

.service-item {
   display: grid;
   grid-template-columns: 20px 1fr;
   align-items: start;
   gap: 3px 9px
}

.service-mark {
   display: grid;
   place-items: center;
   width: 18px;
   height: 18px;
   margin-top: 1px;
   border-radius: 5px;
   background: #f1f1f1;
   color: #8a8a8a
}

.service-item.state-complete .service-mark {
   background: #e7f4ee;
   color: #14684b
}

.service-item.state-pending .service-mark {
   background: #fdefd6;
   color: #8a5100
}

.service-item.state-error .service-mark {
   background: #fbe3e0;
   color: #a32b23
}

/* Nothing pulses ambiently. An outstanding or failed item announces itself once as
   it arrives — three cycles, well under the 3 Hz flash threshold — and then holds
   its colour, the way the annunciator does. */
.service-item.state-pending .service-mark,
.service-item.state-error .service-mark {
   animation: serviceMark 620ms var(--ease-standard) 3
}

@keyframes serviceMark {
   0%, 100% { box-shadow: 0 0 0 0 transparent }
   50% { box-shadow: 0 0 0 4px rgba(192, 57, 47, .16) }
}

.service-item.state-pending .service-mark {
   animation-name: serviceMarkCaution
}

@keyframes serviceMarkCaution {
   0%, 100% { box-shadow: 0 0 0 0 transparent }
   50% { box-shadow: 0 0 0 4px rgba(201, 138, 22, .2) }
}

.service-item-label {
   display: flex;
   align-items: baseline;
   gap: 8px;
   flex-wrap: wrap;
   min-width: 0
}

.service-item-label strong {
   font-size: 13px;
   font-weight: 500;
   color: var(--ink)
}

.service-item-meta {
   font-size: 12px;
   font-weight: 600;
   color: #5f5f5f;
   font-variant-numeric: tabular-nums;
   font-feature-settings: "tnum"
}

.service-item-note {
   grid-column: 2;
   font-size: 11px;
   line-height: 1.45;
   color: var(--muted)
}

.service-item.state-error .service-item-note {
   color: #a32b23
}

.service-item.state-pending .service-item-note {
   color: #8a5100
}

.service-card-link {
   align-self: flex-start;
   margin-top: auto;
   padding-top: 2px
}

.details-list .figure {
   font-variant-numeric: tabular-nums;
   font-feature-settings: "tnum"
}

@media (prefers-reduced-motion: reduce) {

   .service-card,
   .service-item .service-mark {
      animation: none
   }
}

[data-theme=dark] .service-card {
   background: #1e1e1e;
   border-color: #333;
   border-top-color: #3d3d3d
}

[data-theme=dark] .service-card.tone-amber {
   background: #211c12;
   border-color: #4b3d2c;
   border-top-color: #c98a16
}

[data-theme=dark] .service-card.tone-red {
   background: #211514;
   border-color: #50322e;
   border-top-color: #d8564a
}

[data-theme=dark] .service-card-icon {
   background: #2a2a2a;
   color: #b4b4b4
}

[data-theme=dark] .service-card.tone-amber .service-card-icon {
   background: #33270f;
   color: #e2a745
}

[data-theme=dark] .service-card.tone-red .service-card-icon {
   background: #341c19;
   color: #ef8a80
}

[data-theme=dark] .service-mark {
   background: #2a2a2a;
   color: #9a9a9a
}

[data-theme=dark] .service-item.state-complete .service-mark {
   background: #16281f;
   color: #62c39c
}

[data-theme=dark] .service-item.state-pending .service-mark {
   background: #33270f;
   color: #e2a745
}

[data-theme=dark] .service-item.state-error .service-mark {
   background: #341c19;
   color: #ef8a80
}

[data-theme=dark] .service-item.state-error .service-item-note {
   color: #ef8a80
}

[data-theme=dark] .service-item.state-pending .service-item-note {
   color: #e2a745
}

[data-theme=dark] .service-item-meta {
   color: #b4b4b4
}

[data-theme=dark] .aircraft-pane-button.active {
   background: #efefef;
   border-color: #efefef;
   color: #1a1a1a
}

[data-theme=dark] .aircraft-pane-button.tone-amber {
   border-color: #6b5526;
   color: #e2a745
}

[data-theme=dark] .aircraft-pane-button.tone-amber.active {
   background: #e2a745;
   border-color: #e2a745;
   color: #1a1a1a
}

[data-theme=dark] .aircraft-pane-button.tone-red {
   border-color: #6d3a34;
   color: #ef8a80
}

[data-theme=dark] .aircraft-pane-button.tone-red.active {
   background: #ef8a80;
   border-color: #ef8a80;
   color: #1a1a1a
}

@media (max-width: 720px) {
   .services-grid {
      grid-template-columns: 1fr
   }
}
/* Flight board — every rule scoped under `.board-view` so the board and the
   workspace cannot collide in the cascade. Tokens are declared for the light
   theme first, then overridden for dark, matching styles.css. */

.board-view {
  --board-surface: #ffffff;
  --board-raised: #f6f6f6;
  --board-line: #eaeaea;
  --board-line-strong: #dcdcdc;
  --board-dim: #8a8a8a;
  --board-dimmer: #c4c4c4;
  --board-warning: #a32b23;
  --board-caution: #9c5c00;
  --board-normal: #147653;
  --board-warning-bg: #fdeceb;
  --board-caution-bg: #fff0d9;
  --board-font-data: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  --board-row-pad: 13px;
  --board-row-font: 13px;

  display: block;
  padding: 22px 20px 32px;
  background: #f8f8f8;
  /* Matches `.dashboard-layout` — the header is 76 px, the view owns the rest. */
  height: calc(100dvh - 76px);
  overflow: auto;
  scrollbar-width: thin;
}

[data-theme=dark] .board-view {
  --board-surface: #1e1e1e;
  --board-raised: #272727;
  --board-line: #333333;
  --board-line-strong: #3f3f3f;
  --board-dim: #7d7d7d;
  --board-dimmer: #4a4a4a;
  --board-warning: #ff5f56;
  --board-caution: #ffc233;
  --board-normal: #34d399;
  --board-warning-bg: #3a1d1c;
  --board-caution-bg: #33260a;
  background: #181818;
}

[data-density=compact] .board-view { --board-row-pad: 7px; --board-row-font: 12px; }

/* ---- heading ----------------------------------------------------------- */
.board-head { display: flex; align-items: flex-end; gap: 20px; flex-wrap: wrap; margin-bottom: 16px; }
.board-head h1 { margin: 0; font-size: 22px; font-weight: 600; letter-spacing: -.02em; }
.board-sub { margin: 4px 0 0; color: var(--muted); font-size: 12.5px; }
.board-sub span { color: var(--board-dimmer); margin: 0 5px; }

.board-rollup {
  margin-left: auto; display: flex; align-items: center; gap: 11px;
  padding: 9px 15px 9px 13px; border-radius: 8px;
  background: var(--board-raised); border: 1px solid var(--board-line-strong);
}
.board-rollup-text strong { display: block; font-size: 11px; letter-spacing: .09em; text-transform: uppercase; }
.board-rollup-text small { display: block; color: var(--muted); font-size: 11px; margin-top: 2px; }
.board-rollup-count { font-family: var(--board-font-data); font-size: 15px; font-weight: 700; color: var(--board-dim); }
.board-rollup.caution { border-color: var(--board-caution); }
.board-rollup.caution .board-rollup-text strong, .board-rollup.caution .board-rollup-count { color: var(--board-caution); }
.board-rollup.warning { border-color: var(--board-warning); }
.board-rollup.warning .board-rollup-text strong, .board-rollup.warning .board-rollup-count { color: var(--board-warning); }

/* Dark cockpit: unlit unless something is actually open. */
.board-lamp { width: 8px; height: 8px; border-radius: 50%; background: var(--board-dimmer); flex: none; }
.board-rollup.caution .board-lamp { background: var(--board-caution); }
.board-rollup.warning .board-lamp { background: var(--board-warning); }

/* ---- toolbar ----------------------------------------------------------- */
.board-toolbar { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; padding-bottom: 14px; }

.board-search {
  display: flex; align-items: center; gap: 8px;
  flex: 1 1 210px; min-width: 190px; max-width: 320px;
  padding: 7px 12px; border-radius: 7px;
  background: var(--board-raised); border: 1px solid var(--board-line-strong);
  color: var(--board-dim);
}
.board-search input { flex: 1; min-width: 0; border: 0; background: none; color: var(--ink); font-size: 12.5px; outline: none; }
.board-search:focus-within { border-color: var(--muted); }

.board-seg { display: flex; border: 1px solid var(--board-line-strong); border-radius: 7px; overflow: hidden; background: var(--board-raised); }
.board-seg button {
  padding: 8px 13px; font-size: 11.5px; font-weight: 500; color: var(--muted);
  border-right: 1px solid var(--board-line-strong);
}
.board-seg button:last-child { border-right: 0; }
.board-seg button.selected { background: var(--board-line); color: var(--ink); font-weight: 600; }
.board-seg button span { font-family: var(--board-font-data); margin-left: 6px; font-size: 11px; color: var(--board-dim); }

.board-attn {
  display: flex; align-items: center; gap: 8px; padding: 8px 14px; border-radius: 7px;
  font-size: 12px; font-weight: 500; color: var(--muted);
  background: var(--board-raised); border: 1px solid var(--board-line-strong);
}
.board-attn.selected { border-color: var(--board-caution); color: var(--board-caution); background: var(--board-caution-bg); }
.board-attn.selected .board-lamp { background: var(--board-caution); }

/* ---- grid -------------------------------------------------------------- */
.board-grid {
  border: 1px solid var(--board-line-strong); border-radius: 10px;
  overflow: hidden; background: var(--board-surface);
}

.board-columns {
  display: grid;
  grid-template-columns: 18px 78px 44px 138px 84px minmax(110px, 1fr) 96px 1px repeat(5, minmax(54px, 66px)) 84px;
  align-items: center;
  gap: 0 10px;
}
.board-head-row {
  padding: 0 16px; height: 34px;
  background: var(--board-raised); border-bottom: 1px solid var(--board-line-strong);
  font-size: 9.5px; letter-spacing: .11em; text-transform: uppercase;
  color: var(--board-dim); font-weight: 600;
}
.board-col-head { text-align: center; }
.board-rule { width: 1px; height: 22px; background: var(--board-line-strong); justify-self: center; }

.board-row-wrap { border-bottom: 1px solid var(--board-line); }
.board-row-wrap:last-child { border-bottom: 0; }
.board-row-wrap.lit-caution { background: color-mix(in srgb, var(--board-caution) 5%, transparent); }
.board-row-wrap.lit-warning { background: color-mix(in srgb, var(--board-warning) 6%, transparent); }

.board-row { padding: var(--board-row-pad) 16px; position: relative; font-size: var(--board-row-font); }
.board-row::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: transparent; }
.lit-caution .board-row::before { background: var(--board-caution); }
.lit-warning .board-row::before { background: var(--board-warning); }

/* The flight identity is one button, so the whole row expands from anywhere
   that is not a cell. Subgrid keeps it aligned to the header. */
.board-ident {
  grid-column: 1 / 8; display: grid; grid-template-columns: subgrid;
  align-items: center; gap: 0 10px; text-align: left;
  margin: calc(var(--board-row-pad) * -1) 0; padding: var(--board-row-pad) 0;
}

/* The disclosure indicator. A row does two different things depending on where
   you click it — the identity expands it, the cells and the Open button leave the
   board — so the expanding half has to say so before it is clicked, not only
   through `aria-expanded` after. It points right when closed, down when open. */
.board-twisty {
  display: grid; place-items: center;
  /* `--board-dim`, not `--board-dimmer`: this is now the only thing telling you the
     row opens, so it is a control affordance and owes WCAG 1.4.11's 3:1, which the
     dimmer grey missed at 1.88:1 on the board surface. */
  color: var(--board-dim);
  transition: color .15s, transform var(--dur-fast) var(--ease-entrance);
}
.board-ident[aria-expanded=true] .board-twisty { transform: rotate(90deg); color: var(--ink); }
.board-ident:hover .board-twisty { color: var(--ink); }

/* An open row stays marked while you read its detail, so it is obvious which
   flight the panel below belongs to. */
.board-row-wrap.is-open { background: color-mix(in srgb, var(--ink) 3%, transparent); }
.board-row-wrap.is-open.lit-caution { background: color-mix(in srgb, var(--board-caution) 8%, transparent); }
.board-row-wrap.is-open.lit-warning { background: color-mix(in srgb, var(--board-warning) 9%, transparent); }

.board-time { font-family: var(--board-font-data); font-weight: 500; font-size: calc(var(--board-row-font) + 1px); }
.board-time small { display: block; color: var(--board-dim); font-size: 10px; font-weight: 400; margin-top: 1px; }
[data-density=compact] .board-time small { display: none; }

.board-dir {
  font-family: var(--board-font-data); font-size: 9.5px; font-weight: 700; letter-spacing: .06em;
  padding: 3px 6px; border-radius: 4px; background: var(--board-line); color: var(--muted);
}
.board-route { font-family: var(--board-font-data); font-weight: 500; display: flex; align-items: center; gap: 5px; }
.board-route .app-icon { color: var(--board-dimmer); }
.board-tail { font-family: var(--board-font-data); font-weight: 700; }
.board-type { color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.board-state { font-size: 11.5px; color: var(--muted); }
.board-state.is-delayed { color: var(--board-caution); }

.board-cell { display: flex; justify-content: center; }

.board-go-cell { display: flex; justify-content: flex-end; }
.board-go {
  display: flex; align-items: center; gap: 6px;
  padding: 5px 9px; border-radius: 6px;
  font-size: 11.5px; font-weight: 500; color: var(--muted);
  background: var(--board-surface); border: 1px solid var(--board-line-strong);
  transition: background .15s, color .15s, border-color .15s;
}
.board-go .app-icon { color: var(--board-dimmer); transition: color .15s; }
/* Pointing at the row brings Open forward, so it reads as belonging to the flight
   under the cursor rather than floating in the column — but NOT while the pointer
   is on the identity, which expands the row instead. Lighting up Open while the
   cursor sits on the control that expands advertises the wrong action, and that is
   exactly what the row felt like before: highlight one thing, do another.

   `:not(:hover):not(:focus-visible)` is load-bearing, not decoration. Without it
   this rule outranks the button's own hover and repaints the text with the very
   colour the button just set as its background — a filled pill with invisible
   text. The two states are mutually exclusive now, so neither can half-apply. */
.board-row-wrap:hover:not(:has(.board-ident:hover)) .board-go:not(:hover):not(:focus-visible) { color: var(--ink); border-color: var(--muted); }
.board-go:hover .app-icon,
.board-go:focus-visible .app-icon { color: inherit; }
.board-nil { color: var(--board-dimmer); font-size: 13px; line-height: 1; padding: 6px; }

/* A cleared gate confirms itself, quietly. Dial `--board-ok-strength` if the
   confirmations read too loud or too faint against the amber and red cells —
   it is the one knob that trades reassurance against scannability. */
.board-view { --board-ok-strength: 62%; }
.board-ok {
  display: flex; padding: 5px; line-height: 1; border-radius: 6px;
  transition: box-shadow .18s var(--ease-entrance), transform .18s var(--ease-entrance);
  color: color-mix(in srgb, var(--board-normal) var(--board-ok-strength), transparent);
}
.board-chip {
  min-width: 34px; padding: 5px 8px; border-radius: 6px; border: 1px solid transparent;
  transition: box-shadow .18s var(--ease-entrance), transform .18s var(--ease-entrance), filter .15s;
  font-family: var(--board-font-data); font-size: 12px; font-weight: 700; line-height: 1.2;
}
.board-chip.caution {
  background: var(--board-caution-bg); color: var(--board-caution);
  border-color: color-mix(in srgb, var(--board-caution) 40%, transparent);
}
.board-chip.warning { background: var(--board-warning-bg); color: var(--board-warning); border-color: var(--board-warning); }

/* ---- expanded ---------------------------------------------------------- */
/* The panel opens by growing, not by appearing — `[data-disclosure]` in motion.css
   owns that mechanism, and the Messages hub uses the same one. */

/* The spine drops from the centre of the chevron that opened the row: 16px of row
   padding plus half of the 18px twisty column. The detail visibly hangs off the
   control you pressed instead of being indented by an arbitrary amount. */
.board-detail-inner {
  margin-left: 25px; border-left: 1px solid var(--board-line-strong);
  padding: 2px 16px 15px 16px;
  display: flex; flex-direction: column; gap: 5px;
}

/* The contents settle in behind the opening box rather than arriving with it —
   the same relationship the workspace cards have to their slot. */
.is-open .board-issue,
.is-open .board-issue-none,
.is-open .board-open-flight {
  animation: motionSettle var(--dur-fast) var(--ease-entrance) both;
  animation-delay: calc(70ms + var(--motion-index, 0) * var(--stagger-step));
}

/* A lit cell in the row and an issue in the panel are the same fact written
   twice. Pointing at the sentence rings the gate it came from, so the board stops
   being a grid plus a list and reads as one object. `currentColor` is the chip's
   own severity, so the ring is always the colour of the thing it is pointing at. */
.board-row-wrap:has(.board-issue[data-tab=Aircraft]:is(:hover, :focus-within)) .board-cell[data-tab=Aircraft] > *,
.board-row-wrap:has(.board-issue[data-tab=Crew]:is(:hover, :focus-within)) .board-cell[data-tab=Crew] > *,
.board-row-wrap:has(.board-issue[data-tab=Fuel]:is(:hover, :focus-within)) .board-cell[data-tab=Fuel] > *,
.board-row-wrap:has(.board-issue[data-tab=Catering]:is(:hover, :focus-within)) .board-cell[data-tab=Catering] > *,
.board-row-wrap:has(.board-issue[data-tab=Passengers]:is(:hover, :focus-within)) .board-cell[data-tab=Passengers] > * {
  box-shadow: 0 0 0 3px color-mix(in srgb, currentColor 20%, transparent);
  transform: scale(1.07);
}

.board-issue {
  display: flex; align-items: center; gap: 12px; padding: 10px 12px;
  border-radius: 7px; background: var(--board-raised); border: 1px solid var(--board-line);
}
.board-issue.is-target { border-color: var(--muted); }
.board-issue.warning .board-lamp { background: var(--board-warning); }
.board-issue.caution .board-lamp { background: var(--board-caution); }
.board-issue-text { min-width: 0; }
.board-issue-text strong { display: block; font-size: 12.5px; font-weight: 600; }
.board-issue-text small { display: block; color: var(--muted); font-size: 11.5px; margin-top: 2px; }

.board-issue-go {
  margin-left: auto; flex: none; display: flex; align-items: center; gap: 8px;
  padding: 6px 11px; border-radius: 6px; font-size: 11.5px; font-weight: 500;
  background: var(--board-surface); border: 1px solid var(--board-line-strong);
}
.board-issue-tab {
  font-family: var(--board-font-data); font-size: 9.5px; letter-spacing: .06em;
  text-transform: uppercase; color: var(--board-dim);
}
.board-issue-go:hover .board-issue-tab { color: inherit; opacity: .7; }

.board-issue-none {
  display: flex; align-items: center; gap: 9px; margin: 0;
  padding: 10px 12px; font-size: 12.5px; color: var(--muted);
}
.board-issue-none .app-icon { color: var(--board-normal); }

.board-open-flight {
  align-self: flex-start; display: flex; align-items: center; gap: 7px;
  margin-top: 6px; padding: 7px 12px; border-radius: 6px;
  font-size: 12px; font-weight: 500; color: var(--ink);
  background: var(--board-surface); border: 1px solid var(--board-line-strong);
  transition: background .15s, color .15s, border-color .15s;
}
.board-open-flight .app-icon { color: var(--board-dimmer); transition: color .15s; }
.board-open-flight:hover .app-icon { color: inherit; }

/* ---- empty / footer ---------------------------------------------------- */
.board-empty { padding: 48px 20px; text-align: center; color: var(--muted); }
.board-empty .app-icon { color: var(--board-dimmer); }
.board-empty h2 { margin: 12px 0 4px; font-size: 15px; font-weight: 600; color: var(--ink); }
.board-empty p { margin: 0; font-size: 12.5px; }
.board-clear {
  margin-top: 14px; padding: 8px 15px; border-radius: 7px; font-size: 12px; font-weight: 500;
  border: 1px solid var(--board-line-strong); background: var(--board-raised);
}

.board-foot { display: flex; align-items: center; gap: 10px; padding: 13px 4px 0; font-size: 10.5px; color: var(--board-dim); }
.board-foot .live-dot { margin-right: 5px; }

/* ---- narrow ------------------------------------------------------------ */
@media (max-width: 1040px) {
  .board-head-row { display: none; }
  .board-columns { display: block; }
  .board-row { display: flex; flex-wrap: wrap; align-items: center; gap: 9px 10px; }
  .board-ident { display: flex; flex-wrap: wrap; align-items: center; gap: 9px 10px; width: 100%; margin: 0; padding: 0; }
  .board-rule { display: none; }
  .board-type { flex: 1 1 100%; order: 9; }
  .board-state { margin-left: auto; }
  .board-cell { display: contents; }
  .board-go-cell { margin-left: auto; }
  .board-nil { display: none; }
  /* Without a column header to name it, each chip has to name itself. */
  .board-chip::after {
    content: " " attr(data-short);
    font-family: Inter, system-ui, sans-serif; font-weight: 600; font-size: 10px; letter-spacing: .04em;
  }
}
:root {
   font-family: Inter, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
   color: #2a2a2a;
   background: #f8f8f8;
   font-synthesis: none;
   text-rendering: optimizeLegibility;
   --navy: #292929;
   --blue: #6e6e6e;
   --ink: #2a2a2a;
   --muted: #7f7f7f;
   --muted-strong: #717171;
   --line: #eaeaea;
   --green: #147c5a;
   --amber: #b06200;
   --radius: 10px;
   --ease-standard: cubic-bezier(.2, .7, .2, 1);
   --bs-primary: #6e6e6e;
   --bs-primary-rgb: 18, 102, 236;
   --bs-body-font-family: Inter, system-ui, sans-serif;
   --bs-body-color: #2a2a2a;
   --bs-border-color: #6e6e6e;
   --bs-border-radius: 6px
}

* {
   box-sizing: border-box
}

body {
   margin: 0;
   min-width: 360px;
   font-family: Inter, system-ui, sans-serif;
   font-size: 14px;
   color: var(--ink);
   background: #f8f8f8
}

button,
input,
textarea {
   font: inherit
}

button {
   cursor: pointer;
   color: inherit;
   border: 0;
   background: none
}

button:disabled {
   cursor: not-allowed;
   opacity: .55
}

button,
a,
input,
textarea {
   -webkit-tap-highlight-color: transparent
}

button:focus-visible,
a:focus-visible,
input:focus-visible,
textarea:focus-visible {
   outline: 3px solid #a4a4a4;
   outline-offset: 3px
}

a {
   color: var(--blue);
   text-decoration: none
}

.app-icon {
   display: inline-flex;
   align-items: center;
   justify-content: center;
   width: var(--icon-size);
   height: var(--icon-size);
   font-size: var(--icon-size);
   line-height: 1;
   flex-shrink: 0;
   vertical-align: middle
}

h1,
h2,
h3,
h4,
p {
   margin: 0
}

h1,
h2,
h3,
h4 {
   letter-spacing: -.035em
}

strong {
   font-weight: 600
}

.app-header {
   height: 76px;
   background: black;
   color: white;
   display: flex;
   align-items: center;
   padding: 0 28px;
   gap: 44px;
   position: relative;
   z-index: 10;
   box-shadow: 0 1px 6px #28282820
}

.brand {
   height: 58px
}

.brand-logo {
   display: block;
   width: 166px;
   height: auto;
   max-height: 48px;
   object-fit: contain;
   object-position: left center;
   transition: opacity .15s var(--ease-standard)
}

.brand:hover .brand-logo {
   opacity: .9
}

.global-nav {
   display: flex;
   gap: 10px;
   height: 100%;
   align-items: stretch
}

.global-nav>button {
   display: flex;
   align-items: center;
   gap: 9px;
   color: #6e6e6e;
   padding: 0 15px;
   position: relative;
   font-weight: 500
}

.global-nav>button.active {
   color: white
}

.global-nav>button.active:after {
   content: '';
   position: absolute;
   bottom: 0;
   left: 12px;
   right: 12px;
   height: 3px;
   border-radius: 4px 4px 0 0;
   background: #a3a3a3
}

.global-nav>button:hover {
   color: white;
   background: #ffffff08
}

.nav-count {
   border-radius: 5px;
   background: #1f6fd0;
   color: #fff;
   min-width: 19px;
   height: 19px;
   padding: 0 5px;
   font-size: 11px;
   font-weight: 700;
   display: grid;
   place-items: center
}

.header-end {
   margin-left: auto;
   display: flex;
   gap: 14px;
   align-items: center
}

.demo-label {
   font-size: 11px;
   color: #6e6e6e;
   border: 1px solid #ffffff20;
   border-radius: 4px;
   padding: 4px 7px;
   white-space: nowrap
}

.header-icon {
   color: #6e6e6e;
   position: relative;
   padding: 8px
}

.notification-dot {
   width: 6px;
   height: 6px;
   position: absolute;
   right: 7px;
   top: 7px;
   background: #a5a5a5;
   border-radius: 50%;
   border: 1px solid var(--navy);
   animation: notificationPulse 2.4s ease-in-out infinite
}

.header-divider {
   height: 29px;
   width: 1px;
   background: #ffffff20;
   margin: 0 6px
}

.user-label {
   display: flex;
   flex-direction: column;
   gap: 3px;
   font-size: 12px
}

.user-label strong {
   font-size: 13px
}

.user-label>span {
   color: #6e6e6e
}

.avatar {
   width: 34px;
   height: 34px;
   background: linear-gradient(145deg, #efefef, #e7e7e7);
   border: 1px solid #e6e6e6;
   color: #606060;
   font-size: 11px;
   font-weight: 600;
   border-radius: 50%;
   display: inline-flex;
   align-items: center;
   justify-content: center;
   flex-shrink: 0
}

.avatar.large {
   width: 72px;
   height: 72px;
   font-size: 23px
}

.header-end .avatar {
   background: #f1f1f1;
   color: #434343;
   width: 35px;
   height: 35px
}

.dashboard-layout {
   display: grid;
   grid-template-columns: 345px minmax(0, 1fr);
   height: calc(100dvh - 76px)
}

.flight-inbox {
   background: #fcfcfc;
   border-right: 1px solid #e3e3e3;
   display: flex;
   flex-direction: column;
   min-height: 0
}

.inbox-top {
   display: flex;
   justify-content: space-between;
   align-items: center;
   padding: 25px 20px 21px
}

.inbox-top h1 {
   font-size: 26px;
   font-weight: 700
}

.inbox-top p {
   color: var(--muted);
   font-size: 12px;
   margin-top: 4px
}

.inbox-top p>span {
   padding: 0 4px
}

.app-button {
   display: inline-flex;
   align-items: center;
   justify-content: center;
   gap: 8px;
   min-height: 38px;
   padding: 9px 14px;
   font-size: 13px;
   font-weight: 600;
   border-radius: 6px;
   white-space: nowrap;
   border: 1px solid transparent;
   transition: background .15s var(--ease-standard), border-color .15s var(--ease-standard), box-shadow .15s var(--ease-standard), transform .12s var(--ease-standard)
}

.app-button:active,
.soft-view-button:active,
.square-button:active {
   transform: scale(.975)
}

.app-button.primary {
   background: var(--blue);
   color: white;
   box-shadow: 0 2px 3px #5d5d5d1a;
   border-color: #656565
}

.app-button.secondary {
   background: white;
   border-color: #6e6e6e;
   color: #5e5e5e;
   box-shadow: 0 1px 2px #2a2a2a06
}

.app-button.small {
   min-height: 33px;
   padding: 7px 10px;
   font-size: 12px
}

.app-button.small .app-icon {
   --icon-size: 16px !important
}

.app-button.block {
   width: 100%;
   margin-top: 15px
}

.search-row {
   display: flex;
   gap: 8px;
   margin: 0 20px 13px
}

.search-box {
   min-width: 0;
   display: flex;
   align-items: center;
   gap: 9px;
   background: white;
   border: 1px solid #e2e2e2;
   border-radius: 6px;
   padding: 9px 10px;
   flex: 1;
   color: #6e6e6e
}

.search-box input {
   width: 100%;
   border: 0;
   outline: none;
   background: transparent;
   min-width: 0;
   font-size: 12px;
   color: var(--ink)
}

.search-box:focus-within {
   border-color: #6e6e6e;
   box-shadow: 0 0 0 2px #6e6e6e12
}

.search-box input:focus-visible {
   outline: 0
}

.search-box input::placeholder {
   color: #6e6e6e
}

.search-box .app-icon {
   --icon-size: 17px !important
}

.square-button {
   width: 36px;
   height: 36px;
   display: inline-flex;
   align-items: center;
   justify-content: center;
   flex-shrink: 0;
   background: white;
   border: 1px solid #e2e2e2;
   border-radius: 6px;
   color: #6e6e6e
}

.square-button.selected {
   background: #f1f1f1;
   color: var(--blue);
   border-color: #6e6e6e
}

.filter-tabs {
   display: flex;
   padding: 3px;
   background: #f2f2f2;
   border-radius: 6px;
   margin: 0 20px 6px;
   gap: 3px
}

.filter-tabs button {
   flex: 1;
   border-radius: 4px;
   padding: 7px 3px;
   font-size: 12px;
   font-weight: 500;
   color: #6e6e6e;
   display: flex;
   align-items: center;
   justify-content: center;
   gap: 7px
}

.filter-tabs button.selected {
   color: var(--blue);
   background: white;
   box-shadow: 0 1px 4px #2e2e2e14
}

.filter-tabs button span {
   font-size: 10px;
   background: #f3f3f3;
   border-radius: 4px;
   padding: 0 5px;
   line-height: 17px
}

.flight-groups {
   overflow: auto;
   padding: 3px 12px 18px;
   flex: 1;
   scrollbar-width: thin;
   scrollbar-color: #6e6e6e transparent
}

.flight-group {
   margin-top: 18px
}

.flight-group h2 {
   display: flex;
   align-items: center;
   gap: 8px;
   font-size: 13px;
   font-weight: 600;
   padding: 0 8px;
   margin-bottom: 10px;
   letter-spacing: -.02em
}

.group-icon {
   display: inline-flex;
   align-items: center;
   justify-content: center;
   width: 22px;
   height: 22px;
   border-radius: 50%
}

.group-icon.amber {
   background: #fff0db;
   color: #b46214
}

.group-icon.green {
   background: #e0f2eb;
   color: #248164
}

.group-icon.blue {
   background: #eeeeee;
   color: #6e6e6e
}

.group-count {
   font-size: 11px;
   color: #6e6e6e;
   margin-left: auto;
   font-weight: 500
}

.flight-row {
   width: 100%;
   text-align: left;
   border: 1px solid var(--line);
   background: white;
   padding: 14px 13px;
   border-radius: 7px;
   margin-bottom: 7px;
   position: relative;
   transition: background .15s, border-color .15s, transform .15s var(--ease-standard), box-shadow .15s;
   overflow: hidden;
   animation: motionSettle var(--dur-fast) var(--ease-entrance) both;
   animation-delay: calc(min(var(--motion-index, 0), 10) * var(--stagger-row, 60ms))
}

.flight-row.is-selected {
   background: linear-gradient(120deg, #f3f3f3, #f9f9f9);
   border-color: #6e6e6e;
   box-shadow: 0 1px 3px #6e6e6e15
}

.flight-row.is-selected:before {
   content: '';
   position: absolute;
   left: 0;
   top: 0;
   bottom: 0;
   width: 3px;
   background: var(--blue);
   animation: selectedRailIn var(--dur-fast) var(--ease-entrance) both
}

.flight-row-top {
   display: flex;
   align-items: center;
   gap: 11px;
   white-space: nowrap;
   font-size: 12px
}

.flight-time {
   font-weight: 600;
   font-size: 12px;
   width: 65px;
   flex-shrink: 0
}

.mini-route {
   display: flex;
   align-items: center;
   gap: 8px;
   font-size: 13px;
   font-weight: 700;
   letter-spacing: -.03em
}

.mini-route .app-icon {
   color: #6e6e6e
}

.flight-row-top>.app-icon:last-child {
   margin-left: auto;
   color: #6e6e6e
}

.flight-row-meta {
   display: flex;
   gap: 6px;
   align-items: center;
   font-size: 11px;
   color: #6e6e6e;
   padding-top: 7px
}

.flight-row-meta strong {
   font-weight: 500;
   color: #666666
}

.direction-label {
   margin-left: auto;
   font-size: 10px;
   color: #6e6e6e
}

.flight-row-bottom {
   display: flex;
   align-items: center;
   justify-content: space-between;
   gap: 7px;
   margin-top: 11px
}

.flight-reason {
   color: #6e6e6e;
   font-size: 10px;
   white-space: nowrap
}

.status-badge {
   display: inline-flex;
   align-items: center;
   gap: 5px;
   line-height: 1.3;
   font-size: 11px;
   font-weight: 500;
   padding: 4px 7px;
   border-radius: 5px;
   white-space: nowrap;
   animation: badgeIn var(--dur-fast) var(--ease-entrance) both
}

.status-badge.green {
   color: #147653;
   background: #eaf6f0
}

.status-badge.amber {
   color: #9c5c00;
   background: #fff0d9
}

.status-badge.red {
   background: #fdeceb;
   color: #a32b23
}

.status-badge.blue {
   color: #656565;
   background: #f1f1f1
}

.status-badge.gray {
   color: #6e6e6e;
   background: #f3f3f3
}

.inbox-footer {
   border-top: 1px solid var(--line);
   display: flex;
   justify-content: space-between;
   padding: 15px 20px;
   color: #6e6e6e;
   font-size: 10px;
   background: #fcfcfc
}

.inbox-footer>span:last-child {
   display: flex;
   align-items: center;
   gap: 5px
}

.live-dot {
   width: 5px;
   height: 5px;
   border-radius: 50%;
   background: #3faa84
}

.workspace {
   min-width: 0;
   overflow: auto;
   scrollbar-width: thin;
   scrollbar-color: #6e6e6e transparent;
   background: #f8f8f8
}

.flight-header {
   display: flex;
   align-items: center;
   justify-content: space-between;
   gap: 20px;
   padding: 30px 32px 26px;
   background: white
}

.route-heading {
   display: flex;
   align-items: center;
   gap: 15px
}

.flight-symbol {
   height: 56px;
   width: 56px;
   display: grid;
   place-items: center;
   background: #f4f4f4;
   color: var(--blue);
   border: 1px solid #eeeeee;
   border-radius: 9px
}

.eyebrow {
   color: #6e6e6e;
   font-size: 10px;
   font-weight: 600;
   letter-spacing: .09em
}

.route-heading h2 {
   font-size: 29px;
   font-weight: 700;
   display: flex;
   gap: 15px;
   align-items: center;
   white-space: nowrap;
   margin: 3px 0 6px
}

.route-heading h2 .app-icon {
   color: #6e6e6e
}

.route-heading p {
   font-size: 11px;
   color: #6e6e6e;
   display: flex;
   gap: 8px;
   align-items: center;
   white-space: nowrap
}

.route-heading p strong {
   color: #505050
}

.flight-header-right {
   display: flex;
   align-items: center;
   gap: 19px
}

/* Keep time and duration together, with the divider before flight status. */
.schedule {
   display: flex;
   gap: 26px;
   border-right: 1px solid var(--line);
   padding-right: 22px;
   margin-right: 4px;
   white-space: nowrap
}

.schedule>div {
   gap: 3px
}

.schedule .schedule-label {
   font-size: 12px;
   color: #6e6e6e
}

.schedule strong {
   font-size: 15px;
   letter-spacing: -.035em
}

.schedule small {
   font-size: 10px;
   font-weight: 500;
   color: #6e6e6e
}

.flight-header-right>.status-badge {
   font-size: 12px;
   padding: 7px 9px
}

.button-count {
   background: #ededed;
   color: var(--blue);
   font-size: 10px;
   border-radius: 4px;
   padding: 1px 5px
}

.workspace-tabs {
   display: flex;
   align-items: center;
   gap: 26px;
   padding: 0 32px;
   background: white;
   border-top: 1px solid #f4f4f4;
   border-bottom: 1px solid var(--line);
   position: sticky;
   top: 0;
   z-index: 5
}

.workspace-tabs button {
   position: relative;
   padding: 17px 2px;
   display: flex;
   align-items: center;
   gap: 8px;
   font-weight: 500;
   font-size: 13px;
   color: #6e6e6e;
   white-space: nowrap
}

.workspace-tabs button .app-icon {
   --icon-size: 17px !important
}

.workspace-tabs button.active {
   color: var(--blue);
   font-weight: 600
}

.workspace-tabs button.active:after {
   content: '';
   height: 3px;
   background: var(--blue);
   position: absolute;
   left: 0;
   right: 0;
   bottom: 0;
   border-radius: 3px 3px 0 0
}

.tab-dot {
   width: 5px;
   height: 5px;
   background: #dba456;
   border-radius: 50%;
   margin-left: -3px
}

.workspace-content {
   padding: 26px 32px;
   display: flex;
   flex-direction: column;
   gap: 20px;
   max-width: 1500px;
   margin: 0 auto
}

.attention-card {
   background: linear-gradient(115deg, #fff9ef, #fffbf5);
   border: 1px solid #f1dab4;
   border-radius: var(--radius);
   padding: 18px;
   animation: surfaceEnter var(--dur-base) var(--ease-entrance) both
}

.attention-heading {
   display: flex;
   align-items: center;
   gap: 11px;
   margin-bottom: 15px
}

.attention-symbol {
   color: #b56e1c;
   width: 34px;
   height: 34px;
   display: grid;
   place-items: center;
   background: #fff0d7;
   border-radius: 50%
}

.attention-heading h3 {
   font-size: 15px;
   font-weight: 600;
   color: #78491a;
   letter-spacing: -.025em
}

.attention-heading p {
   font-size: 11px;
   color: #a68c6a;
   margin-top: 4px
}

.attention-items {
   display: flex;
   flex-direction: column;
   gap: 8px
}

.attention-items>button {
   display: flex;
   align-items: center;
   gap: 12px;
   background: #ffffffde;
   border: 1px solid #f0e6d6;
   border-radius: 6px;
   text-align: left;
   padding: 12px 14px;
   width: 100%;
   transition: background .15s, transform .15s var(--ease-standard)
}

.attention-items>button>.app-icon:first-child {
   color: #be842d
}

.attention-items>button>.app-icon:last-child {
   color: #c2a580
}

.attention-items>button>div {
   display: flex;
   flex-direction: column;
   gap: 4px;
   flex: 1
}

.attention-items strong {
   font-size: 12px;
   color: #624b30;
   font-weight: 600
}

.attention-items div span {
   font-size: 11px;
   color: #9e8e79
}

.inline-action {
   font-size: 11px;
   color: var(--blue);
   font-weight: 500
}

.attention-items .inline-action {
   border: 1px solid #e3e3e3;
   border-radius: 4px;
   padding: 5px 10px;
   background: #fbfbfb;
   white-space: nowrap
}

.surface-card {
   background: white;
   border: 1px solid var(--line);
   border-radius: var(--radius);
   box-shadow: 0 2px 3px #2c2c2c02;
   overflow: hidden;
   animation: surfaceEnter var(--dur-slow) var(--ease-entrance) both
}

.card-heading {
   display: flex;
   align-items: center;
   gap: 10px;
   padding: 18px 20px
}

.card-heading-icon {
   color: var(--blue);
   background: #f4f4f4;
   width: 31px;
   height: 31px;
   display: grid;
   place-items: center;
   border-radius: 6px
}

.card-heading-icon .app-icon {
   --icon-size: 18px !important
}

.card-heading h3 {
   font-size: 14px;
   font-weight: 600;
   letter-spacing: -.025em
}

.card-heading p {
   font-size: 11px;
   color: #6e6e6e;
   margin-top: 3px
}

.card-heading-action {
   margin-left: auto
}

.text-button {
   display: inline-flex;
   align-items: center;
   justify-content: center;
   gap: 6px;
   padding: 0;
   font-size: 11px;
   font-weight: 500;
   color: var(--blue);
   white-space: nowrap
}

.soft-view-button {
   display: inline-flex;
   align-items: center;
   justify-content: center;
   gap: 7px;
   padding: 7px 10px;
   border: 1px solid #e6e6e6;
   border-radius: 6px;
   background: #f4f4f4;
   color: #696969;
   font-size: 11px;
   font-weight: 600;
   white-space: nowrap;
   transition: background .15s, border-color .15s, color .15s, transform .12s var(--ease-standard)
}

.readiness-table {
   padding: 0 20px 14px
}

.readiness-row {
   display: grid;
   grid-template-columns: 140px minmax(0, 1fr) 145px 15px;
   align-items: center;
   gap: 14px;
   text-align: left;
   width: 100%;
   padding: 14px 9px;
   border-top: 1px solid #f1f1f1;
   font-size: 12px;
   transition: background .15s
}

.readiness-category {
   display: flex;
   align-items: center;
   gap: 11px
}

.readiness-category .app-icon {
   --icon-size: 18px !important;
   color: #6e6e6e
}

.readiness-detail {
   color: #6e6e6e;
   font-size: 12px;
   overflow: hidden;
   text-overflow: ellipsis;
   white-space: nowrap
}

.readiness-row>.status-badge {
   justify-self: start
}

.readiness-row>.app-icon {
   color: #6e6e6e
}

.two-column {
   display: grid;
   grid-template-columns: 1fr 1fr;
   gap: 20px
}

.people-list {
   padding: 0 18px 8px
}

.person-row {
   width: 100%;
   display: flex;
   align-items: center;
   gap: 10px;
   padding: 12px 0;
   text-align: left;
   border-top: 1px solid #f1f1f1
}

.person-name {
   display: flex;
   flex-direction: column;
   gap: 3px;
   min-width: 0;
   flex: 1
}

.person-name strong {
   font-size: 11px;
   letter-spacing: -.02em;
   display: flex;
   align-items: center;
   gap: 6px
}

.person-name>span {
   font-size: 10px;
   color: #6e6e6e
}

.person-row>.status-badge {
   font-size: 10px;
   background: transparent;
   padding: 2px 0;
   gap: 4px
}

.person-row .status-badge .app-icon {
   --icon-size: 12px !important
}

.person-row>.app-icon {
   color: #6e6e6e
}

.lead-label {
   font-size: 9px;
   font-weight: 500;
   color: #6e6e6e;
   background: #f2f2f2;
   border-radius: 3px;
   padding: 2px 4px
}

.card-footer-action {
   width: 100%;
   display: flex;
   align-items: center;
   gap: 8px;
   color: #6e6e6e;
   font-size: 11px;
   border-top: 1px solid #f1f1f1;
   background: #fdfdfd;
   padding: 12px 20px
}

.card-footer-action>.app-icon:last-child {
   margin-left: auto
}

.activity-strip {
   display: flex;
   align-items: center;
   gap: 10px;
   padding: 12px 15px;
   background: #f3f3f3;
   border: 1px solid #e6e6e6;
   border-radius: 7px;
   font-size: 11px;
   text-align: left;
   color: #6e6e6e
}

.activity-strip strong {
   color: #646464;
   font-size: 11px;
   white-space: nowrap
}

.activity-strip>.app-icon {
   color: #6e6e6e
}

.activity-strip>span:not(.time):not(.inline-action) {
   overflow: hidden;
   text-overflow: ellipsis;
   white-space: nowrap
}

.activity-strip .time {
   margin-left: auto;
   font-size: 10px;
   white-space: nowrap
}

.activity-strip .inline-action {
   margin-left: auto;
   white-space: nowrap
}

.workspace-footnote {
   display: flex;
   gap: 6px;
   align-items: center;
   font-size: 10px;
   color: #6e6e6e;
   padding: 0 3px
}

.workspace-footnote>span:last-child {
   margin-left: auto
}

.section-heading {
   display: flex;
   align-items: center;
   justify-content: space-between;
   gap: 16px;
   margin: 1px 0 0
}

.section-heading h3 {
   font-size: 23px;
   font-weight: 700
}

.section-heading p {
   font-size: 12px;
   color: #6e6e6e;
   margin-top: 5px
}

.ready-banner {
   display: flex;
   align-items: center;
   gap: 12px;
   background: #eef9f3;
   border: 1px solid #cdebdc;
   border-radius: 8px;
   padding: 18px;
   color: #328263;
   animation: surfaceEnter var(--dur-base) var(--ease-entrance) both
}

.ready-banner>div {
   display: flex;
   flex-direction: column;
   gap: 4px
}

.ready-banner strong {
   font-size: 13px
}

.ready-banner span {
   font-size: 11px;
   color: #74a08b
}

.expanded .person-row {
   padding: 20px 6px;
   gap: 15px
}

.expanded .person-name strong {
   font-size: 14px
}

.expanded .person-name>span {
   font-size: 12px
}

.expanded .person-row>.status-badge {
   font-size: 12px
}

.expanded .avatar {
   width: 40px;
   height: 40px;
   font-size: 12px
}

.expanded .person-row>.app-icon {
   margin-left: 20px
}

.note {
   display: flex;
   align-items: flex-start;
   gap: 9px;
   color: #6e6e6e;
   background: #f7f7f7;
   border: 1px solid #ececec;
   border-radius: 6px;
   padding: 13px;
   font-size: 12px;
   line-height: 1.7
}

.note .app-icon {
   margin-top: 2px
}

.aircraft-summary {
   display: flex;
   align-items: center;
   gap: 24px;
   background: white;
   border: 1px solid var(--line);
   border-radius: 10px;
   padding: 28px
}

.aircraft-large-icon {
   height: 86px;
   width: 110px;
   background: #f4f4f4;
   color: #6e6e6e;
   display: grid;
   place-items: center;
   border-radius: 10px
}

.aircraft-summary h3 {
   font-size: 23px;
   margin: 5px 0
}

.aircraft-summary p {
   color: #6e6e6e;
   font-size: 12px
}

.aircraft-summary>.status-badge {
   margin-left: auto
}

.itinerary {
   display: flex;
   align-items: center;
   justify-content: space-between;
   padding: 10px 22px 20px;
   color: #6e6e6e
}

.itinerary>div {
   display: flex;
   flex-direction: column;
   gap: 4px
}

.itinerary strong {
   font-size: 28px;
   color: var(--ink)
}

.itinerary>div>span:last-child {
   font-size: 11px;
   color: #6e6e6e
}

.details-list {
   padding: 0 22px;
   margin: 0 0 14px
}

.details-list>div {
   display: flex;
   align-items: flex-start;
   justify-content: space-between;
   gap: 18px;
   padding: 15px 0;
   border-bottom: 1px solid #f1f1f1;
   font-size: 12px
}

.details-list dt {
   font-weight: 400;
   color: #6e6e6e
}

.details-list dd {
   color: #656565;
   font-weight: 500;
   text-align: right;
   margin: 0;
   max-width: 65%
}

.catering-body {
   padding: 8px 23px 24px;
   gap: 35px
}

.catering-body h4,
.panel-form h4 {
   font-size: 13px;
   margin-bottom: 15px;
   font-weight: 600
}

.order-item {
   display: flex;
   gap: 12px;
   align-items: center;
   padding: 10px 0;
   font-size: 12px;
   color: #6e6e6e
}

.quantity {
   width: 23px;
   height: 23px;
   border-radius: 4px;
   background: #f4f4f4;
   display: grid;
   place-items: center;
   color: #6e6e6e;
   font-size: 11px;
   flex-shrink: 0
}

.timeline {
   padding: 8px 0
}

.timeline-item {
   display: flex;
   gap: 13px;
   position: relative;
   padding-bottom: 27px;
   color: #6e6e6e
}

.timeline-item:last-child {
   padding-bottom: 0
}

.timeline-item:not(:last-child):after {
   content: '';
   position: absolute;
   top: 24px;
   left: 11px;
   width: 1px;
   height: calc(100% - 24px);
   background: #e7e7e7
}

.timeline-marker {
   height: 24px;
   width: 24px;
   background: #f4f4f4;
   border: 1px solid #e7e7e7;
   border-radius: 50%;
   display: grid;
   place-items: center;
   flex-shrink: 0;
   position: relative;
   z-index: 1
}

.timeline-item.done .timeline-marker {
   color: #279174;
   background: #ebf7f1;
   border-color: #cce7d9
}

.timeline-item>div {
   display: flex;
   flex-direction: column;
   gap: 5px;
   padding-top: 3px
}

.timeline-item strong {
   font-size: 12px;
   color: #606060;
   font-weight: 500
}

.timeline-item>div>span {
   font-size: 11px;
   color: #6e6e6e
}

.fuel-progress {
   display: grid;
   grid-template-columns: repeat(4, 1fr);
   padding: 24px
}

.fuel-progress>div {
   position: relative;
   display: flex;
   flex-direction: column;
   align-items: center;
   gap: 5px;
   color: #6e6e6e
}

.fuel-progress>div:not(:last-child):after {
   content: '';
   height: 2px;
   background: #ededed;
   position: absolute;
   left: calc(50% + 21px);
   right: calc(-50% + 21px);
   top: 16px
}

.fuel-progress>div.complete:after {
   background: #b9decf
}

.fuel-progress>div>span {
   width: 33px;
   height: 33px;
   display: grid;
   place-items: center;
   border: 1px solid #e4e4e4;
   border-radius: 50%;
   background: #f5f5f5;
   margin-bottom: 3px;
   font-size: 13px
}

.fuel-progress>div.complete>span {
   background: #e6f5ed;
   color: #198560;
   border-color: #bbdfcf
}

.fuel-progress>div.current>span {
   background: #fff0d9;
   color: #b97620;
   border-color: #f2d3a5;
   box-shadow: 0 0 0 4px #fff9ee
}

/* `--muted`, not a hardcoded grey. #6e6e6e was written for the light card and
   never got a dark counterpart, so on the dark surface every label in this tracker
   sat at 3.70:1 — under AA, and the reason the step names read as unavailable even
   when their step was done. The token already carries a value per theme. */
.fuel-progress strong {
   font-size: 12px;
   font-weight: 500;
   color: var(--muted)
}

.fuel-progress small {
   font-size: 10px;
   color: var(--muted)
}

.fuel-details {
   display: grid;
   grid-template-columns: 1fr 1fr;
   gap: 17px 40px;
   padding: 4px 22px 23px;
   margin: 0
}

.fuel-details>div {
   display: flex;
   align-items: center;
   justify-content: space-between;
   gap: 12px;
   font-size: 12px
}

.fuel-details dt {
   color: #6e6e6e;
   font-weight: 400
}

.fuel-details dd {
   margin: 0;
   color: #6d6d6d
}

.fuel-numbers {
   display: grid;
   grid-template-columns: repeat(4, 1fr);
   margin: 0 22px;
   padding: 20px 0 17px;
   border-top: 1px solid var(--line)
}

.fuel-numbers>div {
   display: flex;
   flex-direction: column;
   gap: 9px;
   padding-left: 20px;
   border-left: 1px solid var(--line)
}

.fuel-numbers>div:first-child {
   border: 0;
   padding: 0
}

.fuel-numbers>div>span {
   font-size: 11px;
   color: #6e6e6e
}

.fuel-numbers strong {
   font-size: 20px;
   letter-spacing: -.04em
}

.fuel-numbers strong small {
   font-size: 12px;
   font-weight: 400;
   color: #6e6e6e
}

.fuel-numbers strong.total-figure {
   font-size: 24px
}

.delivery-note {
   display: flex;
   gap: 7px;
   align-items: center;
   padding: 0 22px;
   color: #389479;
   font-size: 11px
}

.amber-text {
   color: #b06d1e
}

.comments {
   padding: 19px 22px 22px;
   font-size: 11px;
   color: #6e6e6e
}

.comments p {
   font-size: 12px;
   background: #f9f9f9;
   border-radius: 5px;
   padding: 11px 13px;
   margin-top: 8px;
   color: #6e6e6e
}

.payment-summary {
   display: flex;
   align-items: center;
   gap: 30px;
   padding: 3px 22px 23px
}

.payment-summary>div {
   display: flex;
   flex-direction: column;
   gap: 6px
}

.payment-summary>div>span:not(.eyebrow) {
   font-size: 11px;
   color: #6e6e6e
}

.payment-summary>div>strong {
   font-size: 14px
}

.payment-summary .amount-due {
   margin-left: auto;
   text-align: right
}

.payment-summary .amount-due strong {
   font-size: 23px;
   letter-spacing: -.04em
}

.invoice-strip {
   border: 1px solid var(--line);
   border-radius: 8px;
   background: white;
   display: flex;
   align-items: center;
   gap: 13px;
   padding: 15px 20px;
   text-align: left
}

.invoice-strip:disabled {
   opacity: .8
}

.invoice-strip>span:nth-child(2) {
   display: flex;
   flex-direction: column;
   gap: 4px;
   flex: 1
}

.invoice-strip strong {
   font-size: 12px
}

.invoice-strip small {
   font-size: 11px;
   color: #6e6e6e
}

.soft-icon {
   width: 36px;
   height: 36px;
   border-radius: 7px;
   background: #f3f3f3;
   color: #6e6e6e;
   display: grid;
   place-items: center;
   flex-shrink: 0
}

/* All focused tasks share this fixed, top-layer panel; the grid stays two columns. */
.dynamic-drawer {
   position: fixed;
   inset: 0 0 0 auto;
   margin: 0;
   width: min(510px, 100vw);
   max-width: 100vw;
   height: 100dvh;
   max-height: 100dvh;
   border: 0;
   border-left: 1px solid #e4e4e4;
   padding: 0;
   color: var(--ink);
   background: white;
   z-index: 2000;
   box-shadow: -12px 0 55px #27272726;
   overflow: hidden
}

.dynamic-drawer[open] {
   display: flex;
   flex-direction: column;
   animation: slideIn var(--dur-slow) var(--ease-entrance)
}

.dynamic-drawer::backdrop {
   background: rgba(15, 34, 59, .22);
   backdrop-filter: blur(1px);
   animation: backdropIn var(--dur-base) ease
}

.dynamic-drawer.closing {
   animation: slideOut var(--dur-fast) var(--ease-exit) forwards
}

.dynamic-drawer.closing::backdrop {
   animation: backdropOut var(--dur-fast) ease forwards
}

.drawer-header {
   display: flex;
   align-items: center;
   gap: 12px;
   border-bottom: 1px solid var(--line);
   padding: 24px;
   min-height: 100px;
   flex-shrink: 0
}

.drawer-header h2 {
   font-size: 21px;
   font-weight: 700;
   letter-spacing: -.04em
}

.drawer-header p {
   font-size: 12px;
   color: #6e6e6e;
   margin-top: 6px
}

.drawer-close {
   margin-left: auto;
   width: 31px;
   height: 31px
}

.drawer-content {
   flex: 1;
   min-height: 0;
   overflow: auto
}

.panel-body {
   padding: 26px
}

.panel-intro {
   font-size: 13px;
   line-height: 1.7;
   color: #6e6e6e;
   margin: 0 0 22px
}

.panel-body>.people-list {
   padding: 0
}

.panel-body .person-row {
   padding: 17px 0;
   gap: 9px
}

.panel-body .person-name strong {
   font-size: 12px
}

.panel-body h3 {
   font-size: 22px;
   letter-spacing: -.04em;
   font-weight: 600
}

.panel-body .details-list {
   padding: 0;
   margin: 20px 0 26px
}

.panel-body .details-list>div {
   padding: 16px 0;
   font-size: 13px
}

.panel-body .details-list dd {
   color: #626262
}

.contact-hero {
   display: flex;
   align-items: center;
   flex-direction: column;
   gap: 10px;
   padding: 5px 0 18px
}

.contact-hero h3 {
   margin-top: 5px;
   font-size: 22px
}

.contact-hero p {
   color: #6e6e6e;
   font-size: 12px
}

.contact-hero .status-badge {
   margin: 2px 0
}

.form-field {
   display: block;
   margin: 0 0 18px;
   width: 100%;
   color: #6e6e6e;
   font-size: 12px;
   font-weight: 500
}

.form-field>.form-label {
   display: block;
   margin-bottom: 8px;
   color: #6e6e6e;
   font-size: 12px;
   font-weight: 500
}

/* A control looks like a control wherever it is. The custom select is listed
   beside `.form-field .form-control` rather than styled separately, because a
   standalone one — the Contacts hub puts a check-in select in a leg row with no
   field label — was falling through to Bootstrap's white input and rendering
   near-white text on white in the dark theme. Same rule, so they cannot drift. */
.form-field .form-control,
.custom-select-trigger {
   width: 100%;
   border: 1px solid #e3e3e3;
   border-radius: 6px;
   background: white;
   color: #4d4d4d;
   padding: 11px 12px;
   min-height: 41px;
   font-size: 13px;
   line-height: 1.5;
   resize: vertical;
   box-shadow: none;
   transition: border-color .15s var(--ease-standard), box-shadow .15s var(--ease-standard), background .15s
}

.form-field .form-control:focus,
.custom-select-trigger:focus {
   border-color: #6e6e6e;
   box-shadow: 0 0 0 3px #6e6e6e12
}

.form-field input::placeholder,
.form-field textarea::placeholder {
   color: #6e6e6e
}

.form-field input:read-only {
   background: #f8f8f8;
   color: #6e6e6e
}

.custom-select-control {
   position: relative
}

.custom-select-trigger {
   cursor: pointer;
   justify-content: space-between;
   gap: 12px
}

.custom-select-trigger .app-icon {
   margin-left: auto;
   color: #6e6e6e;
   transition: transform .18s var(--ease-standard)
}

.custom-select-control.show .custom-select-trigger .app-icon {
   transform: rotate(90deg)
}

.custom-select-menu {
   display: block;
   visibility: hidden;
   opacity: 0;
   transform: translateY(-5px) scale(.985);
   pointer-events: none;
   margin-top: 6px;
   padding: 6px;
   border: 1px solid #e4e4e4;
   border-radius: 7px;
   box-shadow: 0 12px 32px #3333331f;
   transition: opacity .16s var(--ease-standard), transform .16s var(--ease-standard), visibility 0s linear .16s;
   z-index: 2100
}

.custom-select-menu.show {
   visibility: visible;
   opacity: 1;
   transform: translateY(0) scale(1);
   pointer-events: auto;
   transition-delay: 0s
}

.custom-select-menu .dropdown-item {
   justify-content: space-between;
   gap: 10px;
   border-radius: 5px;
   padding: 9px 10px;
   color: #6a6a6a;
   font-size: 12px
}

.custom-select-menu .dropdown-item:focus {
   background: #f5f5f5;
   color: #5f5f5f
}

.custom-select-menu .dropdown-item.active {
   background: #f1f1f1;
   color: #606060;
   font-weight: 600
}

.form-grid {
   display: grid;
   grid-template-columns: 1fr 1fr;
   gap: 16px
}

.field-hint {
   font-size: 11px;
   color: #6e6e6e;
   line-height: 1.7;
   margin: -3px 0 18px
}

.form-actions {
   display: flex;
   justify-content: flex-end;
   gap: 9px;
   border-top: 1px solid var(--line);
   padding-top: 20px;
   margin-top: 22px
}

.panel-flight-summary {
   display: flex;
   align-items: center;
   gap: 13px;
   padding: 16px;
   background: #f8f8f8;
   border: 1px solid #ececec;
   border-radius: 8px;
   margin-bottom: 25px;
   color: #6e6e6e
}

.panel-flight-summary>div {
   display: flex;
   flex-direction: column;
   gap: 4px;
   flex: 1
}

.panel-flight-summary strong {
   font-size: 14px;
   color: #565656
}

.panel-flight-summary span {
   font-size: 11px;
   color: #6e6e6e
}

.panel-body .order-item {
   padding: 9px 0
}

.panel-form>.form-field {
   margin-top: 15px
}

.review-total {
   display: flex;
   align-items: center;
   justify-content: space-between;
   border-top: 1px solid var(--line);
   border-bottom: 1px solid var(--line);
   padding: 22px 0;
   margin: 24px 0;
   color: #6e6e6e;
   font-size: 13px
}

.review-total strong {
   font-size: 27px;
   color: #464646;
   letter-spacing: -.06em
}

.payment-review-icon {
   height: 58px;
   width: 58px;
   border-radius: 12px;
   display: grid;
   place-items: center;
   background: #f4f4f4;
   color: #6e6e6e;
   margin-bottom: 20px
}

.saved-payment {
   display: flex;
   align-items: center;
   gap: 10px;
   border: 1px solid var(--line);
   border-radius: 6px;
   padding: 15px;
   font-size: 13px;
   color: #6c6c6c
}

.saved-payment>.status-badge {
   margin-left: auto
}

.invoice-heading {
   display: flex;
   align-items: center;
   flex-direction: column;
   gap: 13px;
   margin: 10px 0 30px
}

.notification-item {
   display: flex;
   align-items: center;
   gap: 12px;
   width: 100%;
   text-align: left;
   border: 1px solid var(--line);
   padding: 15px;
   margin-bottom: 12px;
   border-radius: 7px
}

.notification-item>span:nth-child(2) {
   display: flex;
   flex-direction: column;
   gap: 7px;
   flex: 1
}

.notification-item strong {
   font-size: 13px
}

.notification-item small {
   font-size: 11px;
   line-height: 1.5;
   color: #6e6e6e
}

.notification-item .soft-icon.amber {
   color: #b7853c;
   background: #fff6e8
}

.conversation-layout {
   height: 100%;
   display: flex;
   flex-direction: column;
   min-height: 0
}

.conversation-audience {
   display: flex;
   align-items: center;
   gap: 12px;
   padding: 20px 24px
}

.conversation-audience>div {
   display: flex;
   flex-direction: column;
   gap: 4px
}

.conversation-audience strong {
   font-size: 14px
}

.conversation-audience>div>span {
   font-size: 11px;
   color: #6e6e6e
}

.conversation-tabs {
   display: flex;
   gap: 27px;
   padding: 0 24px;
   border-bottom: 1px solid var(--line)
}

.conversation-tabs button {
   display: flex;
   align-items: center;
   gap: 7px;
   padding: 13px 0;
   font-size: 12px;
   color: #6e6e6e;
   position: relative
}

.conversation-tabs button.active {
   color: var(--blue)
}

.conversation-tabs button.active:after {
   content: '';
   height: 3px;
   background: var(--blue);
   border-radius: 3px 3px 0 0;
   bottom: 0;
   left: 0;
   right: 0;
   position: absolute
}

.conversation-scroll {
   overflow: auto;
   flex: 1;
   min-height: 0;
   padding: 18px 24px 25px;
   scrollbar-width: thin
}

.chat-date {
   font-size: 10px;
   color: #6e6e6e;
   text-align: center;
   margin: 4px 0 27px
}

.chat-message {
   display: flex;
   align-items: flex-start;
   gap: 10px;
   margin-bottom: 24px
}

.chat-message .avatar {
   width: 31px;
   height: 31px;
   font-size: 10px
}

.chat-message-content {
   flex: 1;
   min-width: 0
}

.chat-byline {
   display: flex;
   align-items: center;
   justify-content: space-between;
   gap: 8px;
   margin: 2px 0
}

.chat-byline strong {
   font-size: 12px;
   font-weight: 600
}

.chat-byline time {
   font-size: 10px;
   color: #6e6e6e;
   white-space: nowrap
}

.chat-role {
   font-size: 10px;
   color: #6e6e6e
}

.chat-message-content>p {
   background: #f6f6f6;
   border: 1px solid #eeeeee;
   border-radius: 0 9px 9px 9px;
   margin: 8px 0 0;
   padding: 12px 13px;
   color: #676767;
   font-size: 13px;
   line-height: 1.7;
   white-space: pre-wrap;
   overflow-wrap: anywhere
}

.chat-message.own .chat-message-content>p {
   background: #f3f3f3;
   border-color: #6e6e6e;
   color: #5e5e5e
}

.chat-order-card {
   display: flex;
   align-items: center;
   gap: 12px;
   border: 1px solid #e6e6e6;
   padding: 16px;
   background: #fdfdfd;
   border-radius: 8px;
   width: calc(100% - 41px);
   margin-left: 41px;
   text-align: left;
   color: #6e6e6e
}

.chat-order-card>span {
   display: flex;
   flex-direction: column;
   gap: 6px;
   flex: 1
}

.chat-order-card strong {
   font-size: 12px;
   color: #5f5f5f
}

.chat-order-card small {
   font-size: 11px;
   color: #6e6e6e
}

.chat-composer {
   padding: 18px 24px;
   border-top: 1px solid var(--line);
   background: white
}

.chat-composer>div {
   display: flex;
   gap: 10px;
   align-items: flex-end
}

.chat-composer textarea {
   width: 100%;
   resize: none;
   border: 1px solid #e5e5e5;
   border-radius: 6px;
   padding: 10px 12px;
   font-size: 12px;
   color: #606060;
   line-height: 1.5
}

.chat-composer textarea::placeholder {
   color: #6e6e6e
}

.chat-composer button {
   height: 40px;
   width: 40px;
   background: var(--blue);
   color: white;
   border-radius: 6px;
   flex-shrink: 0;
   display: grid;
   place-items: center
}

.chat-composer p {
   display: flex;
   align-items: center;
   gap: 5px;
   font-size: 10px;
   color: #6e6e6e;
   margin-top: 9px
}

.chat-composer p>span {
   margin-left: auto
}

.empty-state {
   display: flex;
   align-items: center;
   flex-direction: column;
   gap: 13px;
   text-align: center;
   padding: 40px 18px;
   color: #6e6e6e
}

.empty-state h3 {
   font-size: 17px;
   color: #6a6a6a
}

.empty-state p {
   font-size: 12px;
   line-height: 1.6;
   max-width: 280px
}

.toast-message {
   position: fixed;
   right: 24px;
   bottom: 24px;
   background: #3d3d3d;
   color: white;
   box-shadow: 0 8px 30px #2a2a2a26;
   border: 1px solid #606060;
   border-radius: 8px;
   padding: 13px 17px;
   z-index: 3000;
   display: flex;
   align-items: center;
   gap: 10px;
   font-size: 12px;
   max-width: calc(100vw - 32px);
   animation: toastIn var(--dur-base) var(--ease-entrance) both
}

.toast-message>.app-icon {
   color: #81dbb9
}

.toast-message button {
   padding: 0 0 0 12px;
   color: #6e6e6e
}

@keyframes slideIn {
   from {
      transform: translateX(100%)
   }

   to {
      transform: translateX(0)
   }
}

@keyframes slideOut {
   from {
      transform: translateX(0)
   }

   to {
      transform: translateX(100%)
   }
}

@keyframes backdropIn {
   from {
      opacity: 0
   }

   to {
      opacity: 1
   }
}

@keyframes backdropOut {
   from {
      opacity: 1
   }

   to {
      opacity: 0
   }
}

@keyframes toastIn {
   from {
      opacity: 0;
      transform: translate(8px, 8px)
   }

   to {
      opacity: 1;
      transform: translate(0)
   }
}

@keyframes fadeUp {
   from {
      opacity: 0;
      transform: translateY(4px)
   }

   to {
      opacity: 1;
      transform: translateY(0)
   }
}

@keyframes surfaceEnter {
   from {
      opacity: 0;
      transform: translateY(7px)
   }

   to {
      opacity: 1;
      transform: translateY(0)
   }
}

@keyframes selectedRailIn {
   from {
      transform: scaleY(0)
   }

   to {
      transform: scaleY(1)
   }
}

@keyframes badgeIn {
   from {
      opacity: 0;
      transform: scale(.94)
   }

   to {
      opacity: 1;
      transform: scale(1)
   }
}

@keyframes notificationPulse {

   0%,
   70%,
   100% {
      box-shadow: 0 0 0 0 #a5a5a500
   }

   82% {
      box-shadow: 0 0 0 4px #a5a5a524
   }
}

@media(min-width:1600px) {
   .dashboard-layout {
      grid-template-columns: 380px minmax(0, 1fr)
   }

   .flight-header {
      padding: 33px 42px
   }

   .workspace-tabs {
      padding: 0 42px;
      gap: 36px
   }

   .workspace-content {
      padding: 30px 42px
   }

   .inbox-top {
      padding: 28px 25px 23px
   }

   .search-row,
   .filter-tabs {
      margin-left: 25px;
      margin-right: 25px
   }

   .flight-groups {
      padding-left: 17px;
      padding-right: 17px
   }

   .flight-row {
      padding: 16px
   }

   .flight-row-top {
      gap: 17px
   }

   .mini-route {
      font-size: 14px
   }

   .person-name strong {
      font-size: 12px
   }

   .person-row>.status-badge {
      font-size: 11px
   }

   .readiness-row {
      padding-top: 17px;
      padding-bottom: 17px
   }
}

@media(max-width:1250px) {
   .app-header {
      gap: 25px;
      padding: 0 20px
   }

   .global-nav {
      gap: 0
   }

   .global-nav>button {
      padding: 0 10px
   }

   .header-end {
      gap: 10px
   }

   .demo-label {
      display: none
   }

   .dashboard-layout {
      grid-template-columns: 305px minmax(0, 1fr)
   }

   .flight-header {
      padding: 26px 22px;
      align-items: flex-start;
      flex-wrap: wrap
   }

   .flight-header-right {
      gap: 10px;
      flex-wrap: nowrap;
      justify-content: flex-end;
      max-width: none
   }

   .flight-header-right>.schedule {
      padding-right: 16px;
      text-align: left;
      margin: 0
   }

   .flight-header-right>.app-button {
      min-height: 30px;
      padding: 6px 9px;
      font-size: 11px
   }

   .flight-header-right>.status-badge {
      font-size: 10px;
      padding: 5px 7px
   }

   .route-heading {
      gap: 11px
   }

   .route-heading h2 {
      font-size: 25px;
      gap: 9px
   }

   .flight-symbol {
      width: 45px;
      height: 45px
   }

   .workspace-tabs {
      gap: 19px;
      padding: 0 22px
   }

   .workspace-tabs button {
      font-size: 12px;
      gap: 6px
   }

   .workspace-content {
      padding: 23px 22px
   }

   .readiness-row {
      grid-template-columns: 115px minmax(0, 1fr) 126px 12px;
      gap: 9px;
      padding-left: 0;
      padding-right: 0
   }

   .readiness-detail {
      font-size: 11px
   }

   .two-column {
      gap: 15px
   }

   .two-column>.surface-card .card-heading {
      padding: 16px 13px;
      gap: 7px
   }

   .two-column .card-heading-icon {
      width: 25px;
      height: 25px
   }

   .two-column .card-heading h3 {
      font-size: 12px
   }

   .two-column .text-button {
      font-size: 10px
   }

   .two-column .people-list {
      padding: 0 12px 5px
   }

   .two-column .person-row {
      flex-wrap: wrap;
      column-gap: 8px;
      row-gap: 4px
   }

   .two-column .person-name {
      flex-basis: calc(100% - 44px)
   }

   .two-column .person-row>.status-badge {
      margin-left: 42px
   }

   .two-column .person-row>.app-icon {
      margin-left: auto
   }

   .two-column .card-heading-action .app-icon {
      display: none
   }

   .flight-row {
      padding: 12px 10px
   }

   .mini-route {
      font-size: 12px;
      gap: 5px
   }

   .flight-row-top {
      gap: 8px
   }

   .flight-time {
      font-size: 11px;
      width: 58px
   }

   .flight-row-meta {
      font-size: 10px;
      gap: 4px
   }

   .direction-label {
      display: none
   }

   .search-row,
   .filter-tabs {
      margin-left: 15px;
      margin-right: 15px
   }

   .inbox-top {
      padding-left: 15px;
      padding-right: 15px
   }

   .search-box input {
      font-size: 11px
   }

   .fuel-numbers strong {
      font-size: 17px
   }

   .fuel-numbers strong.total-figure {
      font-size: 20px
   }

   .fuel-details {
      gap: 18px
   }

   .fuel-details>div {
      align-items: flex-start;
      flex-direction: column;
      gap: 6px
   }

   .payment-summary {
      gap: 16px
   }

   .payment-summary .amount-due strong {
      font-size: 19px
   }

   .payment-summary .app-button {
      font-size: 11px;
      padding: 9px
   }
}

@media(max-width:950px) {

   .user-label,
   .header-divider {
      display: none
   }

   .brand-logo {
      width: 148px
   }

   .app-header {
      gap: 18px
   }

   .global-nav>button {
      font-size: 12px
   }

   .dashboard-layout {
      grid-template-columns: 270px minmax(0, 1fr)
   }

   .flight-row-bottom {
      flex-wrap: wrap
   }

   .flight-reason {
      font-size: 9px
   }

   .flight-row .status-badge {
      font-size: 10px
   }

   .workspace-tabs {
      gap: 0;
      justify-content: space-between;
      padding: 0 15px;
      overflow: auto
   }

   .workspace-tabs button {
      font-size: 11px;
      gap: 4px;
      padding: 16px 6px
   }

   .workspace-tabs button .app-icon {
      --icon-size: 14px !important
   }

   .workspace-tabs .tab-dot {
      display: none
   }

   .flight-header {
      padding: 23px 18px;
      flex-wrap: wrap;
      gap: 17px
   }

   .route-heading h2 {
      font-size: 26px
   }

   .flight-header-right {
      width: 100%;
      max-width: none;
      justify-content: space-between;
      gap: 10px
   }

   .flight-header-right>.schedule {
      margin: 0;
      text-align: left;
      flex-direction: row;
      align-items: center;
      gap: 7px
   }

   .schedule>span:last-child {
      display: none
   }

   .schedule strong {
      font-size: 12px
   }

   .flight-header-right>.status-badge {
      margin-left: auto
   }

   .workspace-content {
      padding: 20px 16px;
      gap: 16px
   }

   .two-column {
      grid-template-columns: 1fr
   }

   .two-column .person-row {
      flex-wrap: nowrap
   }

   .two-column .person-name {
      flex-basis: auto
   }

   .two-column .person-row>.status-badge {
      margin-left: 0
   }

   .two-column>.surface-card .card-heading {
      padding: 17px
   }

   .two-column .people-list {
      padding: 0 17px 8px
   }

   .two-column .card-heading h3 {
      font-size: 14px
   }

   .two-column .text-button {
      font-size: 11px
   }

   .readiness-row {
      grid-template-columns: 110px 1fr 12px;
      gap: 6px
   }

   .readiness-row .readiness-detail {
      grid-row: 2;
      grid-column: 1/3;
      margin: 0 0 0 29px
   }

   .readiness-row>.status-badge {
      justify-self: end
   }

   .readiness-row>.app-icon {
      grid-column: 3;
      grid-row: 1
   }

   .attention-items .inline-action {
      display: none
   }

   .attention-items div span {
      font-size: 10px
   }

   .card-heading {
      padding: 16px
   }

   .readiness-table {
      padding: 0 16px 8px
   }

   .activity-strip {
      flex-wrap: wrap;
      font-size: 10px
   }

   .activity-strip>span:not(.time):not(.inline-action) {
      white-space: normal;
      flex-basis: 70%
   }

   .fuel-numbers {
      grid-template-columns: repeat(2, 1fr);
      gap: 20px
   }

   .fuel-numbers>div:nth-child(3) {
      border: 0;
      padding: 0
   }

   .payment-summary {
      flex-wrap: wrap
   }

   .payment-summary>.app-button {
      width: 100%;
      margin-top: 7px
   }

   .section-heading h3 {
      font-size: 20px
   }

   .section-heading p {
      font-size: 11px
   }

   .section-heading .app-button {
      font-size: 11px;
      padding: 8px 10px
   }

   .section-heading .app-button .app-icon {
      --icon-size: 16px !important
   }

   .aircraft-summary {
      gap: 14px;
      padding: 20px
   }

   .aircraft-large-icon {
      width: 60px;
      height: 60px
   }

   .aircraft-large-icon .app-icon {
      --icon-size: 34px !important
   }

   .aircraft-summary h3 {
      font-size: 18px
   }

   .aircraft-summary p {
      font-size: 10px
   }

   .aircraft-summary>.status-badge {
      display: none
   }
}

@media(max-width:700px) {
   .app-header {
      height: 62px;
      padding: 0 16px;
      gap: 8px
   }

   .brand {
      height: 48px
   }

   .brand-logo {
      width: 132px;
      max-height: 40px
   }

   .header-end {
      gap: 7px;
      margin-left: 0
   }

   .header-end>.avatar {
      width: 29px;
      height: 29px;
      font-size: 10px
   }

   .global-nav {
      margin-left: auto;
      gap: 0
   }

   .global-nav>button {
      padding: 0 9px;
      font-size: 0;
      gap: 0
   }

   .global-nav>button .app-icon {
      --icon-size: 20px !important
   }

   .global-nav>button:first-child {
      display: none
   }

   .global-nav .nav-count {
      position: absolute;
      right: 3px;
      top: 10px;
      font-size: 9px;
      height: 14px;
      min-width: 14px;
      padding: 0 3px
   }

   .header-icon {
      display: none
   }

   .dashboard-layout {
      height: auto;
      display: block
   }

   .flight-inbox {
      border-right: 0;
      border-bottom: 1px solid var(--line)
   }

   .inbox-top {
      padding: 18px 16px 14px
   }

   .inbox-top h1 {
      font-size: 23px
   }

   .inbox-top p {
      font-size: 11px
   }

   .search-row {
      margin: 0 16px 10px
   }

   .filter-tabs {
      margin: 0 16px 8px
   }

   .flight-groups {
      display: flex;
      overflow-x: auto;
      overflow-y: hidden;
      padding: 8px 16px 15px;
      gap: 14px
   }

   .flight-group {
      display: contents;
      margin: 0
   }

   .flight-group h2 {
      display: none
   }

   .flight-row {
      width: 246px;
      flex-shrink: 0;
      margin: 0;
      padding: 13px
   }

   .flight-row-top {
      font-size: 12px;
      gap: 12px
   }

   .flight-time {
      font-size: 12px
   }

   .mini-route {
      font-size: 13px
   }

   .flight-row-meta {
      font-size: 10px
   }

   .flight-row-bottom {
      flex-wrap: nowrap
   }

   .flight-reason {
      font-size: 10px
   }

   .inbox-footer {
      display: none
   }

   .flight-groups>.empty-state {
      padding: 10px;
      width: 100%;
      flex-shrink: 0
   }

   .flight-header {
      padding: 23px 18px;
      background: white
   }

   .route-heading h2 {
      font-size: 28px
   }

   .route-heading p {
      font-size: 11px
   }

   .flight-header-right>.schedule {
      flex-direction: column;
      align-items: flex-start;
      gap: 2px
   }

   .flight-header-right>.schedule strong {
      font-size: 13px
   }

   .workspace {
      overflow: visible
   }

   .workspace-tabs {
      top: 0;
      padding: 0 9px;
      position: sticky;
      gap: 5px
   }

   .workspace-tabs button {
      padding: 15px 8px;
      font-size: 11px
   }

   .workspace-tabs button .app-icon {
      display: none
   }

   .workspace-content {
      padding: 20px 14px;
      gap: 17px
   }

   .attention-heading h3 {
      font-size: 14px
   }

   .attention-heading p {
      font-size: 10px
   }

   .attention-card {
      padding: 14px
   }

   .attention-items>button {
      padding: 11px 10px;
      gap: 9px
   }

   .attention-items strong {
      font-size: 12px
   }

   .card-heading h3 {
      font-size: 14px
   }

   .readiness-row {
      grid-template-columns: 115px 1fr 12px;
      padding: 14px 0
   }

   .person-name strong,
   .two-column .person-name strong {
      font-size: 12px
   }

   .person-row>.status-badge {
      font-size: 10px
   }

   .workspace-footnote {
      font-size: 9px
   }

   .expanded .person-row {
      gap: 10px;
      padding: 17px 0
   }

   .expanded .person-name strong {
      font-size: 12px
   }

   .expanded .person-name>span {
      font-size: 10px
   }

   .expanded .person-row>.status-badge {
      font-size: 10px
   }

   .expanded .person-row>.app-icon {
      margin: 0
   }

   .expanded .avatar {
      width: 33px;
      height: 33px;
      font-size: 10px
   }

   .fuel-progress {
      padding: 22px 12px
   }

   .fuel-progress strong {
      font-size: 11px
   }

   .fuel-progress small {
      font-size: 9px
   }

   .fuel-details {
      padding: 0 17px 20px
   }

   .fuel-numbers {
      margin: 0 17px
   }

   .section-heading {
      align-items: flex-start
   }

   .section-heading h3 {
      font-size: 21px
   }

   .section-heading p {
      max-width: 230px;
      line-height: 1.6
   }

   .section-heading .app-button {
      font-size: 10px
   }

   .section-heading .app-button .app-icon {
      display: none
   }

   .dynamic-drawer {
      width: min(480px, 100vw)
   }

   .drawer-header {
      padding: 20px;
      min-height: 90px
   }

   .drawer-header h2 {
      font-size: 20px
   }

   .panel-body {
      padding: 22px
   }

   .chat-composer {
      padding: 16px 20px
   }

   .conversation-scroll,
   .conversation-audience {
      padding: 20px
   }

   .toast-message {
      bottom: 15px;
      font-size: 11px;
      width: max-content
   }

   .catering-body {
      padding: 5px 20px 22px
   }
}

.drawer-page {
   height: 100%;
   overflow: auto
}

.drawer-page[hidden] {
   display: none
}

.drawer-content {
   overflow: hidden
}

#drawer-title:focus {
   outline: none
}

.custom-select-menu {
   max-height: 260px;
   overflow-y: auto;
   scrollbar-width: thin;
   scrollbar-color: #6e6e6e transparent
}

/* Stronger inbox grouping keeps the soft palette while making status scannable. */
.flight-inbox {
   background: #f5f5f5
}

.flight-groups {
   padding-left: 10px;
   padding-right: 10px
}

.flight-group {
   margin-top: 14px;
   padding: 10px 8px 3px;
   border: 1px solid #e5e5e5;
   border-radius: 10px;
   background: #fafafa
}

.flight-group.amber {
   border-color: #eadfcf;
   background: linear-gradient(145deg, #fffaf2, #fafafa 42%)
}

.flight-group.green {
   border-color: #d7e8e2;
   background: linear-gradient(145deg, #f2faf6, #fafafa 42%)
}

.flight-group.blue {
   border-color: #6e6e6e;
   background: linear-gradient(145deg, #f5f5f5, #fafafa 42%)
}

.flight-group h2 {
   padding: 0 4px 1px;
   margin-bottom: 9px;
   color: #525252
}

.group-count {
   min-width: 20px;
   height: 20px;
   display: grid;
   place-items: center;
   border-radius: 10px;
   background: #ededed;
   color: #6e6e6e;
   font-weight: 600
}

.flight-row {
   border-color: #6e6e6e;
   box-shadow: 0 2px 5px #3737370a;
   margin-bottom: 8px
}

.flight-row-meta {
   color: #6e6e6e
}

.flight-row-meta strong {
   color: #565656
}

.flight-reason {
   color: #6e6e6e;
   font-weight: 500
}

.flight-row.is-selected {
   border-color: #6e6e6e;
   box-shadow: 0 4px 13px #6e6e6e1a
}

.demo-label {
   display: inline-flex;
   align-items: center;
   gap: 6px
}

.demo-label .live-dot {
   box-shadow: 0 0 0 3px #3faa8420
}

.theme-toggle {
   transition: background .15s var(--ease-standard), color .15s var(--ease-standard), transform .12s var(--ease-standard)
}

.theme-toggle:hover {
   background: #ffffff12;
   color: white
}

.theme-toggle:active {
   transform: scale(.94)
}

.card-heading-icon.category-plane {
   color: var(--category-aircraft);
   background: var(--category-aircraft-soft)
}

.card-heading-icon.category-crew {
   color: var(--category-crew);
   background: var(--category-crew-soft)
}

.card-heading-icon.category-fuel {
   color: var(--category-fuel);
   background: var(--category-fuel-soft)
}

.card-heading-icon.category-food {
   color: var(--category-catering);
   background: var(--category-catering-soft)
}

.card-heading-icon.category-people {
   color: var(--category-passengers);
   background: var(--category-passengers-soft)
}

.card-heading-icon.category-car {
   color: var(--category-transport);
   background: var(--category-transport-soft)
}

.card-heading-icon.category-message {
   color: var(--category-messages);
   background: var(--category-messages-soft)
}

/* Two class vocabularies reach this system: the tab row writes the tab's name
   (`category-aircraft`), while card headings and readiness rows write the icon's
   name (`category-plane`). The readiness selectors below used to name the tab, so
   three of the five never matched anything — aircraft, catering and passengers
   rows have been uncoloured since the system was written. Both spellings are
   answered here.

   `:not()` rather than source order. These rules and the attention rules that
   override them have identical specificity, so which one wins was decided by
   where each happened to sit in this file — restate either one lower down and the
   category hue would silently start beating amber. Excluding the states makes the
   rule say what it means: a tab or row carries its category hue only while it has
   nothing open. */
.workspace-tabs button.category-aircraft:not(.has-caution):not(.has-warning) {
   --tab-hue: var(--category-aircraft)
}

.readiness-row.category-plane:not(.needs-caution):not(.needs-warning) .readiness-category .app-icon,
.aircraft-large-icon {
   color: var(--category-aircraft)
}

.workspace-tabs button.category-crew:not(.has-caution):not(.has-warning) {
   --tab-hue: var(--category-crew)
}

.readiness-row.category-crew:not(.needs-caution):not(.needs-warning) .readiness-category .app-icon {
   color: var(--category-crew)
}

.workspace-tabs button.category-fuel:not(.has-caution):not(.has-warning) {
   --tab-hue: var(--category-fuel)
}

.readiness-row.category-fuel:not(.needs-caution):not(.needs-warning) .readiness-category .app-icon {
   color: var(--category-fuel)
}

.workspace-tabs button.category-catering:not(.has-caution):not(.has-warning) {
   --tab-hue: var(--category-catering)
}

.readiness-row.category-food:not(.needs-caution):not(.needs-warning) .readiness-category .app-icon {
   color: var(--category-catering)
}

.workspace-tabs button.category-passengers:not(.has-caution):not(.has-warning) {
   --tab-hue: var(--category-passengers)
}

.readiness-row.category-people:not(.needs-caution):not(.needs-warning) .readiness-category .app-icon {
   color: var(--category-passengers)
}

.workspace-tabs button.category-transport:not(.has-caution):not(.has-warning) {
   --tab-hue: var(--category-transport)
}

.readiness-row.category-car:not(.needs-caution):not(.needs-warning) .readiness-category .app-icon {
   color: var(--category-transport)
}

/* Messages never wears a caution or a warning — an unread count is information,
   not outstanding work, and `has-info` leaves the icon alone — but the guards stay
   so every tab in the row is written the same way. */
.workspace-tabs button.category-messages:not(.has-caution):not(.has-warning) {
   --tab-hue: var(--category-messages)
}

/* The icon and the underline are the same fact drawn twice, so they read one
   value. State overwrites `--tab-hue` below, which is what makes the indicator on
   a tab with work outstanding amber or red rather than its domain colour. */
.workspace-tabs button>.app-icon {
   color: var(--tab-hue, inherit)
}

.workspace-tabs button.active:after {
   background: var(--tab-hue, var(--blue))
}

.flight-row.is-lane-exiting {
   pointer-events: none;
   will-change: transform, opacity;
   animation: laneExit var(--dur-fast) var(--ease-exit) both
}

.flight-row.is-lane-entering {
   will-change: transform, opacity;
   animation: laneEnter var(--dur-slow) var(--ease-entrance) both
}

@keyframes laneExit {
   from {
      opacity: 1;
      transform: translateX(0) scale(1)
   }

   to {
      opacity: 0;
      transform: translateX(18px) scale(.985)
   }
}

@keyframes laneEnter {
   from {
      opacity: 0;
      transform: translateX(-14px) scale(.985)
   }

   to {
      opacity: 1;
      transform: translateX(0) scale(1)
   }
}

/* Dark mode uses the same blue-gray visual language with deeper surfaces. */
:root[data-theme=dark] {
   color-scheme: dark;
   --ink: #efefef;
   --muted: #a9a9a9;
   --muted-strong: #a9a9a9;
   --line: #3d3d3d;
   --bs-body-color: #efefef;
   --bs-border-color: #3d3d3d;
   background: #181818
}

:root[data-theme=dark] body {
   color: var(--ink);
   background: #181818
}

[data-theme=dark] .workspace {
   background: #181818
}

[data-theme=dark] .flight-inbox {
   background: #1e1e1e;
   border-color: #393939
}

[data-theme=dark] .inbox-top p,
[data-theme=dark] .flight-row-meta,
[data-theme=dark] .direction-label,
[data-theme=dark] .flight-reason,
[data-theme=dark] .card-heading p,
[data-theme=dark] .person-name>span,
[data-theme=dark] .section-heading p,
[data-theme=dark] .workspace-footnote {
   color: #a2a2a2
}

[data-theme=dark] .search-box,
[data-theme=dark] .filter-tabs,
[data-theme=dark] .square-button,
[data-theme=dark] .flight-row,
[data-theme=dark] .surface-card,
[data-theme=dark] .flight-header,
[data-theme=dark] .workspace-tabs,
[data-theme=dark] .aircraft-summary,
[data-theme=dark] .invoice-strip,
[data-theme=dark] .dynamic-drawer,
[data-theme=dark] .chat-composer {
   background: #272727;
   border-color: #3f3f3f;
   color: var(--ink)
}

[data-theme=dark] .search-box input,
[data-theme=dark] .form-field .form-control,
[data-theme=dark] .custom-select-trigger,
[data-theme=dark] .chat-composer textarea {
   color: #e7e7e7;
   background: #212121;
   border-color: #454545
}

[data-theme=dark] .search-box input::placeholder,
[data-theme=dark] .form-field input::placeholder,
[data-theme=dark] .form-field textarea::placeholder,
[data-theme=dark] .chat-composer textarea::placeholder {
   color: #848484
}

[data-theme=dark] .filter-tabs {
   background: #1c1c1c
}

.filter-tabs button {
   transition: background .15s, color .15s
}

[data-theme=dark] .filter-tabs button {
   color: #a5a5a5
}

[data-theme=dark] .filter-tabs button.selected {
   color: #b2b2b2;
   background: #353535;
   box-shadow: none
}

[data-theme=dark] .filter-tabs button span {
   background: #424242;
   color: #c6c6c6
}

[data-theme=dark] .flight-group {
   border-color: #3b3b3b;
   background: #242424
}

[data-theme=dark] .flight-group.amber {
   border-color: #51422f;
   background: linear-gradient(145deg, #29261f, #242424 46%)
}

[data-theme=dark] .flight-group.green {
   border-color: #29483f;
   background: linear-gradient(145deg, #292929, #242424 46%)
}

[data-theme=dark] .flight-group.blue {
   border-color: #424242;
   background: linear-gradient(145deg, #2a2a2a, #242424 46%)
}

[data-theme=dark] .flight-group h2 {
   color: #d6d6d6
}

[data-theme=dark] .group-count {
   background: #3a3a3a;
   color: #c1c1c1
}

[data-theme=dark] .flight-row {
   background: #2b2b2b;
   border-color: #464646;
   box-shadow: 0 3px 8px #11111138
}

[data-theme=dark] .flight-row.is-selected {
   background: linear-gradient(120deg, #373737, #323232);
   border-color: #909090
}

[data-theme=dark] .flight-row-meta strong {
   color: #cacaca
}

[data-theme=dark] .mini-route .app-icon {
   color: #8f8f8f
}

[data-theme=dark] .inbox-footer {
   background: #1c1c1c;
   border-color: #393939;
   color: #969696
}

[data-theme=dark] .flight-symbol,
[data-theme=dark] .card-heading-icon,
[data-theme=dark] .aircraft-large-icon,
[data-theme=dark] .soft-icon,
[data-theme=dark] .payment-review-icon {
   background: #363636;
   border-color: #444444;
   color: #adadad
}

[data-theme=dark] .workspace-tabs {
   border-color: #393939
}

.workspace-tabs button {
   transition: color .15s
}

[data-theme=dark] .attention-card {
   background: linear-gradient(115deg, #2b261e, #242424);
   border-color: #51432e
}

[data-theme=dark] .attention-heading h3 {
   color: #f0c582
}

[data-theme=dark] .attention-heading p {
   color: #b8a27d
}

[data-theme=dark] .attention-items>button {
   background: #2a2925;
   border-color: #4d4333;
   color: #e7d8bf
}

[data-theme=dark] .attention-items strong {
   color: #edd7b4
}

[data-theme=dark] .attention-items div span {
   color: #baa88c
}

[data-theme=dark] .readiness-row,
[data-theme=dark] .person-row,
[data-theme=dark] .details-list>div {
   border-color: #3c3c3c
}

[data-theme=dark] .readiness-detail,
[data-theme=dark] .details-list dt,
[data-theme=dark] .panel-intro,
[data-theme=dark] .field-hint {
   color: #a3a3a3
}

[data-theme=dark] .details-list dd,
[data-theme=dark] .person-name strong,
[data-theme=dark] .panel-body .details-list dd {
   color: #d3d3d3
}

[data-theme=dark] .activity-strip,
[data-theme=dark] .note,
[data-theme=dark] .saved-payment,
[data-theme=dark] .panel-flight-summary {
   background: #2b2b2b;
   border-color: #444444;
   color: #b4b4b4
}

[data-theme=dark] .card-footer-action {
   background: #252525;
   border-color: #3c3c3c;
   color: #b1b1b1
}

[data-theme=dark] .form-field>.form-label {
   color: #b6b6b6
}

[data-theme=dark] .form-field input:read-only {
   background: #1f1f1f;
   color: #949494
}

[data-theme=dark] .custom-select-menu {
   background: #2b2b2b;
   border-color: #4e4e4e;
   box-shadow: 0 18px 42px #0c0c0c70
}

[data-theme=dark] .custom-select-menu .dropdown-item {
   color: #c6c6c6
}

[data-theme=dark] .custom-select-menu .dropdown-item:focus {
   background: #3a3a3a;
   color: #e7e7e7
}

[data-theme=dark] .custom-select-menu .dropdown-item.active {
   background: #444444;
   color: #c5c5c5
}

[data-theme=dark] .drawer-header,
[data-theme=dark] .conversation-tabs,
[data-theme=dark] .chat-composer {
   border-color: #3d3d3d
}

[data-theme=dark] .chat-message-content>p {
   background: #2f2f2f;
   border-color: #3e3e3e;
   color: #d0d0d0
}

[data-theme=dark] .chat-message.own .chat-message-content>p {
   background: #363636;
   border-color: #4f4f4f;
   color: #e5e5e5
}

[data-theme=dark] .status-badge.gray {
   background: #3b3b3b;
   color: #c1c1c1
}

[data-theme=dark] .status-badge.blue {
   background: #3b3b3b;
   color: #c2c2c2
}

[data-theme=dark] .status-badge.green {
   background: #193b34;
   color: #81d2b5
}

[data-theme=dark] .status-badge.amber {
   background: #433521;
   color: #f1be73
}

[data-theme=dark] .soft-view-button {
   background: #383838;
   border-color: #4e4e4e;
   color: #bfbfbf
}

[data-theme=dark] .app-button.secondary {
   background: #2b2b2b;
   border-color: #535353;
   color: #c9c9c9
}

/* A neutral charcoal base and stepped surfaces keep dark mode from reading as one navy block. */
:root[data-theme=dark] {
   --ink: #f1f1f1;
   --muted: #a5a5a5;
   --line: #323232;
   --bs-body-color: #f1f1f1;
   --bs-border-color: #323232;
   background: #0b0b0b
}

:root[data-theme=dark] {
}

:root[data-theme=dark] body,
[data-theme=dark] .workspace {
   background: #0d0d0d
}

[data-theme=dark] .flight-inbox {
   background: #131313;
   border-color: #2c2c2c
}

[data-theme=dark] .flight-header {
   background: #151515;
   border-color: #2d2d2d
}

[data-theme=dark] .workspace-tabs {
   background: #181818;
   border-color: #303030
}

[data-theme=dark] .surface-card,
[data-theme=dark] .aircraft-summary,
[data-theme=dark] .invoice-strip {
   background: #1b1b1b;
   border-color: #343434
}

[data-theme=dark] .dynamic-drawer,
[data-theme=dark] .chat-composer {
   background: #171717;
   border-color: #323232
}

[data-theme=dark] .search-box,
[data-theme=dark] .square-button {
   background: #1b1b1b;
   border-color: #393939
}

[data-theme=dark] .filter-tabs {
   background: #0e0e0e;
   border-color: #2a2a2a
}

[data-theme=dark] .flight-group {
   border-color: #313131;
   background: #181818
}

[data-theme=dark] .flight-group.amber {
   border-color: #493b2b;
   background: linear-gradient(145deg, #211c16, #181818 48%)
}

[data-theme=dark] .flight-group.green {
   border-color: #263c34;
   background: linear-gradient(145deg, #13201b, #181818 48%)
}

[data-theme=dark] .flight-group.blue {
   border-color: #363636;
   background: linear-gradient(145deg, #1b1b1b, #181818 48%)
}

[data-theme=dark] .flight-row {
   background: #1f1f1f;
   border-color: #3e3e3e;
   box-shadow: 0 4px 10px #00000038
}

[data-theme=dark] .flight-row.is-selected {
   background: linear-gradient(120deg, #262626, #242424);
   border-color: #8b8b8b
}

[data-theme=dark] .inbox-footer {
   background: #0f0f0f;
   border-color: #2c2c2c
}

[data-theme=dark] .activity-strip,
[data-theme=dark] .note,
[data-theme=dark] .saved-payment,
[data-theme=dark] .panel-flight-summary {
   background: #1c1c1c;
   border-color: #3b3b3b
}

[data-theme=dark] .card-footer-action {
   background: #181818;
   border-color: #323232
}

[data-theme=dark] .search-box input,
[data-theme=dark] .form-field .form-control,
[data-theme=dark] .custom-select-trigger,
[data-theme=dark] .chat-composer textarea {
   background: #121212;
   border-color: #3a3a3a
}

[data-theme=dark] .custom-select-menu {
   background: #1d1d1d;
   border-color: #454545;
   box-shadow: 0 18px 44px #0000008a
}

[data-theme=dark] .attention-card {
   background: linear-gradient(120deg, #211d17, #191a18);
   border-color: #4b3d2c
}

[data-theme=dark] .attention-items>button {
   background: #24231f;
   border-color: #453c2f
}

[data-theme=dark] .toast-message {
   background: #1d1d1d;
   border-color: #464646;
   box-shadow: 0 14px 38px #00000073;
   color: #f3f3f3
}

@media(max-width:1250px) {
   .demo-label {
      display: none
   }
}

@media(max-width:700px) {
   .flight-group {
      display: contents;
      margin: 0;
      padding: 0;
      border: 0;
      background: none
   }

   .theme-toggle {
      display: inline-flex
   }

   .brand-logo {
      width: 122px
   }

   .toast-message {
      right: 15px;
      bottom: 15px
   }
}

@media(prefers-reduced-motion:reduce) {

   *,
   *::before,
   *::after {
      animation-duration: .01ms !important;
      transition-duration: .01ms !important;
      scroll-behavior: auto !important
   }
}

/* Shared maps and airport information. */
.segmented {
   display: flex;
   gap: 4px;
   padding: 4px;
   border: 1px solid var(--line);
   border-radius: 7px;
   background: var(--ops-soft, #f1f1f1);
   width: max-content;
   max-width: 100%
}

.segmented button {
   padding: 8px 13px;
   border-radius: 5px;
   font-size: 12px;
   display: flex;
   align-items: center;
   justify-content: center;
   gap: 7px;
   color: var(--muted)
}

.segmented button.active {
   background: var(--ops-surface, white);
   color: var(--blue);
   box-shadow: 0 1px 5px #0000000d
}

.map-toolbar {
   display: flex;
   align-items: center;
   gap: 14px;
   flex-wrap: wrap
}

.map-toolbar select {
   border: 1px solid var(--line);
   border-radius: 6px;
   padding: 10px;
   background: var(--ops-surface, white);
   color: var(--ink);
   font-size: 12px
}

.map-toolbar>span {
   margin-left: auto;
   font-size: 12px;
   color: var(--muted)
}

.ops-map {
   position: relative;
   height: 440px;
   overflow: hidden;
   border-radius: 9px 9px 0 0;
   background: #dce5d8;
   isolation: isolate
}

.ops-map.compact {
   height: 295px;
   border-radius: 8px;
   margin-top: 18px
}

.map-viewport {
   position: absolute;
   inset: 0;
   overflow: hidden;
   touch-action: none;
   cursor: grab
}

.map-viewport:active {
   cursor: grabbing
}

.map-layer {
   position: absolute;
   inset: 0;
   transform-origin: center;
   transition: transform .12s ease-out
}

.map-image {
   width: 100%;
   height: 100%;
   object-fit: cover;
   display: block;
   user-select: none
}

.map-marker {
   position: absolute;
   display: flex;
   align-items: center;
   gap: 7px;
   transform: translate(-50%, -50%);
   padding: 9px 11px;
   color: #515151;
   background: white;
   border: 1px solid #c0c0c0;
   border-radius: 7px;
   box-shadow: 0 3px 12px #3a3a3a40;
   white-space: nowrap;
   font-size: 11px;
   font-weight: 700
}

.map-marker .app-icon {
   transform: rotate(-25deg)
}

.map-marker.selected {
   background: #6e6e6e;
   color: white;
   border-color: #6e6e6e;
   z-index: 2;
   box-shadow: 0 0 0 5px #6e6e6e26, 0 3px 12px #3a3a3a33
}

.map-marker.delayed {
   border-color: #bc6e14
}

.map-context {
   position: absolute;
   top: 16px;
   left: 16px;
   display: flex;
   align-items: center;
   gap: 7px;
   background: #ffffffed;
   color: #4e4e4e;
   border-radius: 5px;
   padding: 9px 11px;
   font-size: 11px;
   box-shadow: 0 2px 8px #2a2a2a12
}

.map-controls {
   position: absolute;
   right: 16px;
   top: 16px;
   display: flex;
   flex-direction: column;
   box-shadow: 0 3px 15px #2a2a2a25;
   border: 1px solid #d5d5d5;
   border-radius: 6px;
   overflow: hidden;
   background: white
}

.map-controls button {
   width: 35px;
   height: 35px;
   border-bottom: 1px solid #e8e8e8;
   color: #3b3b3b;
   font-size: 22px
}

.map-controls button:last-child {
   border: 0
}

.map-attribution {
   position: absolute;
   bottom: 7px;
   right: 8px;
   background: #ffffffdf;
   padding: 4px 6px;
   border-radius: 3px;
   color: #616161;
   font-size: 9px
}

.map-destination {
   position: absolute;
   left: 30%;
   top: 35%;
   padding: 12px;
   background: white;
   box-shadow: 0 3px 12px #34343435;
   border-radius: 8px;
   color: #434343;
   font-size: 11px
}

.weather-strip {
   display: flex;
   align-items: center;
   justify-content: space-between;
   gap: 12px;
   padding: 20px 22px
}

.weather-strip>div {
   display: flex;
   align-items: center;
   flex-direction: column;
   gap: 8px;
   font-size: 12px
}

.weather-strip>div:first-child {
   align-items: flex-start;
   gap: 5px;
   margin-right: 15px
}

.weather-strip small {
   font-size: 10px;
   color: var(--muted)
}

.weather-strip .app-icon {
   color: #b78c47
}

.map-flight-detail {
   display: flex;
   align-items: center;
   gap: 15px;
   padding: 19px;
   background: var(--ops-surface, white);
   border: 1px solid var(--line);
   border-radius: 9px;
   flex-wrap: wrap
}

.map-flight-detail>div:nth-child(2) {
   flex: 1
}

.map-flight-detail strong {
   font-size: 13px
}

.map-flight-detail p {
   font-size: 11px;
   color: var(--muted);
   margin-top: 6px
}

.weather-hero {
   display: flex;
   flex-direction: column;
   align-items: center;
   padding: 35px;
   gap: 15px
}

.weather-hero strong {
   font-size: 40px
}

.weather-hero span {
   font-size: 12px;
   color: var(--muted)
}

.spaced-heading {
   margin-top: 24px
}

.public-board {
   display: flex;
   flex-direction: column;
   gap: 18px
}

.public-board .ops-map {
   margin: 0
}

.board-table {
   overflow: auto
}

.board-table table {
   width: 100%;
   font-size: 12px;
   white-space: nowrap
}

.board-table th {
   background: var(--ops-soft, #f3f3f3);
   color: var(--muted);
   font-weight: 500
}

.board-table th,
.board-table td {
   padding: 12px;
   border-bottom: 1px solid var(--line)
}

.board-table td small {
   display: block;
   color: var(--muted);
   margin-top: 5px
}

:root {
   --ops-surface: #fff;
   --ops-soft: #f1f1f1
}

:root[data-theme=dark] {
   --ops-surface: #1b1b1b;
   --ops-soft: #131313
}

@media(max-width:700px) {
   .ops-map {
      height: 360px
   }

   .map-context {
      max-width: 75%;
      font-size: 10px
   }

   .map-marker {
      font-size: 9px;
      padding: 7px;
      gap: 4px
   }

   .map-marker .app-icon {
      --icon-size: 15px !important
   }

   .weather-strip {
      padding: 15px 12px;
      gap: 9px
   }

   .weather-strip>div:first-child {
      display: none
   }

   .map-flight-detail .app-button {
      flex: 1
   }

   .workspace-tabs button {
      flex-shrink: 0
   }

   .map-toolbar {
      gap: 8px
   }
}

/* Role workflows reuse the dashboard's cards, typography and status colors. */
.workflow-card-body {
   padding: 22px
}

.workflow-card-body>p {
   color: var(--muted);
   font-size: 12px;
   line-height: 1.7;
   margin: 8px 0
}

.workflow-card-body h3 {
   font-size: 19px
}

.workflow-action-row {
   display: flex;
   flex-wrap: wrap;
   gap: 10px;
   margin-top: 15px
}

.workflow-panel {
   display: flex;
   flex-direction: column;
   gap: 20px
}

.workflow-panel .section-heading {
   flex-wrap: wrap;
   gap: 12px
}

.workflow-panel .app-button {
   white-space: normal
}

.person-summary {
   display: flex;
   align-items: center;
   gap: 14px
}

.person-summary>div {
   flex: 1;
   min-width: 0
}

.person-summary h3 {
   font-size: 17px
}

.person-summary p {
   font-size: 11px;
   color: var(--muted);
   margin: 6px 0
}

.passenger-grid,
.assignment-list {
   display: grid;
   grid-template-columns: repeat(2, minmax(0, 1fr));
   gap: 18px
}

.passenger-badges {
   display: flex;
   gap: 8px;
   margin: 18px 0
}

.passenger-grid .app-button {
   font-size: 11px
}

.passenger-grid .workflow-action-row {
   gap: 8px
}

.passenger-grid .avatar.large {
   width: 49px;
   height: 49px;
   font-size: 17px
}

.service-actions {
   padding: 0 22px 14px
}

.service-actions>button {
   display: flex;
   align-items: center;
   gap: 15px;
   padding: 18px 0;
   border-bottom: 1px solid var(--line);
   width: 100%;
   text-align: left
}

.service-actions>button:last-child {
   border: 0
}

.service-actions>button>span {
   display: flex;
   flex-direction: column;
   flex: 1;
   gap: 6px
}

.service-actions strong {
   font-size: 13px
}

.service-actions small {
   font-size: 11px;
   color: var(--muted)
}

.duty-summary {
   display: flex;
   align-items: center;
   gap: 28px;
   padding: 24px;
   background: var(--ops-surface);
   border: 1px solid var(--line);
   border-radius: 9px
}

.duty-summary>div {
   display: flex;
   flex-direction: column;
   gap: 7px
}

.duty-summary>div>span {
   font-size: 10px;
   color: var(--muted);
   letter-spacing: .08em
}

.duty-summary strong {
   font-size: 19px
}

.duty-summary>.app-icon {
   color: var(--muted)
}

.duty-summary>.app-button {
   margin-left: auto
}

.leg-grid {
   display: grid;
   grid-template-columns: repeat(2, minmax(0, 1fr));
   gap: 18px
}

.leg-card {
   text-align: left;
   border: 1px solid var(--line);
   border-radius: 9px;
   background: var(--ops-surface);
   padding: 0;
   overflow: hidden
}

.leg-card.active {
   border-color: #6e6e6e;
   box-shadow: 0 0 0 2px #88888820
}

.leg-top {
   padding: 13px 18px;
   display: flex;
   align-items: center;
   justify-content: space-between;
   background: var(--ops-soft);
   border-bottom: 1px solid var(--line);
   font-size: 13px
}

.leg-card>small {
   display: block;
   padding: 16px 18px 0;
   color: var(--muted);
   font-size: 10px
}

.leg-route {
   font-size: 29px;
   font-weight: 700;
   display: flex;
   align-items: center;
   justify-content: space-between;
   padding: 13px 18px
}

.leg-route>.app-icon {
   color: #6e6e6e
}

.leg-bottom {
   padding: 0 18px 18px;
   display: flex;
   justify-content: space-between;
   color: var(--muted);
   font-size: 11px
}

.leg-readiness {
   display: flex;
   gap: 20px;
   font-size: 10px;
   padding: 13px 18px;
   border-top: 1px solid var(--line);
   color: var(--muted)
}

.leg-readiness>span {
   display: flex;
   align-items: center;
   gap: 5px
}

.mechanical-banner {
   display: flex;
   align-items: center;
   gap: 13px
}

.mechanical-banner>div {
   flex: 1
}

.mechanical-banner p {
   font-size: 12px;
   margin-top: 6px
}

.checkin-heading {
   text-align: center;
   display: flex;
   align-items: center;
   flex-direction: column;
   gap: 14px
}

.checkin-heading h3 {
   font-size: 25px
}

.checkin-heading p {
   font-size: 12px;
   color: var(--muted);
   line-height: 1.8
}

.check-row {
   display: flex;
   align-items: flex-start;
   gap: 12px;
   padding: 18px 0;
   border-bottom: 1px solid var(--line);
   font-size: 13px;
   line-height: 1.6;
   cursor: pointer
}

.check-row input {
   width: 18px;
   height: 18px;
   accent-color: var(--blue);
   flex-shrink: 0;
   margin-top: 2px
}

.blocking-list {
   padding-left: 20px;
   font-size: 12px;
   line-height: 1.9;
   margin: 12px 0
}

.catering-progress {
   display: flex;
   justify-content: space-between;
   padding: 20px;
   background: var(--ops-soft);
   border-top: 1px solid var(--line);
   border-bottom: 1px solid var(--line)
}

.catering-progress>div {
   position: relative;
   flex: 1;
   text-align: center;
   display: flex;
   flex-direction: column;
   align-items: center;
   gap: 9px
}

.catering-progress>div:before {
   content: '';
   position: absolute;
   height: 2px;
   background: var(--line);
   left: -50%;
   right: 50%;
   top: 14px
}

.catering-progress>div:first-child:before {
   display: none
}

.catering-progress>div>span {
   z-index: 1;
   width: 29px;
   height: 29px;
   background: var(--ops-surface);
   border: 1px solid var(--line);
   border-radius: 50%;
   display: grid;
   place-items: center;
   color: var(--muted)
}

.catering-progress .done>span {
   color: #fff;
   background: #238772;
   border-color: #238772
}

.catering-progress strong {
   font-size: 10px;
   color: var(--muted)
}

.catering-progress .done strong {
   color: var(--ink)
}

.transport-driver {
   display: flex;
   align-items: center;
   padding: 25px;
   gap: 20px
}

.transport-driver>div {
   flex: 1
}

.transport-driver strong {
   font-size: 19px
}

.transport-driver p {
   font-size: 11px;
   color: var(--muted);
   margin-top: 6px
}

.transport-car {
   height: 70px;
   width: 95px;
   display: grid;
   place-items: center;
   border: 1px solid var(--line);
   border-radius: 8px;
   background: var(--ops-soft);
   color: #6e6e6e
}

.transport-progress {
   display: flex;
   padding: 18px 15px;
   border-top: 1px solid var(--line)
}

.transport-progress>div {
   flex: 1;
   display: flex;
   flex-direction: column;
   align-items: center;
   gap: 9px;
   position: relative;
   text-align: center
}

.transport-progress>div>span {
   z-index: 1;
   background: var(--ops-surface);
   border: 1px solid var(--line);
   border-radius: 50%;
   width: 24px;
   height: 24px;
   display: grid;
   place-items: center;
   font-size: 10px;
   color: var(--muted)
}

.transport-progress>div:before {
   content: '';
   position: absolute;
   left: -50%;
   right: 50%;
   top: 12px;
   height: 1px;
   background: var(--line)
}

.transport-progress>div:first-child:before {
   display: none
}

.transport-progress .done>span {
   background: #238772;
   border-color: #238772;
   color: white
}

.transport-progress small {
   font-size: 9px;
   color: var(--muted);
   max-width: 90px
}

.transport-stops {
   padding: 22px;
   display: flex;
   gap: 30px
}

.transport-stops>div {
   flex: 1;
   display: flex;
   gap: 14px
}

.transport-stops small {
   display: block;
   color: var(--muted);
   font-size: 9px;
   margin-bottom: 7px
}

.transport-stops strong {
   font-size: 12px
}

.transport-stops p {
   font-size: 11px;
   color: var(--muted);
   margin-top: 7px;
   line-height: 1.6
}

.stop-dot {
   display: block;
   width: 10px;
   height: 10px;
   border: 2px solid var(--blue);
   border-radius: 50%;
   flex-shrink: 0;
   margin-top: 3px
}

.stop-dot.destination {
   background: var(--blue);
   border-radius: 2px
}

.sample-document {
   display: flex;
   flex-direction: column;
   align-items: center;
   gap: 14px;
   padding: 30px 20px;
   border: 1px dashed var(--line);
   background: var(--ops-soft);
   border-radius: 10px;
   margin: 25px 0
}

.sample-document span,
.sample-document p {
   font-size: 11px;
   color: var(--muted);
   text-align: center;
   line-height: 1.7
}

.sample-document>.app-icon {
   color: #6e6e6e
}

.date-filter {
   margin: 8px 20px;
   color: var(--muted);
   font-size: 11px
}

.date-filter summary {
   display: flex;
   gap: 7px;
   cursor: pointer;
   align-items: center
}

.date-filter>div {
   display: flex;
   gap: 8px;
   padding-top: 10px
}

.date-filter label {
   min-width: 0;
   flex: 1;
   display: flex;
   flex-direction: column;
   gap: 5px
}

.date-filter input {
   width: 100%;
   min-width: 0;
   padding: 7px;
   border: 1px solid var(--line);
   border-radius: 5px;
   background: var(--ops-surface);
   color: var(--ink);
   font-size: 10px
}

/* The same conversation component powers mobile, desktop, and drawers. */
.messages-workspace {
   display: grid;
   grid-template-columns: 240px minmax(0, 1fr);
   height: 580px;
   min-height: 440px;
   border: 1px solid var(--line);
   border-radius: 9px;
   background: var(--ops-surface);
   overflow: hidden
}

.channel-list {
   border-right: 1px solid var(--line);
   overflow: auto
}

.channel-heading {
   padding: 23px 19px;
   border-bottom: 1px solid var(--line)
}

.channel-heading h3 {
   font-size: 19px
}

.channel-heading p {
   font-size: 10px;
   color: var(--muted);
   margin-top: 6px
}

.channel-list>button {
   display: flex;
   gap: 10px;
   align-items: center;
   text-align: left;
   width: 100%;
   padding: 19px 15px;
   border-bottom: 1px solid var(--line)
}

.channel-list>button.active {
   background: var(--ops-soft);
   box-shadow: inset 3px 0 0 var(--blue)
}

.channel-list>button>span:nth-child(2) {
   flex: 1;
   min-width: 0
}

.channel-list strong {
   display: block;
   font-size: 11px
}

.channel-list small {
   display: block;
   font-size: 10px;
   color: var(--muted);
   margin-top: 6px;
   white-space: nowrap;
   text-overflow: ellipsis;
   overflow: hidden
}

.channel-icon {
   height: 30px;
   width: 30px;
   display: grid;
   place-items: center;
   color: #6e6e6e;
   flex-shrink: 0
}

.message-thread {
   min-width: 0;
   min-height: 0;
   display: flex;
   flex-direction: column
}

.message-thread .conversation-layout {
   height: 100%;
   min-height: 0
}

.message-thread .conversation-audience {
   padding: 20px
}

.message-thread .conversation-scroll {
   padding: 22px 18px
}

.message-thread .chat-composer {
   padding: 16px
}

.message-thread .chat-byline {
   flex-wrap: wrap
}

.mobile-message-back {
   display: none
}

.messages-content {
   min-height: calc(100% - 190px)
}

.workspace-tabs {
   overflow-x: auto;
   scrollbar-width: thin;
   flex-wrap: nowrap
}

.workspace-tabs>button {
   flex-shrink: 0
}

@media(max-width:1100px) {
   .messages-workspace {
      grid-template-columns: 190px minmax(0, 1fr)
   }

   .channel-list>button {
      padding: 15px 10px
   }

   .channel-icon {
      display: none
   }

   .duty-summary {
      flex-wrap: wrap;
      gap: 20px
   }

   .duty-summary>.app-button {
      margin-left: 0
   }

   .passenger-grid,
   .assignment-list {
      grid-template-columns: 1fr
   }

   .transport-driver {
      padding: 20px;
      gap: 13px
   }

   .transport-car {
      width: 60px;
      height: 55px
   }

   .transport-car>.app-icon {
      --icon-size: 30px !important
   }

   .transport-driver strong {
      font-size: 16px
   }

   .transport-stops {
      flex-direction: column;
      gap: 20px
   }
}

@media(max-width:700px) {

   .leg-grid,
   .passenger-grid,
   .assignment-list {
      grid-template-columns: 1fr
   }

   .duty-summary {
      padding: 20px;
      gap: 18px
   }

   .duty-summary>div {
      flex: 1
   }

   .duty-summary>.app-button {
      width: 100%
   }

   .workflow-card-body {
      padding: 20px
   }

   .workflow-action-row {
      gap: 8px
   }

   .workflow-action-row>.app-button {
      font-size: 11px;
      flex: 1
   }

   .transport-driver {
      flex-wrap: wrap
   }

   .transport-driver>.app-button {
      font-size: 11px
   }

   .transport-driver p {
      font-size: 10px
   }

   .transport-progress {
      padding: 15px 8px
   }

   .transport-progress small {
      font-size: 8px
   }

   .person-summary {
      gap: 10px
   }

   .person-summary h3 {
      font-size: 16px
   }

   .checkin-heading h3 {
      font-size: 22px
   }

   .mechanical-banner {
      flex-wrap: wrap
   }

   .messages-workspace {
      height: 560px;
      display: block
   }

   .channel-list {
      height: 100%;
      border: 0
   }

   .channel-list>button {
      padding: 20px
   }

   .channel-icon {
      display: grid
   }

   .channel-list strong {
      font-size: 13px
   }

   .channel-list small {
      font-size: 11px
   }

   .message-thread {
      display: none;
      height: 100%
   }

   .thread-open .channel-list {
      display: none
   }

   .thread-open .message-thread {
      display: flex
   }

   .mobile-message-back {
      display: flex;
      padding: 14px 20px;
      border-bottom: 1px solid var(--line);
      font-size: 12px
   }

   .message-thread .conversation-audience {
      padding: 15px 20px
   }

   .date-filter {
      margin: 4px 16px
   }

   .role-transport .filter-tabs {
      display: none
   }

   .role-transport .flight-header-right>.status-badge {
      display: none
   }

   .role-transport .flight-inbox .inbox-top {
      padding-bottom: 12px
   }
}

.public-display-shell {
   min-height: 100dvh;
   background: var(--ops-surface)
}

.public-display-shell>header {
   display: flex;
   gap: 35px;
   align-items: center;
   padding: 25px 35px;
   background: #292929;
   color: white
}

.public-display-shell>header img {
   width: 185px;
   height: 55px;
   object-fit: contain
}

.public-display-shell>header strong {
   font-size: 18px
}

.public-display-shell>header p {
   font-size: 11px;
   color: #bababa;
   margin-top: 5px
}

.public-display-shell>header>span {
   margin-left: auto;
   font-size: 20px
}

/* The schedule and map stack independently; map height never stretches controls. */
.full-display {
   display: grid;
   grid-template-columns: minmax(0, 1.08fr) minmax(0, 1fr);
   align-items: start;
   gap: 28px;
   max-width: 1900px;
   margin: 0 auto;
   padding: 28px
}

.public-flight-list {
   min-width: 0;
   border: 1px solid var(--line);
   border-radius: 18px;
   background: var(--ops-surface);
   overflow: hidden
}

.public-board-toolbar {
   display: flex;
   align-items: center;
   justify-content: space-between;
   gap: 16px;
   padding: 22px 24px 0
}

.public-board-toolbar>.segmented { margin: 0; flex-shrink: 0 }
.public-board-toolbar>.segmented button { padding: 10px 18px; min-height: 40px; font-size: 13px }
.public-board-toolbar>span { color: var(--muted-strong); font-size: 13px }
.public-board-heading { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 26px 24px 24px }
.public-board-heading h1 { font-size: clamp(28px, 2.3vw, 38px); line-height: 1.2; letter-spacing: -.04em; margin: 7px 0 8px }
.public-board-heading p { margin: 0; font-size: 12px; color: var(--muted-strong) }
.public-board-heading .public-board-eyebrow { font-size: 10px; font-weight: 650; letter-spacing: .12em }
.public-flight-count { font-size: 12px; color: var(--muted-strong); white-space: nowrap }
.public-flight-columns, .public-flight-row { display: grid; grid-template-columns: .7fr 1.4fr 1.2fr 1fr; gap: 16px; align-items: center; padding: 0 24px }
.public-flight-columns { min-height: 38px; background: var(--ops-soft); border-block: 1px solid var(--line); font-size: 10px; letter-spacing: .08em; text-transform: uppercase; color: var(--muted-strong) }
.public-flight-columns>span:last-child { text-align: right; padding-right: 23px }
.public-flight-row { position: relative; width: 100%; min-height: 96px; border: 0; border-bottom: 1px solid var(--line); background: transparent; text-align: left; color: inherit; font: inherit; cursor: pointer; transition: background .18s }
.public-flight-row.is-current { background: #3081b013 }
.public-flight-row.is-current:before { content: ''; position: absolute; inset: 18px auto 18px 0; width: 3px; background: #2786b7; border-radius: 0 3px 3px 0 }
.public-flight-row:focus-visible { outline: 2px solid #2786b7; outline-offset: -3px }
.public-flight-time { font-size: clamp(18px, 1.6vw, 25px); font-weight: 550; letter-spacing: -.04em; font-variant-numeric: tabular-nums }
.public-flight-time small { display: block; font-size: 10px; letter-spacing: .04em; color: var(--muted-strong); margin-top: 4px }
.public-flight-place, .public-flight-aircraft { min-width: 0 }
.public-flight-place strong, .public-flight-aircraft strong { display: block; font-size: 14px; font-weight: 550; line-height: 1.4 }
.public-flight-place small, .public-flight-aircraft small { display: block; font-size: 11px; color: var(--muted-strong); margin-top: 5px; line-height: 1.4 }
.public-flight-status { display: flex; align-items: center; justify-content: flex-end; gap: 8px }
.public-flight-status .status-badge { font-size: 11px; white-space: nowrap }
.public-flight-status>.app-icon { flex-shrink: 0; opacity: .2 }
.public-flight-row.is-current .public-flight-status>.app-icon { color: #2786b7; opacity: 1 }
.public-board-footer { display: flex; justify-content: space-between; flex-wrap: wrap; gap: 8px; padding: 17px 24px; font-size: 11px; color: var(--muted-strong) }
.public-flight-context { min-width: 0; display: flex; flex-direction: column; gap: 22px }
.public-flight-context>.ops-map { height: clamp(300px, 29vw, 470px); margin: 0; border-radius: 18px }
.public-flight-context>.wx-panel { margin: 0 }
[data-theme=dark] .public-flight-row.is-current { background: #3789ba18 }
[data-theme=dark] .public-flight-row.is-current:before { background: #63b5e2 }
[data-theme=dark] .public-flight-row.is-current .public-flight-status>.app-icon { color: #8dceef }

@media (max-width:1100px) {
   .full-display { grid-template-columns: 1fr; max-width: 850px; gap: 22px }
   .public-flight-context>.ops-map { height: 360px }
}

@media (max-width:560px) {
   .public-board-toolbar, .public-board-heading { padding-left: 16px; padding-right: 16px }
   .public-flight-columns, .public-flight-row { grid-template-columns: .65fr 1.3fr 1fr; gap: 10px; padding-inline: 16px }
   .public-flight-columns>span:nth-child(3) { display: none }
   .public-flight-row { min-height: 110px; padding-block: 16px; row-gap: 4px }
   .public-flight-time { grid-column: 1; grid-row: 1 / 3 }
   .public-flight-place { grid-column: 2; grid-row: 1 }
   .public-flight-aircraft { grid-column: 2; grid-row: 2 }
   .public-flight-aircraft strong { font-size: 11px; color: var(--muted-strong) }
   .public-flight-aircraft small { display: none }
   .public-flight-status { grid-column: 3; grid-row: 1 / 3 }
   .public-flight-place strong { font-size: 13px }
   .public-board-footer { padding-inline: 16px }
}

@media(max-width:700px) {
   .public-display-shell>header {
      padding: 20px;
      gap: 18px
   }

   .public-display-shell>header img {
      width: 130px
   }

   .public-display-shell>header>span {
      display: none
   }

   .public-display-shell>header strong {
      font-size: 13px
   }

   .full-display {
      display: flex;
      padding: 20px
   }

   .full-display>.ops-map {
      height: 360px;
      flex-shrink: 0
   }
}

.mobile-flight-picker,
.mobile-role-nav {
   display: none
}

@media(max-width:700px) {

   .role-pilot .flight-inbox,
   .role-transport .flight-inbox {
      display: none
   }

   .mobile-flight-picker {
      display: flex;
      flex-direction: column;
      gap: 6px;
      padding: 14px 18px;
      border-bottom: 1px solid var(--line);
      background: var(--ops-surface)
   }

   .mobile-flight-picker label {
      font-size: 10px;
      color: var(--muted)
   }

   .mobile-flight-picker select {
      width: 100%;
      font-size: 12px;
      color: var(--ink);
      padding: 9px;
      border: 1px solid var(--line);
      border-radius: 6px;
      background: var(--ops-soft)
   }

   .mobile-role-nav {
      display: flex;
      position: fixed;
      bottom: 0;
      left: 0;
      right: 0;
      z-index: 12;
      height: 67px;
      padding: 6px 9px max(7px, env(safe-area-inset-bottom));
      background: var(--ops-surface);
      border-top: 1px solid var(--line);
      box-shadow: 0 -3px 18px #00000010
   }

   .mobile-role-nav>button {
      flex: 1;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: 7px;
      color: var(--muted);
      font-size: 9px
   }

   .mobile-role-nav>button.active {
      color: var(--blue)
   }

   .role-pilot,
   .role-transport {
      padding-bottom: 70px
   }

   .role-pilot .flight-header,
   .role-transport .flight-header {
      padding: 17px 18px;
      gap: 14px
   }

   .role-pilot .flight-header .route-heading,
   .role-transport .flight-header .route-heading {
      gap: 12px
   }

   .role-pilot .flight-header .flight-symbol,
   .role-transport .flight-header .flight-symbol {
      width: 43px;
      height: 43px
   }

   .role-pilot .flight-header h2,
   .role-transport .flight-header h2 {
      font-size: 24px
   }

   .role-pilot .flight-header-right,
   .role-transport .flight-header-right {
      display: none
   }

   .role-transport .workspace-tabs {
      display: none
   }

   .role-pilot .workspace-tabs {
      position: static
   }

   .role-pilot .workspace-content,
   .role-transport .workspace-content {
      padding-top: 18px
   }

   .role-pilot .messages-workspace,
   .role-transport .messages-workspace {
      height: calc(100dvh - 325px);
      min-height: 410px
   }

   .role-pilot .messages-content,
   .role-transport .messages-content {
      padding-bottom: 10px
   }

   .role-pilot .messages-content .workspace-footnote,
   .role-transport .messages-content .workspace-footnote {
      display: none
   }

   .toast-message {
      bottom: 78px
   }

   .header-end>.header-icon[aria-label^="Open"] {
      display: inline-flex;
      padding: 4px
   }
}

/* Bootstrap display utilities must yield to the mobile application layout. */
@media(max-width:950px) {
   .user-label.d-flex {
      display: none !important
   }
}

@media(max-width:700px) {
   .inbox-footer.d-flex {
      display: none !important
   }

   .role-pilot .flight-inbox.d-flex,
   .role-transport .flight-inbox.d-flex {
      display: none !important
   }

   .role-pilot .flight-header-right.d-flex,
   .role-transport .flight-header-right.d-flex {
      display: none !important
   }

   .role-transport .workspace-tabs.d-flex {
      display: none !important
   }

   .role-transport .flight-header-right>.status-badge {
      display: none !important
   }

   .header-end {
      min-width: 0
   }

   .app-header {
      overflow: hidden
   }

   .mobile-role-nav {
      padding-bottom: 9px
   }

   .mobile-role-nav .app-icon {
      display: inline-flex
   }

   /* The pilot reads a long workspace one-handed, and the header carries the only
      way out of the flight — Messages, Contacts, the theme control — so it rides
      along instead of scrolling off the top. The page itself is the scroller at
      this width (`.dashboard-layout` goes `height:auto; display:block`), so
      `sticky` pins to the viewport rather than to an inner overflow box. The tab
      row is already sticky at `top:0`; it now parks under the header instead of
      sliding beneath it, offset by the header's real height rather than a second
      copy of the number. Hub shells are excluded: they own a `100dvh` column that
      never scrolls its header away, so sticky there would do nothing. */
   .role-pilot:not(.hub-shell) {
      --mobile-header-h: 62px
   }

   .role-pilot:not(.hub-shell)>.app-header {
      position: sticky;
      top: 0
   }

   .role-pilot:not(.hub-shell) .workspace-tabs {
      top: var(--mobile-header-h)
   }
}

@media(min-width:701px) {
   .workspace-tabs {
      gap: 12px;
      padding-left: 24px;
      padding-right: 24px
   }

   .workspace-tabs>button {
      padding: 17px 5px;
      font-size: 12px;
      gap: 7px
   }

   .messages-content {
      height: calc(100% - 188px);
      min-height: 420px
   }

   .messages-workspace {
      height: 100%;
      min-height: 340px;
      flex: 1
   }

   .messages-content>.workspace-footnote {
      flex-shrink: 0
   }

   .message-thread .conversation-layout {
      overflow: hidden
   }
}

/* --- Live position -------------------------------------------------------- */
.map-route {
   position: absolute;
   inset: 0;
   width: 100%;
   height: 100%;
   overflow: visible;
   pointer-events: none
}

.map-route-line {
   fill: none;
   stroke: #29292938;
   stroke-width: 3px;
   stroke-linecap: round;
   vector-effect: non-scaling-stroke
}

.map-route-flown {
   fill: none;
   stroke: var(--blue);
   stroke-width: 3px;
   stroke-linecap: round;
   vector-effect: non-scaling-stroke;
   transition: stroke-dasharray 1.2s linear
}

[data-theme=dark] .map-route-line {
   stroke: #ffffff33
}

.map-endpoint {
   position: absolute;
   transform: translate(-50%, -210%);
   display: inline-flex;
   align-items: center;
   gap: 5px;
   padding: 5px 9px;
   border-radius: 20px;
   font-size: 11px;
   font-weight: 600;
   white-space: nowrap;
   color: #fff;
   background: #393939ee;
   box-shadow: 0 2px 8px #00000030
}

.map-endpoint::after {
   content: '';
   position: absolute;
   top: 100%;
   left: 50%;
   transform: translate(-50%, 4px);
   width: 8px;
   height: 8px;
   border-radius: 50%;
   background: inherit;
   box-shadow: 0 0 0 3px #ffffffcc
}

.map-endpoint.destination {
   background: #0c5f45ee;
   transform: translate(-50%, 110%)
}

.map-endpoint.destination::after {
   top: auto;
   bottom: 100%;
   transform: translate(-50%, -4px)
}

.map-aircraft {
   position: absolute;
   transform: translate(-50%, -50%);
   display: inline-flex;
   align-items: center;
   gap: 6px;
   padding: 6px 10px 6px 7px;
   border-radius: 22px;
   font-size: 11px;
   font-weight: 700;
   color: #fff;
   background: var(--blue);
   box-shadow: 0 3px 14px #6e6e6e55;
   transition: left 1.2s linear, top 1.2s linear
}

.map-aircraft .app-icon {
   transform: rotate(var(--heading, 0deg))
}

/* One ping per position report, not a decorative loop. */
.map-ping {
   position: absolute;
   inset: -5px;
   border-radius: 26px;
   border: 2px solid #6e6e6e66;
   pointer-events: none;
   animation: livePing 1.6s ease-out 1 both
}

@keyframes livePing {
   0% {
      transform: scale(.9);
      opacity: .9
   }

   100% {
      transform: scale(1.35);
      opacity: 0
   }
}

.trip-progress {
   padding: 19px 22px 21px;
   border-top: 1px solid var(--line);
   display: flex;
   flex-direction: column;
   gap: 13px
}

.trip-progress-track {
   position: relative;
   height: 6px;
   border-radius: 6px;
   background: var(--ops-soft);
   margin: 10px 0
}

.trip-progress-bar {
   position: absolute;
   inset: 0 auto 0 0;
   width: calc(var(--progress) * 100%);
   border-radius: 6px;
   background: linear-gradient(90deg, #6e6e6e, #9c9c9c);
   transition: width 1.2s linear
}

.trip-progress-thumb {
   position: absolute;
   top: 50%;
   left: calc(var(--progress) * 100%);
   transform: translate(-50%, -50%);
   width: 27px;
   height: 27px;
   border-radius: 50%;
   display: grid;
   place-items: center;
   color: #fff;
   background: var(--blue);
   box-shadow: 0 2px 9px #6e6e6e55;
   transition: left 1.2s linear
}

.trip-progress-ends {
   display: flex;
   gap: 14px;
   font-size: 11px;
   color: var(--muted-strong)
}

.trip-progress-ends strong {
   display: block;
   font-size: 13px;
   color: var(--ink)
}

.telemetry-grid {
   display: grid;
   grid-template-columns: repeat(3, minmax(0, 1fr));
   gap: 1px;
   margin: 0;
   padding: 1px;
   background: var(--line);
   border-top: 1px solid var(--line)
}

.telemetry-grid>div {
   padding: 15px 18px;
   background: var(--ops-surface)
}

.telemetry-grid dt {
   font-size: 10px;
   letter-spacing: .08em;
   text-transform: uppercase;
   color: var(--muted-strong)
}

.telemetry-grid dd {
   margin: 5px 0 0;
   font-size: 14px;
   font-weight: 600
}

.ops-map+.trip-progress,
.ops-map+.telemetry-grid {
   border-top: 1px solid var(--line)
}

/* --- Inline surfaces that used to be drawer pages ------------------------- */
.inline-subtabs {
   margin: 16px 22px 4px
}

.inline-form {
   display: flex;
   flex-direction: column;
   gap: 17px;
   padding: 19px 22px 22px
}

.inline-form .form-grid {
   display: grid;
   grid-template-columns: 1fr 1fr;
   gap: 14px
}

.inline-form .form-actions {
   display: flex;
   gap: 10px;
   justify-content: flex-end
}

.transport-edit {
   border-top: 1px solid var(--line)
}

.people-list.is-accordion {
   gap: 0
}

.person-item {
   border-bottom: 1px solid var(--line)
}

.person-item:last-child {
   border-bottom: 0
}

.person-item .person-caret {
   display: grid;
   place-items: center;
   transition: transform .18s var(--ease-standard);
   color: var(--muted-strong)
}

.person-item.is-open .person-caret {
   transform: rotate(90deg);
   color: var(--blue)
}

.person-item.is-open>.person-row {
   background: var(--ops-soft)
}

.person-details {
   display: flex;
   flex-direction: column;
   gap: 15px;
   padding: 6px 4px 22px
}

.person-details.is-inline {
   padding-top: 16px;
   border-top: 1px solid var(--line)
}

.identity-review {
   display: flex;
   flex-direction: column;
   gap: 14px;
   padding: 17px;
   border: 1px solid var(--line);
   border-radius: var(--radius);
   background: var(--ops-soft)
}

.order-verify {
   display: flex;
   flex-direction: column;
   gap: 11px
}

.order-verify .form-actions {
   display: flex;
   gap: 10px;
   justify-content: flex-end;
   margin-top: 6px
}

.activity-body {
   padding: 6px 22px 20px
}

.public-board-inline {
   padding: 20px 22px 22px
}

.leg-chip {
   display: inline-flex;
   align-items: center;
   gap: 5px
}

.leg-chip.green {
   color: var(--green)
}

.leg-chip.amber {
   color: var(--amber)
}

.invoice-strip[aria-disabled=true] {
   opacity: .6
}

/* --- Development-only preview controls ----------------------------------- */
.dev-chip {
   font-size: 9px;
   font-weight: 700;
   letter-spacing: .12em;
   text-transform: uppercase;
   padding: 3px 6px;
   border-radius: 4px;
   color: #d6d6d6;
   background: #393939
}

.dev-tools {
   position: fixed;
   left: 16px;
   bottom: 16px;
   z-index: 40;
   display: flex;
   flex-direction: column-reverse;
   gap: 9px;
   align-items: flex-start;
   font-size: 12px
}

.dev-launcher {
   display: flex;
   align-items: center;
   gap: 10px;
   padding: 8px 12px;
   border-radius: 24px;
   color: #efefef;
   background: #222222;
   border: 1px solid #434343;
   box-shadow: 0 6px 22px #1717174d
}

.dev-launcher-role {
   display: flex;
   flex-direction: column;
   text-align: left;
   line-height: 1.3
}

.dev-launcher-role strong {
   font-size: 12px
}

.dev-launcher-role small {
   font-size: 10px;
   color: #ababab
}

.dev-panel {
   width: 300px;
   max-height: min(78dvh, 700px);
   overflow-y: auto;
   padding: 18px;
   border-radius: 12px;
   color: #e8e8e8;
   background: #1d1d1d;
   border: 1px solid #434343;
   box-shadow: 0 18px 46px #10101066
}

.dev-panel-head {
   display: flex;
   flex-direction: column;
   gap: 3px;
   margin-bottom: 16px
}

.dev-panel-head small {
   font-size: 10px;
   color: #a3a3a3
}

.dev-panel fieldset {
   border: 0;
   padding: 0;
   margin: 0 0 18px
}

.dev-panel legend {
   font-size: 10px;
   letter-spacing: .1em;
   text-transform: uppercase;
   color: #a3a3a3;
   margin-bottom: 8px
}

.dev-roles {
   display: flex;
   flex-direction: column;
   gap: 6px
}

.dev-roles button {
   display: flex;
   align-items: center;
   gap: 10px;
   width: 100%;
   text-align: left;
   padding: 10px 11px;
   border: 1px solid #3f3f3f;
   border-radius: 8px;
   color: #dedede;
   background: #242424
}

.dev-roles button>span:first-child {
   display: flex;
   flex-direction: column;
   line-height: 1.35
}

.dev-roles button small {
   font-size: 10px;
   color: #a5a5a5
}

.dev-roles button.selected {
   border-color: #9b9b9b;
   background: #353535;
   color: #fff
}

.dev-device {
   margin-left: auto;
   font-size: 9px;
   letter-spacing: .06em;
   text-transform: uppercase;
   padding: 3px 6px;
   border-radius: 4px;
   background: #3e3e3e;
   color: #c4c4c4
}

.dev-device.desktop {
   background: #1c4636;
   color: #8fe0bb
}

.dev-segmented {
   display: flex;
   gap: 6px
}

.dev-segmented button {
   flex: 1;
   padding: 9px;
   border: 1px solid #3f3f3f;
   border-radius: 7px;
   color: #d6d6d6;
   background: #242424;
   font-size: 11px
}

.dev-segmented button.selected {
   border-color: #9b9b9b;
   background: #353535;
   color: #fff
}

.dev-links {
   display: flex;
   flex-wrap: wrap;
   gap: 6px
}

.dev-links button {
   padding: 8px 10px;
   border: 1px solid #3f3f3f;
   border-radius: 7px;
   color: #d6d6d6;
   background: #242424;
   font-size: 11px
}

.dev-hint {
   font-size: 10px;
   line-height: 1.6;
   color: #a3a3a3;
   margin: 0
}

.dev-hint b {
   color: #dedede
}

.dev-panel button:focus-visible,
.dev-launcher:focus-visible {
   outline: 2px solid #bcbcbc;
   outline-offset: 2px
}

/* Mobile-only roles previewed in a real nested phone viewport. */
.device-stage {
   min-height: 100dvh;
   display: flex;
   align-items: center;
   justify-content: center;
   gap: 64px;
   flex-wrap: wrap;
   padding: 48px;
   background: radial-gradient(circle at 22% 18%, #343434, #181818 62%)
}

.device-stage-info {
   max-width: 330px;
   color: #e6e6e6;
   display: flex;
   flex-direction: column;
   gap: 11px;
   align-items: flex-start
}

.device-stage-info h2 {
   font-size: 31px;
   color: #fff
}

.device-stage-info p {
   font-size: 13px;
   color: #bbbbbb;
   line-height: 1.65
}

.device-stage-note {
   font-size: 12px !important;
   padding: 13px 15px;
   border: 1px solid #464646;
   border-radius: 9px;
   background: #272727
}

.device-stage-info dl {
   display: flex;
   flex-direction: column;
   gap: 12px;
   margin: 5px 0 0;
   width: 100%
}

.device-stage-info dt {
   font-size: 10px;
   letter-spacing: .1em;
   text-transform: uppercase;
   color: #979797
}

.device-stage-info dd {
   margin: 4px 0 0;
   font-size: 12px;
   color: #dadada;
   line-height: 1.6
}

.device-frame {
   position: relative;
   width: var(--device-width, 393px);
   height: min(852px, 88dvh);
   flex-shrink: 0;
   padding: 11px;
   border-radius: 46px;
   background: #0c0c0c;
   border: 1px solid #4e4e4e;
   box-shadow: 0 32px 80px #08080899, inset 0 0 0 3px #2b2b2b
}

.device-frame iframe {
   width: 100%;
   height: 100%;
   border: 0;
   border-radius: 36px;
   background: #fff;
   display: block
}

@media(max-width:1100px) {
   .device-stage {
      gap: 32px;
      padding: 28px
   }

   .device-stage-info {
      max-width: none
   }
}

/* The app inside the phone frame keeps its own dvh sizing and skips the launcher. */
.app-shell.in-device-frame {
   min-height: 100dvh
}

@media(max-width:700px) {
   .dev-tools {
      left: 10px;
      bottom: 78px
   }

   .dev-panel {
      width: min(300px, calc(100vw - 24px))
   }
}

@media(max-width:700px) {
   .telemetry-grid {
      grid-template-columns: repeat(2, minmax(0, 1fr))
   }

   .telemetry-grid>div {
      padding: 13px 15px
   }

   .inline-form {
      padding: 17px 18px 20px
   }

   .inline-form .form-grid {
      grid-template-columns: 1fr
   }

   .inline-subtabs {
      margin: 14px 18px 2px
   }

   .trip-progress {
      padding: 17px 18px 19px
   }

   .person-details {
      padding: 4px 2px 18px
   }

   .activity-body,
   .public-board-inline {
      padding-left: 18px;
      padding-right: 18px
   }
}

[data-theme=dark] .telemetry-grid {
   background: #393939
}

[data-theme=dark] .telemetry-grid>div {
   background: #212121
}

[data-theme=dark] .identity-review,
[data-theme=dark] .person-item.is-open>.person-row {
   background: #212121
}

/* ==========================================================================
   Ops palette — near-black default
   The dark cockpit rule: normal states stay neutral, and colour is spent only
   on the exceptions. Saturated hues belong to state, never to chrome.
   ========================================================================== */
:root {
   --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace
}

:root[data-theme=dark] {
   --ink: #ececec;
   --muted: #969696;
   --muted-strong: #a4a4a4;
   --line: #262626;
   --bs-body-color: #ececec;
   --bs-border-color: #262626;
   --ops-ground: #0a0a0a;
   --ops-panel: #111111;
   --ops-raised: #191919;
   --ops-rail: #070707;
   --ops-surface: #111111;
   --ops-soft: #0a0a0a;
   --state-normal: #34d399;
   --state-caution: #ffc233;
   --state-warning: #ff5f56;
   --state-info: #b7b7b7;
   --state-advisory: #3d90dd;
   --state-inactive: #8c8c8c;
   background: #070707;
}

:root[data-theme=dark] body,
[data-theme=dark] .workspace {
   background: var(--ops-ground)
}

[data-theme=dark] .app-header {
   background: linear-gradient(110deg, #0f0f0f, #090909);
   box-shadow: 0 1px 0 #262626
}

[data-theme=dark] .flight-inbox {
   background: var(--ops-rail);
   border-color: var(--line)
}

[data-theme=dark] .flight-header,
[data-theme=dark] .workspace-tabs {
   background: var(--ops-panel);
   border-color: var(--line)
}

[data-theme=dark] .surface-card,
[data-theme=dark] .aircraft-summary,
[data-theme=dark] .invoice-strip,
[data-theme=dark] .dynamic-drawer,
[data-theme=dark] .chat-composer {
   background: var(--ops-panel);
   border-color: var(--line)
}

[data-theme=dark] .flight-row {
   background: var(--ops-raised);
   border-color: #2b2b2b;
   box-shadow: none
}

[data-theme=dark] .flight-row.is-selected {
   background: #1f1f1f;
   border-color: var(--state-info);
   box-shadow: inset 3px 0 0 var(--state-info)
}

[data-theme=dark] .inbox-footer {
   background: var(--ops-rail);
   border-color: var(--line)
}

[data-theme=dark] .search-box,
[data-theme=dark] .square-button,
[data-theme=dark] .filter-tabs {
   background: var(--ops-raised);
   border-color: #2b2b2b
}

[data-theme=dark] .search-box input,
[data-theme=dark] .form-field .form-control,
[data-theme=dark] .custom-select-trigger,
[data-theme=dark] .chat-composer textarea {
   background: #0e0e0e;
   border-color: #2d2d2d
}

/* Groups carry a single hairline of state, not a filled tint. */
[data-theme=dark] .flight-group,
[data-theme=dark] .flight-group.green,
[data-theme=dark] .flight-group.blue {
   background: var(--ops-panel);
   border-color: var(--line)
}

[data-theme=dark] .flight-group.amber {
   background: var(--ops-panel);
   border-color: #6b5526
}

[data-theme=dark] .attention-card {
   background: #17120a;
   border-color: #6b5526
}

[data-theme=dark] .attention-items>button {
   background: #1c1710;
   border-color: #40331c
}

[data-theme=dark] .activity-strip,
[data-theme=dark] .note,
[data-theme=dark] .saved-payment,
[data-theme=dark] .panel-flight-summary,
[data-theme=dark] .card-footer-action,
[data-theme=dark] .identity-review,
[data-theme=dark] .person-item.is-open>.person-row {
   background: var(--ops-raised);
   border-color: #2b2b2b
}

[data-theme=dark] .custom-select-menu,
[data-theme=dark] .toast-message {
   background: var(--ops-raised);
   border-color: #363636
}

[data-theme=dark] .telemetry-grid {
   background: var(--line)
}

[data-theme=dark] .telemetry-grid>div {
   background: var(--ops-panel)
}

/* Status colour discipline. */
[data-theme=dark] .status-badge.green {
   background: #0e2a20;
   color: var(--state-normal)
}

[data-theme=dark] .status-badge.amber {
   background: #33260a;
   color: var(--state-caution)
}

[data-theme=dark] .status-badge.blue {
   background: #222222;
   color: var(--state-info)
}

[data-theme=dark] .status-badge.gray {
   background: #1c1c1c;
   color: var(--state-inactive)
}

[data-theme=dark] .status-badge.red {
   background: #2c1210;
   color: var(--state-warning)
}

[data-theme=dark] .leg-chip.green {
   color: var(--state-normal)
}

[data-theme=dark] .leg-chip.amber {
   color: var(--state-caution)
}

/* Night map: the artwork is a daylight export, so it is dimmed rather than inverted. */
[data-theme=dark] .map-image {
   filter: brightness(.42) saturate(.5) contrast(1.12)
}

[data-theme=dark] .map-route-line {
   stroke: #ffffff2e
}

/* Tabular figures — times, tails, quantities and altitudes line up in columns. */
.flight-time,
.zulu-time,
.telemetry-grid dd,
.fuel-numbers strong,
.amount-due strong,
.review-total strong,
.board-table td,
.trip-progress-ends strong,
.duty-summary strong,
.tower-time,
.tower-tail,
.tower-clock strong {
   font-family: var(--font-mono);
   font-variant-numeric: tabular-nums;
   letter-spacing: -.01em
}

.zulu-time {
   font-size: 10px;
   color: var(--muted-strong);
   letter-spacing: .02em
}

.flight-row-top .zulu-time {
   margin-left: -4px
}

/* ==========================================================================
   Master caution annunciator
   Unlit when nothing needs attention. Amber = act soon, red = act now.
   ========================================================================== */
.annunciator {
   display: flex;
   align-items: center;
   gap: 9px;
   padding: 6px 12px 6px 10px;
   border-radius: 6px;
   border: 1px solid #ffffff1c;
   background: #ffffff08;
   color: #6e6e6e;
   text-align: left
}

.annunciator-lamp {
   width: 9px;
   height: 9px;
   border-radius: 2px;
   background: #424242;
   flex-shrink: 0
}

.annunciator strong {
   display: block;
   font-size: 10px;
   font-weight: 700;
   letter-spacing: .15em
}

.annunciator small {
   display: block;
   font-size: 9px;
   letter-spacing: .05em;
   opacity: .85;
   margin-top: 2px
}

.annunciator.caution {
   border-color: #ffc23359;
   background: #ffc2331c;
   color: #ffcd76
}

.annunciator.caution .annunciator-lamp {
   background: #ffc233;
   box-shadow: 0 0 9px #ffc23399
}

.annunciator.warning {
   border-color: #ff5f5659;
   background: #ff5f561f;
   color: #ffa39d
}

.annunciator.warning .annunciator-lamp {
   background: #ff5f56;
   box-shadow: 0 0 9px #ff5f5699
}

/* Timing and status stay on the same side of the route when the header wraps. */
.flight-header-right {
   flex-wrap: nowrap
}

.flight-alerts {
   flex-shrink: 0;
   min-height: 44px;
   border-color: var(--line);
   color: var(--muted-strong)
}

.flight-alerts strong {
   font-size: 14px;
   letter-spacing: 0
}

.flight-alerts small {
   font-size: 12px;
   letter-spacing: 0
}

[data-theme=light] .flight-alerts.warning {
   color: #a32b23
}

[data-theme=light] .flight-alerts.caution {
   color: #805300
}

@media(max-width:700px) {
   .role-pilot .flight-header-right.d-flex {
      display: flex !important;
      width: auto
   }

   .role-pilot .flight-header-right>:not(.flight-alerts) {
      display: none
   }

   .flight-alerts .annunciator-text {
      display: block !important
   }

   .flight-alerts .annunciator-count {
      display: none
   }
}

/* Two pulses at ~1.8 Hz — well under the 3 Hz flash threshold, and self-limiting. */
.annunciator.is-alerting {
   animation: annunciate .56s ease-out 2
}

@keyframes annunciate {

   0%,
   100% {
      box-shadow: 0 0 0 0 transparent
   }

   45% {
      box-shadow: 0 0 0 4px #ffc23333
   }
}

.annunciator.warning.is-alerting {
   animation-name: annunciateWarning
}

@keyframes annunciateWarning {

   0%,
   100% {
      box-shadow: 0 0 0 0 transparent
   }

   45% {
      box-shadow: 0 0 0 4px #ff5f5638
   }
}

/* State changes earn the motion: a row pulses when its state actually moves. */
.flight-row.is-changed-caution {
   animation: rowCaution .6s ease-out 2
}

.flight-row.is-changed-warning {
   animation: rowWarning .6s ease-out 2
}

.flight-row.is-changed-normal {
   animation: rowNormal .6s ease-out 2
}

@keyframes rowCaution {

   0%,
   100% {
      box-shadow: inset 0 0 0 0 transparent
   }

   50% {
      box-shadow: inset 0 0 0 1px var(--state-caution), 0 0 14px #ffc23333
   }
}

@keyframes rowWarning {

   0%,
   100% {
      box-shadow: inset 0 0 0 0 transparent
   }

   50% {
      box-shadow: inset 0 0 0 1px var(--state-warning), 0 0 14px #ff5f5638
   }
}

@keyframes rowNormal {

   0%,
   100% {
      box-shadow: inset 0 0 0 0 transparent
   }

   50% {
      box-shadow: inset 0 0 0 1px var(--state-normal), 0 0 14px #34d39930
   }
}

/* ==========================================================================
   Density — the dense scan and the comfortable read are a preference, not a fight
   ========================================================================== */
.density-toggle {
   display: flex;
   gap: 2px;
   padding: 3px;
   border-radius: 6px;
   border: 1px solid #ffffff1c;
   background: #ffffff08
}

.density-toggle button {
   padding: 5px 9px;
   border-radius: 4px;
   font-size: 10px;
   letter-spacing: .08em;
   font-weight: 600;
   color: #6e6e6e
}

.density-toggle button[aria-pressed=true] {
   background: #ffffff1a;
   color: #fff
}

[data-density=compact] .flight-row {
   padding: 8px 11px;
   margin-bottom: 4px;
   border-radius: 5px
}

[data-density=compact] .flight-row-top {
   gap: 9px
}

[data-density=compact] .flight-row-meta {
   font-size: 10px
}

[data-density=compact] .flight-row-bottom .flight-reason {
   font-size: 10px
}

[data-density=compact] .flight-row .status-badge {
   font-size: 10px;
   padding: 2px 6px
}

[data-density=compact] .flight-group {
   margin-top: 11px
}

[data-density=compact] .inbox-top {
   padding: 16px 18px 12px
}

[data-density=compact] .inbox-top h1 {
   font-size: 21px
}

[data-density=compact] .workspace-content {
   padding: 18px 24px;
   gap: 13px
}

[data-density=compact] .flight-header {
   padding: 18px 24px 16px
}

[data-density=compact] .route-heading h2 {
   font-size: 29px
}

[data-density=compact] .card-heading {
   padding: 13px 16px
}

[data-density=compact] .readiness-row {
   padding: 9px
}

[data-density=compact] .person-row {
   padding: 9px 0
}

[data-density=compact] .workspace-tabs {
   padding: 0 24px;
   gap: 18px
}

[data-density=compact] .workspace-tabs>button {
   padding: 13px 4px
}

[data-density=compact] .telemetry-grid>div {
   padding: 11px 15px
}

[data-density=compact] .ops-map {
   height: 300px
}

/* ==========================================================================
   Tower view — the operations wall
   ========================================================================== */
.tower {
   min-height: 100dvh;
   display: flex;
   flex-direction: column;
   background: #070707;
   color: #ececec;
   font-variant-numeric: tabular-nums
}

.tower-header {
   display: flex;
   align-items: center;
   gap: 30px;
   padding: 16px 28px;
   background: linear-gradient(110deg, #0f0f0f, #090909);
   border-bottom: 1px solid #262626
}

.tower-header>img {
   width: 168px;
   height: 48px;
   object-fit: contain;
   object-position: left center
}

.tower-station strong {
   display: block;
   font-size: 17px;
   letter-spacing: .06em
}

.tower-station small {
   display: block;
   font-size: 10px;
   letter-spacing: .2em;
   color: #8a8a8a;
   margin-top: 4px
}

.tower-clock {
   display: flex;
   gap: 24px;
   margin-left: auto
}

.tower-clock small {
   display: block;
   font-size: 9px;
   letter-spacing: .2em;
   color: #8a8a8a
}

.tower-clock strong {
   display: block;
   font-size: 26px;
   font-weight: 600;
   letter-spacing: -.02em;
   margin-top: 2px
}

.tower-annunciator {
   padding: 10px 16px 10px 13px
}

.tower-annunciator strong {
   font-size: 11px
}

.tower-body {
   flex: 1;
   display: grid;
   grid-template-columns: minmax(0, 1.45fr) minmax(340px, .85fr);
   gap: 1px;
   background: #262626;
   min-height: 0
}

.tower-board,
.tower-side {
   background: #070707;
   min-height: 0;
   display: flex;
   flex-direction: column
}

.tower-side {
   gap: 1px;
   background: #262626
}

.tower-board-head {
   display: flex;
   align-items: center;
   gap: 16px;
   padding: 15px 24px;
   border-bottom: 1px solid #262626
}

.tower-board-head h2 {
   font-size: 14px;
   letter-spacing: .18em;
   font-weight: 700;
   display: flex;
   align-items: center;
   gap: 11px
}

.tower-board-head h2 span {
   font-family: var(--font-mono);
   font-size: 11px;
   padding: 2px 7px;
   border-radius: 4px;
   background: #191919;
   color: #969696;
   letter-spacing: 0
}

.tower-filters {
   display: flex;
   gap: 5px;
   margin-left: auto
}

.tower-filters button {
   padding: 6px 11px;
   border-radius: 5px;
   border: 1px solid #2b2b2b;
   background: #111111;
   color: #969696;
   font-size: 10px;
   letter-spacing: .12em;
   font-weight: 700
}

.tower-filters button.active {
   border-color: #454545;
   background: #1f1f1f;
   color: #dedede
}

.tower-cycle {
   display: flex;
   align-items: center;
   gap: 7px
}

.tower-cycle.active {
   color: #34d399 !important;
   border-color: #1d4436 !important
}

.tower-scroll {
   flex: 1;
   overflow-y: auto;
   min-height: 0
}

.tower table {
   width: 100%;
   border-collapse: collapse
}

.tower thead th {
   position: sticky;
   top: 0;
   z-index: 1;
   text-align: left;
   padding: 10px 14px;
   font-size: 9px;
   letter-spacing: .2em;
   color: #7b7b7b;
   background: #0a0a0a;
   border-bottom: 1px solid #262626;
   font-weight: 700
}

.tower-row {
   border-bottom: 1px solid #191919;
   animation: towerRowIn var(--dur-slow) var(--ease-entrance) backwards;
   animation-delay: calc(var(--row-index) * 26ms)
}

@keyframes towerRowIn {
   from {
      opacity: 0;
      transform: translateY(-6px)
   }

   to {
      opacity: 1;
      transform: none
   }
}

.tower-row td {
   padding: 13px 14px;
   font-size: 15px;
   color: #d1d1d1
}

.tower-dir {
   font-size: 10px !important;
   letter-spacing: .14em;
   color: #7b7b7b !important;
   font-weight: 700;
   width: 52px
}

.tower-time strong {
   display: block;
   font-size: 17px;
   font-weight: 600;
   color: #ececec
}

.tower-time small {
   display: block;
   font-size: 10px;
   color: #8a8a8a;
   margin-top: 3px
}

.tower-route {
   font-size: 19px !important;
   font-weight: 600;
   color: #ececec !important;
   display: flex;
   align-items: center;
   gap: 10px;
   letter-spacing: .02em
}

.tower-route .app-icon {
   color: #565656
}

.tower-type {
   color: #969696 !important;
   font-size: 13px !important
}

.tower-tail {
   font-weight: 600;
   letter-spacing: .04em
}

.tower-state {
   display: flex;
   align-items: center;
   gap: 9px;
   font-size: 13px !important;
   letter-spacing: .04em
}

/* Lamp = does this flight need attention. Status text = what the flight is doing. */
.tower-lamp {
   width: 8px;
   height: 8px;
   border-radius: 2px;
   background: #424242;
   flex-shrink: 0
}

.lamp-caution .tower-lamp {
   background: var(--state-caution);
   box-shadow: 0 0 8px #ffc23380
}

.lamp-warning {
   background: #1a0f0e
}

.lamp-warning .tower-lamp {
   background: var(--state-warning);
   box-shadow: 0 0 9px #ff5f5699
}

.tone-normal .tower-state {
   color: var(--state-normal) !important
}

.tone-info .tower-state {
   color: var(--state-info) !important
}

.tone-caution .tower-state {
   color: var(--state-caution) !important
}

.tone-inactive td {
   color: #6e6e6e !important
}

.tone-inactive .tower-time strong,
.tone-inactive .tower-route {
   color: #898989 !important
}

.tower-empty {
   padding: 34px;
   text-align: center;
   color: #7b7b7b;
   font-size: 13px
}

.tower-panel-head {
   display: flex;
   align-items: center;
   gap: 9px;
   padding: 11px 16px;
   font-size: 9px;
   letter-spacing: .2em;
   font-weight: 700;
   color: #7b7b7b;
   background: #0a0a0a;
   border-bottom: 1px solid #262626
}

.tower-panel-head b {
   margin-left: auto;
   font-family: var(--font-mono);
   letter-spacing: 0;
   font-size: 11px;
   color: #b5b5b5
}

.tower-map {
   background: #070707;
   display: flex;
   flex-direction: column
}

.tower-map .ops-map {
   height: 300px;
   border: 0;
   border-radius: 0
}

.tower-alerts {
   flex: 1;
   background: #070707;
   display: flex;
   flex-direction: column;
   min-height: 0
}

.tower-alert-list {
   flex: 1;
   overflow-y: auto;
   min-height: 0
}

.tower-alert {
   display: flex;
   align-items: flex-start;
   gap: 11px;
   padding: 13px 16px;
   border-bottom: 1px solid #191919;
   animation: towerRowIn var(--dur-slow) var(--ease-entrance) backwards;
   animation-delay: calc(var(--row-index) * 40ms)
}

.tower-alert .tower-lamp {
   margin-top: 4px
}

.tower-alert strong {
   display: block;
   font-size: 12px;
   color: #dfdfdf;
   letter-spacing: .02em
}

.tower-alert small {
   display: block;
   font-size: 11px;
   color: #8a8a8a;
   margin-top: 3px;
   line-height: 1.5
}

.tower-alert.caution .tower-lamp {
   background: var(--state-caution);
   box-shadow: 0 0 8px #ffc23380
}

.tower-alert.warning {
   background: #1a0f0e
}

.tower-alert.warning .tower-lamp {
   background: var(--state-warning);
   box-shadow: 0 0 9px #ff5f5699
}

.tower-alert.warning strong {
   color: #ffa39d
}

.tower-alert.normal .tower-lamp {
   background: var(--state-normal);
   box-shadow: 0 0 8px #34d39980
}

.tower .weather-strip {
   background: #0a0a0a;
   border: 0;
   border-top: 1px solid #262626;
   border-radius: 0;
   color: #b5b5b5
}

.tower .weather-strip strong,
.tower .weather-strip small {
   color: inherit
}

.tower-footer {
   display: flex;
   justify-content: space-between;
   padding: 11px 28px;
   font-size: 9px;
   letter-spacing: .2em;
   color: #898989;
   background: #0a0a0a;
   border-top: 1px solid #262626
}

@media(max-width:1200px) {
   .tower-body {
      grid-template-columns: minmax(0, 1fr)
   }

   .tower-side {
      flex-direction: row;
      flex-wrap: wrap
   }

   .tower-map,
   .tower-alerts {
      flex: 1 1 340px
   }

   .tower-header {
      flex-wrap: wrap;
      gap: 18px
   }

   .tower-clock {
      margin-left: 0
   }
}

/* The FBO dashboard is a desktop surface; it is not squeezed onto a phone. */
.desktop-only-notice {
   min-height: 100dvh;
   display: flex;
   flex-direction: column;
   align-items: center;
   justify-content: center;
   gap: 15px;
   padding: 40px 28px;
   text-align: center;
   background: var(--ops-ground, #0a0a0a);
   color: var(--ink)
}

.desktop-only-notice .soft-icon {
   width: 64px;
   height: 64px;
   display: grid;
   place-items: center;
   border-radius: 50%;
   background: #191919;
   color: #6e6e6e
}

.desktop-only-notice h2 {
   font-size: 24px
}

.desktop-only-notice p {
   font-size: 13px;
   line-height: 1.7;
   color: var(--muted-strong);
   max-width: 390px
}

/* Severity on the attention list and notification tray: red acts now, amber soon. */
.attention-items>button.severity-warning>.app-icon {
   color: #a32b23
}

.attention-items>button.severity-warning {
   border-left: 3px solid #c0392b
}

[data-theme=dark] .attention-items>button.severity-warning {
   border-left-color: var(--state-warning);
   background: #20100e
}

[data-theme=dark] .attention-items>button.severity-warning>.app-icon {
   color: var(--state-warning)
}

.soft-icon.red {
   background: #fdeceb;
   color: #a32b23
}

[data-theme=dark] .soft-icon.red {
   background: #2c1210;
   color: var(--state-warning)
}

/* Compact reflows the row into two lines: the route line stays clear across the
   full width, and identity and status share the second line. */
[data-density=compact] .flight-row {
   display: grid;
   grid-template-columns: minmax(0, 1fr) auto;
   gap: 3px 10px;
   align-items: center;
   padding: 8px 11px
}

[data-density=compact] .flight-row-top {
   grid-column: 1/-1;
   grid-row: 1
}

[data-density=compact] .flight-row-top>.app-icon {
   margin-left: auto
}

[data-density=compact] .flight-row-meta {
   grid-column: 1;
   grid-row: 2;
   gap: 5px;
   min-width: 0;
   overflow: hidden;
   white-space: nowrap
}

[data-density=compact] .flight-row-meta>span:not(.direction-label) {
   overflow: hidden;
   text-overflow: ellipsis
}

[data-density=compact] .flight-row-meta .direction-label {
   display: none
}

[data-density=compact] .flight-row-bottom {
   grid-column: 2;
   grid-row: 2;
   flex-wrap: nowrap;
   gap: 8px;
   justify-content: flex-end
}

[data-density=compact] .flight-row-bottom .flight-reason {
   font-size: 9px;
   white-space: nowrap
}

/* On a phone the annunciator collapses to the lamp and a count; the accessible
   name on the button still carries the full "MASTER CAUTION, n open items". */
.annunciator-count {
   display: none;
   font-family: var(--font-mono);
   font-size: 12px;
   font-weight: 700
}

@media(max-width:700px) {
   .annunciator {
      padding: 6px 9px;
      gap: 7px
   }

   .annunciator .annunciator-text {
      display: none
   }

   .annunciator-count {
      display: inline
   }
}

/* The device stage sits behind a near-black app, so it goes near-black too. */
.device-stage {
   background: radial-gradient(circle at 22% 16%, #1a1a1a, #070707 64%)
}

.device-stage-note {
   border-color: #2b2b2b;
   background: #111111
}

.device-frame {
   background: #040404;
   border-color: #2b2b2b;
   box-shadow: 0 32px 80px #00000099, inset 0 0 0 3px #191919
}

.device-stage-info dt {
   color: #7b7b7b
}

.device-stage-info dd {
   color: #b5b5b5
}

.device-stage-info p {
   color: #969696
}

/* ==========================================================================
   Hue discipline — saturated hue is state; category hue is identity
   Structure and surfaces stay neutral. Amber, red and green are reserved for
   what a flight is doing and what needs attention, and a restrained steel accent
   marks "you can act on this".

   Category hue is the one exception, and it is kept subordinate three ways: it
   paints the *icon* only and never a label, a fill or an edge; it names a
   destination rather than a condition; and it yields the moment anything is
   outstanding — see the `:not()` rules above. So a coloured icon says *which*
   place, amber and red still say *how it is going*, and the two can never be
   confused for one another.

   Seven destinations, and the state palette owns red, amber and green, so the
   hues are placed in what is left. Neighbours in the tab row are kept far apart on
   the wheel: the closest pair is Fuel's teal and the Messages slate, which are
   four tabs apart and never adjacent. Overview stays neutral on purpose — it is
   the summary of the other seven, not an eighth place to be.

   It lives in work mode only. The flight board has no category classes at all —
   it is a dark-cockpit scan surface whose whole point is that a clean day is
   nearly blank, and identity colour there would compete with the lit cells.
   `tests/palette.test.mjs` locks that.
   ========================================================================== */
:root {
   --navy: #0f0f0f;
   --category-aircraft: #0f90c1;
   --category-aircraft-soft: #e9f5fa;
   --category-crew: #796eb5;
   --category-crew-soft: #f1eff9;
   --category-fuel: #006467;
   --category-fuel-soft: #e6f2f2;
   --category-catering: #c86888;
   --category-catering-soft: #fbeef1;
   --category-passengers: #628039;
   --category-passengers-soft: #f0f4e9;
   --category-transport: #774686;
   --category-transport-soft: #f4ecf6;
   --category-messages: #145b9d;
   --category-messages-soft: #e9eff7;
}

:root[data-theme=dark] {
   --category-aircraft: #5fbde6;
   --category-aircraft-soft: #14252d;
   --category-crew: #b9aeea;
   --category-crew-soft: #211f2e;
   --category-fuel: #4fbfc3;
   --category-fuel-soft: #122726;
   --category-catering: #f2a3b8;
   --category-catering-soft: #2d1d22;
   --category-passengers: #a8c47c;
   --category-passengers-soft: #1f2618;
   --category-transport: #c08fce;
   --category-transport-soft: #271c2b;
   --category-messages: #82b0e8;
   --category-messages-soft: #161f2c;
   --accent: #5e5e5e;
   --accent-text: #a4a4a4;
}

/* Chrome is black in both themes — the brand bar is not a coloured surface. */
.app-header,
[data-theme=dark] .app-header,
.public-display-shell>header,
.tower-header {
   background: linear-gradient(110deg, #0f0f0f, #090909)
}

.app-header {
   box-shadow: 0 1px 0 #262626
}

.aircraft-large-icon {
   color: var(--category-aircraft)
}

/* Dark theme: neutral interaction, so the only saturated things on screen are
   the flight's own state and anything that needs attention. */
[data-theme=dark] {
   --blue: var(--accent-text)
}

[data-theme=dark] .app-button.primary,
[data-theme=dark] .app-button.btn-primary {
   background: var(--accent);
   border-color: #707070;
   color: #fff
}

[data-theme=dark] .app-button.secondary {
   background: #1c1c1c;
   border-color: #393939;
   color: #cdcdcd
}

[data-theme=dark] .soft-view-button {
   background: #1f1f1f;
   border-color: #393939;
   color: #c1c1c1
}

[data-theme=dark] a,
[data-theme=dark] .text-button {
   color: var(--accent-text)
}

[data-theme=dark] .global-nav>button.active:after {
   background: #cdcdcd
}

[data-theme=dark] .workspace-tabs button.active,
[data-theme=dark] .filter-tabs button.selected {
   color: #ececec
}

[data-theme=dark] .filter-tabs button.selected {
   background: #242424
}

[data-theme=dark] .segmented button.active {
   background: #242424;
   color: #ececec
}

/* Selection reads through elevation and a bright neutral bar, not a colour. */
[data-theme=dark] .flight-row.is-selected {
   background: #222222;
   border-color: #525252;
   box-shadow: inset 3px 0 0 #cdcdcd
}

[data-theme=dark] .status-badge.blue {
   background: #212121;
   color: #c1c1c1
}

[data-theme=dark] .soft-icon,
[data-theme=dark] .flight-symbol,
[data-theme=dark] .card-heading-icon,
[data-theme=dark] .channel-icon {
   background: #1f1f1f;
   color: #a5a5a5
}

[data-theme=dark] .chat-message-content>p {
   background: #1c1c1c;
   border-color: #333333;
   color: #cdcdcd
}

[data-theme=dark] .chat-message.own .chat-message-content>p {
   background: #292929;
   border-color: #3f3f3f;
   color: #e4e4e4
}

[data-theme=dark] .notification-dot {
   background: #cdcdcd;
   border-color: #0f0f0f
}

[data-theme=dark] .trip-progress-bar {
   background: #9b9b9b
}

[data-theme=dark] .trip-progress-thumb {
   background: #cdcdcd;
   color: #0f0f0f;
   box-shadow: none
}

[data-theme=dark] .fuel-progress .complete>span {
   background: var(--state-normal);
   color: #090909
}

[data-theme=dark] .tower-filters button.active {
   background: #242424;
   border-color: #525252;
   color: #ececec
}

/* A focus ring is transient and must be unmistakable, so it stays bright white. */
[data-theme=dark] button:focus-visible,
[data-theme=dark] a:focus-visible,
[data-theme=dark] input:focus-visible,
[data-theme=dark] textarea:focus-visible,
[data-theme=dark] select:focus-visible {
   outline-color: #fff
}

/* The aircraft on the map is neutral while everything is normal. */
.map-aircraft {
   background: #ececec;
   color: #0f0f0f;
   box-shadow: 0 3px 14px #00000066
}

.map-aircraft b {
   color: inherit
}

.map-aircraft.alert-caution {
   background: var(--state-caution);
   color: #231800
}

.map-aircraft.alert-warning {
   background: var(--state-warning);
   color: #2b0906
}

.map-ping {
   border-color: #6e6e6e5c
}

.map-aircraft.alert-caution .map-ping {
   border-color: #ffc23380
}

.map-aircraft.alert-warning .map-ping {
   border-color: #ff5f5680
}

[data-theme=dark] .map-route-flown {
   stroke: #e4e4e4
}

[data-theme=dark] .map-endpoint {
   background: #222222ee
}

[data-theme=dark] .map-endpoint.destination {
   background: #222222ee
}

/* A mechanical report grounds the leg — the banner is a warning, not a caution. */
.attention-card.mechanical-banner {
   background: #fdeceb;
   border-color: #f0c2be
}

.attention-card.mechanical-banner>.app-icon {
   color: #a32b23
}

.attention-card.mechanical-banner strong {
   color: #8d241d
}

[data-theme=dark] .attention-card.mechanical-banner {
   background: #1d100e;
   border-color: #4a211d
}

[data-theme=dark] .attention-card.mechanical-banner>.app-icon,
[data-theme=dark] .attention-card.mechanical-banner strong {
   color: var(--state-warning)
}

/* Labels, avatars and group icons are not states and not actions, so they go
   neutral too. The accent survives only where you can actually act: primary
   buttons, links, text buttons and the inline action on an attention row — and on
   the global unread count, which is an advisory state of its own. */
[data-theme=dark] .button-count {
   color: #cdcdcd;
   background: #333333
}

[data-theme=dark] .filter-tabs button.selected span {
   background: #333333;
   color: #cdcdcd
}

[data-theme=dark] .group-icon.blue,
[data-theme=dark] .group-icon.blue>.app-icon {
   color: #a5a5a5
}

[data-theme=dark] .avatar {
   background: #232323;
   border-color: #333333;
   color: #a5a5a5
}

[data-theme=dark] .lead-label {
   background: #333333;
   color: #cdcdcd
}

[data-theme=dark] .activity-strip>.app-icon,
[data-theme=dark] .activity-strip .app-icon {
   color: #a5a5a5
}

[data-theme=dark] .map-marker {
   background: #ececec;
   border-color: #cdcdcd;
   color: #0f0f0f
}

[data-theme=dark] .map-marker>.app-icon,
[data-theme=dark] .map-marker>span {
   color: #0f0f0f
}

[data-theme=dark] .map-marker.selected {
   background: #fff;
   box-shadow: 0 0 0 3px #ffffff40
}

[data-theme=dark] .map-marker.delayed {
   background: var(--state-caution);
   border-color: #e09a12
}

[data-theme=dark] .map-marker.delayed>.app-icon,
[data-theme=dark] .map-marker.delayed>span {
   color: #231800
}

/* Last of the blue chrome: data values, big glyphs, list selection and map dots. */
[data-theme=dark] .fuel-details dd,
[data-theme=dark] .activity-strip strong,
[data-theme=dark] .chat-order-card strong,
[data-theme=dark] .chat-order-card small {
   color: #cdcdcd
}

[data-theme=dark] .aircraft-large-icon,
[data-theme=dark] .aircraft-large-icon>.app-icon,
[data-theme=dark] .transport-car,
[data-theme=dark] .transport-car>.app-icon,
[data-theme=dark] .chat-order-card>.app-icon,
[data-theme=dark] .chat-order-card .app-icon {
   color: #a5a5a5
}

[data-theme=dark] .channel-list>button.active {
   background: #222222;
   color: #ececec;
   box-shadow: inset 3px 0 0 #cdcdcd
}

[data-theme=dark] .channel-list>button.active strong {
   color: #ececec
}

[data-theme=dark] .stop-dot {
   background: #a5a5a5
}

[data-theme=dark] .stop-dot.destination {
   background: #ececec
}

[data-theme=dark] .timeline-marker {
   background: #232323;
   color: #a5a5a5
}

[data-theme=dark] .timeline-item.done .timeline-marker {
   background: #0e2a20;
   color: var(--state-normal)
}

/* Messages: channel selection and the order card are neutral; the send button is a
   real action, so it takes the same steel accent as every other primary action. */
[data-theme=dark] .channel-list button.active {
   background: #222222;
   color: #ececec;
   box-shadow: inset 3px 0 0 #cdcdcd
}

[data-theme=dark] .channel-list button.active strong,
[data-theme=dark] .channel-list button.active small {
   color: #ececec
}

[data-theme=dark] .chat-order-card {
   color: #cdcdcd;
   background: #1c1c1c;
   border-color: #333333
}

[data-theme=dark] .chat-order-card strong,
[data-theme=dark] .chat-order-card small,
[data-theme=dark] .chat-order-card .app-icon {
   color: #cdcdcd
}

[data-theme=dark] .chat-composer button[type=submit] {
   background: var(--accent);
   color: #fff
}

[data-theme=dark] .chat-composer button[type=submit]:disabled {
   background: #2b2b2b;
   color: #858585
}

/* ==========================================================================
   Black and greys — the header is the only blue
   Every neutral above is a true grey (R=G=B) at the same relative luminance it
   had as a slate, so the measured contrast ratios still hold. Red, amber and
   green survive as the only hues in the interface, and they only ever describe
   state. Affordance is carried by luminance instead of colour.
   ========================================================================== */
.app-header,
.public-display-shell>header,
.tower-header {
   background: linear-gradient(110deg, #0d1d33, #0a1626)
}

[data-theme=dark] .app-header {
   background: linear-gradient(110deg, #0d1d33, #0a1626);
   box-shadow: 0 1px 0 #242424
}

:root {
   --state-normal: #147c5a;
   --state-caution: #b06200;
   --state-warning: #a32b23;
   --state-info: var(--state-normal)
}

:root[data-theme=dark] {
   --state-normal: #34d399;
   --state-caution: #ffc233;
   --state-warning: #ff5f56;
   --state-info: var(--state-normal);
   --state-inactive: #8d8d8d
}

/* A primary action is the brightest thing on the surface, not the most colourful. */
.app-button.primary,
.app-button.btn-primary {
   background: #1a1a1a;
   border-color: #1a1a1a;
   color: #fff
}

[data-theme=dark] .app-button.primary,
[data-theme=dark] .app-button.btn-primary {
   background: #e8e8e8;
   border-color: #e8e8e8;
   color: #0a0a0a
}

[data-theme=dark] .chat-composer button[type=submit] {
   background: #e8e8e8;
   color: #0a0a0a
}

[data-theme=dark] .chat-composer button[type=submit]:disabled {
   background: #2b2b2b;
   color: #8d8d8d
}

/* Links and text buttons read as actions through weight and an underline on hover. */
a,
.text-button,
.inline-action {
   color: #1a1a1a;
   text-decoration-color: #6e6e6e
}

[data-theme=dark] a,
[data-theme=dark] .text-button,
[data-theme=dark] .inline-action {
   color: #e8e8e8
}

/* A focus ring must be unmistakable, so it is pure black or pure white. */
button:focus-visible,
a:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible {
   outline: 3px solid #111;
   outline-offset: 3px
}

[data-theme=dark] button:focus-visible,
[data-theme=dark] a:focus-visible,
[data-theme=dark] input:focus-visible,
[data-theme=dark] textarea:focus-visible,
[data-theme=dark] select:focus-visible {
   outline-color: #fff
}

/* Selection is elevation plus a bright bar. */
[data-theme=dark] .flight-row.is-selected {
   background: #1f1f1f;
   border-color: #4a4a4a;
   box-shadow: inset 3px 0 0 #e8e8e8
}

[data-theme=dark] .channel-list button.active {
   box-shadow: inset 3px 0 0 #e8e8e8
}

.map-aircraft {
   background: #f0f0f0;
   color: #0a0a0a
}

[data-theme=dark] .map-route-flown {
   stroke: #e8e8e8
}

.map-ping {
   border-color: #6e6e6e66
}

/* The attention-row action is a chip with its own surface, so it needs a surface
   per theme — not just a text colour. */
.inline-action {
   background: #fbfbfb;
   border-color: #6e6e6e;
   color: #1a1a1a
}

[data-theme=dark] .inline-action {
   background: #2b2b2b;
   border-color: #3d3d3d;
   color: #ededed
}

/* The tail number in the workspace header neutralised too dark to read. */
.route-heading p strong {
   color: #2a2a2a
}

[data-theme=dark] .route-heading p strong {
   color: #b5b5b5
}

/* ==========================================================================
   Normal recedes
   The dark-cockpit rule applied to the positive states: "everything is fine" is
   the quietest thing on the screen, not a filled green panel. Completed and
   confirmed states sit on the surface colour and carry a dim green mark; only
   caution and warning get a filled, coloured treatment that pops.
   ========================================================================== */
.ready-banner {
   background: var(--ops-surface);
   border-color: var(--line);
   color: var(--ink)
}

.ready-banner>.app-icon {
   color: #2f7d5f
}

.ready-banner strong {
   color: var(--ink)
}

.ready-banner span {
   color: var(--muted-strong)
}

[data-theme=dark] .ready-banner {
   background: var(--ops-surface);
   border-color: var(--line)
}

[data-theme=dark] .ready-banner>.app-icon {
   color: #2f9e77
}

/* A confirmed state is a dim mark on a neutral chip, not a green fill. */
.status-badge.green {
   background: #f1f1f1;
   color: #136b4d
}

[data-theme=dark] .status-badge.green {
   background: #1c1c1c;
   color: #2f9e77
}

.leg-chip.green {
   color: #136b4d
}

[data-theme=dark] .leg-chip.green {
   color: #2f9e77
}

.group-icon.green {
   background: #f1f1f1;
   color: #5c5c5c
}

[data-theme=dark] .group-icon.green {
   background: #1c1c1c;
   color: #8d8d8d
}

/* Completed steps: neutral track, dim green tick. */
.catering-progress .done>span,
.transport-progress .done>span,
.fuel-progress .complete>span {
   background: #f1f1f1;
   border-color: #6e6e6e;
   color: #2f7d5f
}

[data-theme=dark] .catering-progress .done>span,
[data-theme=dark] .transport-progress .done>span,
[data-theme=dark] .fuel-progress .complete>span {
   background: #1c1c1c;
   border-color: #333;
   color: #2f9e77
}

.timeline-item.done .timeline-marker {
   background: #f1f1f1;
   border-color: #6e6e6e;
   color: #2f7d5f
}

[data-theme=dark] .timeline-item.done .timeline-marker {
   background: #1c1c1c;
   border-color: #333;
   color: #2f9e77
}

.live-dot {
   background: #2f9e77
}

/* Attention keeps its fill — this is the half that is meant to pop. */
[data-theme=dark] .status-badge.amber {
   background: #33260a;
   color: var(--state-caution)
}

[data-theme=dark] .status-badge.red {
   background: #2c1210;
   color: var(--state-warning)
}

/* Two muted tints on the attention surfaces also sat below AA in the light theme. */
.attention-heading p {
   color: #8a6b3f
}

.mechanical-banner p,
.attention-card p {
   color: #7d5f34
}

[data-theme=dark] .attention-heading p {
   color: #c9a878
}

[data-theme=dark] .mechanical-banner p {
   color: #e0918a
}

[data-theme=dark] .attention-card p {
   color: #c9a878
}

/* Header chrome follows the selected theme, including secondary controls. */
.app-header {
   --header-bg: #fff;
   --header-text: #171717;
   --header-muted: #595959;
   --header-line: #dedede;
   --header-hover: #00000008;
   --header-selected: #e8e8e8;
   --header-caution: #854400;
   --header-warning: #a32b23;
   background: var(--header-bg);
   color: var(--header-text);
   box-shadow: 0 1px 0 var(--header-line)
}

[data-theme=dark] .app-header {
   --header-bg: #000;
   --header-text: #fff;
   --header-muted: #c7c7c7;
   --header-line: #333;
   --header-hover: #ffffff0d;
   --header-selected: #292929;
   --header-caution: #ffcd76;
   --header-warning: #ffa39d;
   background: var(--header-bg);
   box-shadow: 0 1px 0 var(--header-line)
}

.global-nav>button {
   color: var(--header-muted)
}

.global-nav>button.active,
.global-nav>button:hover {
   color: var(--header-text)
}

.demo-label {
   color: var(--header-muted);
   border-color: var(--header-line)
}

.header-icon {
   color: var(--header-muted)
}

.user-label strong {
   color: var(--header-text)
}

.user-label>span {
   color: var(--header-muted)
}

.app-header .global-nav>button:hover,
.app-header .header-icon:hover {
   background: var(--header-hover);
   color: var(--header-text)
}

.app-header .global-nav>button.active:after {
   background: var(--header-text)
}

.app-header .header-divider {
   background: var(--header-line)
}

.app-header .annunciator,
.app-header .density-toggle {
   border-color: var(--header-line);
   background: var(--header-hover);
   color: var(--header-muted)
}

.app-header .annunciator.caution {
   border-color: #b0620066;
   background: #ffc2331c;
   color: var(--header-caution)
}

.app-header .annunciator.warning {
   border-color: #a32b2366;
   background: #ff5f561f;
   color: var(--header-warning)
}

.app-header .header-end .avatar {
   background: var(--header-selected);
   color: var(--header-text);
   border-color: var(--header-line)
}

.app-header .notification-dot {
   border-color: var(--header-bg)
}

.tower-station small,
.tower-clock small {
   color: #b4b4b4
}

/* `--muted` was 4.00:1 on white — the whole muted family needed one notch darker. */
:root {
   --muted: #6e6e6e;
   --muted-strong: #5f5f5f
}

.attention-items>button span,
.attention-items>button small {
   color: #6b5636
}

[data-theme=dark] .attention-items>button span,
[data-theme=dark] .attention-items>button small {
   color: #c9a878
}

[data-theme=dark] .attention-items>button.severity-warning span {
   color: #e0918a
}

.zulu-time {
   color: #5f5f5f
}

[data-theme=dark] .zulu-time {
   color: #9a9a9a
}

/* Counts and density controls use the same header palette. */
.app-header .density-toggle button {
   color: var(--header-muted)
}

.app-header .density-toggle button[aria-pressed=true] {
   background: var(--header-selected);
   color: var(--header-text)
}

/* Unread is advisory, not a fault, so the count takes the advisory blue rather
   than the caution/warning hues — it reads at a glance without claiming something
   is wrong. Solid fill so it carries against both header grounds. */
.app-header .nav-count {
   background: #1f6fd0;
   color: #fff
}

[data-theme=dark] .app-header .nav-count {
   background: var(--state-advisory);
   color: #04121f
}

.button-count {
   background: #e0e0e0;
   color: #1a1a1a
}

[data-theme=dark] .button-count {
   background: #3d3d3d;
   color: #ededed
}

/* Caution is a yellow, not a brown. The hue was sitting at ~29° (orange-brown) and
   reading as mud; it now runs at ~35° in light and 42° in dark. Text can only go so
   bright on a pale chip before it fails AA — on plain white the tab label is the
   binding case at 5.32:1 — so the lift is split: text moves in hue at roughly its old
   luminance, while the bar, border and lamp, which only owe 3:1, go properly bright. */
.status-badge.amber {
   color: #9c5c00
}

/* These three carry unscoped greys that the light-theme clamp darkened; on the
   near-black surface they need to come back up. */
[data-theme=dark] .eyebrow,
[data-theme=dark] .route-heading p,
[data-theme=dark] .workspace-tabs>button,
[data-theme=dark] .schedule span,
[data-theme=dark] .schedule small,
[data-theme=dark] .aircraft-summary p,
[data-theme=dark] .card-heading p {
   color: #9a9a9a
}

[data-theme=dark] .workspace-tabs>button.active {
   color: #f0f0f0
}

/* ==========================================================================
   Attention has to be findable across a dense board
   A 5px dot was hidden on desktop and invisible everywhere else. Anything that
   needs work now carries a count, a coloured edge and a tint — three redundant
   cues, so it survives a glance, a dense row and colour-vision deficiency.
   ========================================================================== */
.workspace-tabs>button {
   position: relative
}

/* No pill. Measured on the dark surface, the old chip's background sat at 1.34–1.66:1
   against the tab behind it — far under the 3:1 a shape needs to register at all, so
   it read as a smudge rather than as a container. Worse, it was costing the digit
   contrast: 7.77:1 on the chip against 12.51:1 on the bare tab. Removing it makes the
   number both cleaner and measurably more legible, and lets the neon reach it.
   Monospaced and tabular so a count never reads as part of the label. */
.tab-count {
   font-family: var(--font-mono);
   font-size: 11.5px;
   font-weight: 700;
   font-variant-numeric: tabular-nums;
   line-height: 1;
   letter-spacing: 0
}

.workspace-tabs>button.has-caution:before,
.workspace-tabs>button.has-warning:before {
   content: '';
   position: absolute;
   top: 0;
   left: 2px;
   right: 2px;
   height: 2px;
   border-radius: 0 0 2px 2px
}

/* Light */
.workspace-tabs>button.has-caution,
.workspace-tabs>button.has-caution>.app-icon {
   color: #9c5c00
}

.workspace-tabs>button.has-caution:before {
   background: #9c5c00
}

.workspace-tabs>button.has-caution {
   --tab-hue: #9c5c00
}

.workspace-tabs>button.has-warning {
   --tab-hue: #a32b23
}

.has-caution .tab-count {
   color: #8a5200
}

.workspace-tabs>button.has-warning,
.workspace-tabs>button.has-warning>.app-icon {
   color: #a32b23
}

.workspace-tabs>button.has-warning:before {
   background: #a32b23
}

.has-warning .tab-count {
   color: #8d241d
}

.has-info .tab-count {
   color: #3a3a3a
}

/* Dark */
[data-theme=dark] .workspace-tabs>button.has-caution,
[data-theme=dark] .workspace-tabs>button.has-caution>.app-icon {
   color: var(--state-caution)
}

[data-theme=dark] .workspace-tabs>button.has-caution:before {
   background: var(--state-caution)
}

[data-theme=dark] .workspace-tabs>button.has-caution {
   --tab-hue: var(--state-caution)
}

[data-theme=dark] .workspace-tabs>button.has-warning {
   --tab-hue: var(--state-warning)
}

[data-theme=dark] .has-caution .tab-count {
   color: #ffca6a
}

[data-theme=dark] .workspace-tabs>button.has-warning,
[data-theme=dark] .workspace-tabs>button.has-warning>.app-icon {
   color: var(--state-warning)
}

[data-theme=dark] .workspace-tabs>button.has-warning:before {
   background: var(--state-warning)
}

[data-theme=dark] .has-warning .tab-count {
   color: #ff9a92
}

[data-theme=dark] .has-info .tab-count {
   color: #ededed
}

/* The left edge marks the open flight only. Severity is carried by the row's own
   tint, border and badge, so it does not need a permanent bar of its own. */
.flight-row {
   position: relative
}

.flight-row:before {
   content: '';
   position: absolute;
   left: 0;
   top: 0;
   bottom: 0;
   width: 3px;
   border-radius: 7px 0 0 7px;
   background: transparent;
   animation: none
}

.flight-row.is-selected:before {
   background: #8b8b8b
}

.flight-row.attention-caution {
   background: #fffaf2;
   border-color: #edd2a0
}

.flight-row.attention-warning {
   background: #fff6f5;
   border-color: #efc8c4
}

[data-theme=dark] .flight-row.is-selected {
   box-shadow: none
}

[data-theme=dark] .flight-row.is-selected:before {
   background: #e8e8e8
}

[data-theme=dark] .flight-row.attention-caution {
   background: #221a0c;
   border-color: #6b5526
}

[data-theme=dark] .flight-row.attention-warning {
   background: #20110f;
   border-color: #4d2420
}

/* A small spatial offset identifies the open flight without another label. */
.flight-row {
   translate: 0;
   transition: translate .2s var(--ease-standard), background .15s, border-color .15s, box-shadow .15s
}

.flight-row.is-selected,
.flight-row.is-selected:hover {
   translate: 6px 0;
   border-color: #929292;
   background-image: linear-gradient(110deg, #ffffff55, #ffffff99);
   box-shadow: -4px 3px 10px #0000000e;
   transform: none
}

[data-theme=dark] .flight-row.is-selected,
[data-theme=dark] .flight-row.is-selected:hover {
   border-color: #ffffff40;
   background-image: linear-gradient(110deg, #ffffff0e, #ffffff06);
   box-shadow: -4px 3px 12px #00000030
}

.flight-row.is-selected .flight-row-top>.app-icon:last-child {
   color: var(--text);
   opacity: 1
}

@media (prefers-reduced-motion: reduce) {
   .flight-row { transition: none }
}

/* The "Needs attention" group header takes the caution colour back. */
.flight-group.is-attention>h2 {
   color: #8a5200
}

.flight-group.is-attention .group-icon.amber {
   background: #f6e2c2;
   color: #8a5200
}

.flight-group.is-attention .group-count {
   background: #f6e2c2;
   color: #8a5200
}

[data-theme=dark] .flight-group.is-attention>h2 {
   color: #ffca6a
}

[data-theme=dark] .flight-group.is-attention .group-icon.amber {
   background: #4a3410;
   color: var(--state-caution)
}

[data-theme=dark] .flight-group.is-attention .group-count {
   background: #4a3410;
   color: #ffca6a
}

/* Readiness rows: the scan surface gets the same edge treatment. */
.readiness-row {
   position: relative
}

.readiness-row.needs-caution,
.readiness-row.needs-warning {
   padding-left: 13px
}

.readiness-row.needs-caution:before,
.readiness-row.needs-warning:before {
   content: '';
   position: absolute;
   left: 0;
   top: 4px;
   bottom: 4px;
   width: 3px;
   border-radius: 2px
}

.readiness-row.needs-caution:before {
   background: #c87800
}

.readiness-row.needs-warning:before {
   background: #bf332a
}

.readiness-row.needs-caution {
   background: #fffaf2
}

.readiness-row.needs-warning {
   background: #fff6f5
}

.readiness-row.needs-caution>.app-icon,
.readiness-row.needs-caution .readiness-category .app-icon {
   color: #9c5c00
}

.readiness-row.needs-warning>.app-icon,
.readiness-row.needs-warning .readiness-category .app-icon {
   color: #a32b23
}

[data-theme=dark] .readiness-row.needs-caution {
   background: #221a0c
}

[data-theme=dark] .readiness-row.needs-warning {
   background: #20110f
}

[data-theme=dark] .readiness-row.needs-caution:before {
   background: var(--state-caution)
}

[data-theme=dark] .readiness-row.needs-warning:before {
   background: var(--state-warning)
}

[data-theme=dark] .readiness-row.needs-caution>.app-icon,
[data-theme=dark] .readiness-row.needs-caution .readiness-category .app-icon {
   color: var(--state-caution)
}

[data-theme=dark] .readiness-row.needs-warning>.app-icon,
[data-theme=dark] .readiness-row.needs-warning .readiness-category .app-icon {
   color: var(--state-warning)
}

/* A note that reports an open item is not a muted aside — it takes the caution
   treatment so the cause of an amber tab count is visible on the page. */
.note.is-caution {
   background: #fffaf2;
   border-color: #edd2a0;
   color: #5f4a25;
   align-items: flex-start;
   gap: 11px
}

.note.is-caution>.app-icon {
   color: #9c5c00;
   margin-top: 1px
}

.note.is-caution span {
   display: flex;
   flex-direction: column;
   gap: 4px
}

.note.is-caution strong {
   color: #8a5200;
   font-size: 12px
}

[data-theme=dark] .note.is-caution {
   background: #221a0c;
   border-color: #6b5526;
   color: #c9a878
}

[data-theme=dark] .note.is-caution>.app-icon {
   color: var(--state-caution)
}

[data-theme=dark] .note.is-caution strong {
   color: #ffca6a
}

/* A flagged person row carries the same left edge as a flagged flight row. */
.person-item.has-flag>.person-row {
   position: relative;
   padding-left: 11px
}

.person-item.has-flag>.person-row:before {
   content: '';
   position: absolute;
   left: 0;
   top: 6px;
   bottom: 6px;
   width: 3px;
   border-radius: 2px;
   background: #c87800
}

[data-theme=dark] .person-item.has-flag>.person-row:before {
   background: var(--state-caution)
}

.person-row>.status-badge+.status-badge {
   margin-left: 0
}

/* A note reporting a blocker takes the warning treatment. */
.note.is-warning {
   background: #fdeceb;
   border-color: #f0c2be;
   color: #6b3733;
   align-items: flex-start;
   gap: 11px
}

.note.is-warning>.app-icon {
   color: #a32b23;
   margin-top: 1px
}

.note.is-warning span {
   display: flex;
   flex-direction: column;
   gap: 4px
}

.note.is-warning strong {
   color: #8d241d;
   font-size: 12px
}

[data-theme=dark] .note.is-warning {
   background: #20110f;
   border-color: #4d2420;
   color: #e0918a
}

[data-theme=dark] .note.is-warning>.app-icon {
   color: var(--state-warning)
}

[data-theme=dark] .note.is-warning strong {
   color: #ff9a92
}

.person-item.has-flag>.person-row:before {
   background: #bf332a
}

[data-theme=dark] .person-item.has-flag>.person-row:before {
   background: var(--state-warning)
}

/* A tally is not a status: neutral, but bright enough to read as a live count. */
.status-badge.count {
   background: #e0e0e0;
   color: #1f1f1f;
   font-family: var(--font-mono);
   font-variant-numeric: tabular-nums
}

[data-theme=dark] .status-badge.count {
   background: #3d3d3d;
   color: #ededed
}

/* Collapsible inbox groups with sticky headers: with a full day of movements the
   rail scrolls, and no group should be discoverable only by hunting for it. */
.flight-group>h2 {
   position: sticky;
   top: -3px;
   z-index: 2;
   padding: 0;
   margin: 0;
   background: inherit
}

.group-toggle {
   display: flex;
   align-items: center;
   gap: 9px;
   width: 100%;
   padding: 11px 12px;
   font: inherit;
   font-size: 12px;
   font-weight: 600;
   letter-spacing: -.01em;
   color: inherit;
   text-align: left;
   border-radius: 7px
}

.group-caret {
   display: grid;
   place-items: center;
   margin-left: 2px;
   color: var(--muted-strong);
   transition: transform .18s var(--ease-standard)
}

.group-toggle[aria-expanded=true] .group-caret {
   transform: rotate(90deg)
}

.flight-group .group-count {
   margin-left: auto
}

.flight-group.is-collapsed {
   padding-bottom: 0
}

@media(max-width:700px) {
   .flight-group>h2 {
      display: none
   }
}

/* A pinned index of the groups, so every group is visible from any scroll position. */
.inbox-footer {
   flex-direction: column;
   gap: 9px;
   padding: 10px 12px 12px
}

.group-index {
   display: flex;
   flex-wrap: wrap;
   gap: 5px
}

.group-index-chip {
   display: flex;
   align-items: center;
   gap: 6px;
   padding: 5px 8px;
   border: 1px solid var(--line);
   border-radius: 6px;
   font-size: 10px;
   font-weight: 600;
   letter-spacing: .02em;
   color: var(--muted-strong);
   background: var(--ops-surface)
}

.group-index-chip b {
   font-family: var(--font-mono);
   font-variant-numeric: tabular-nums;
   font-size: 10px
}

.group-index-chip.amber {
   border-color: #edd2a0;
   background: #fffaf2;
   color: #8a5200
}

[data-theme=dark] .group-index-chip {
   background: #1c1c1c;
   border-color: #333
}

[data-theme=dark] .group-index-chip.amber {
   border-color: #6b5526;
   background: #221a0c;
   color: #ffca6a
}

.inbox-footer-meta {
   width: 100%;
   font-size: 10px;
   color: var(--muted-strong);
   gap: 8px
}

@media(max-width:700px) {
   .inbox-footer {
      display: none
   }
}

/* One row in the narrowest rail, and the dev launcher clears the footer. */
.group-index {
   gap: 4px
}

.group-index-chip {
   padding: 5px 7px;
   gap: 5px;
   flex: 1 1 auto;
   justify-content: center;
   white-space: nowrap
}

.dev-tools {
   bottom: 82px
}

@media(max-width:700px) {
   .dev-tools {
      bottom: 78px
   }
}

/* Person rows: a name must never be crushed to one character per line.
   The badges live in their own group, and below a narrow container width the row
   becomes two lines — avatar and name first, status underneath. This is a container
   query rather than a media query because the same list renders in the wide
   dashboard, a drawer and a phone frame. */
.people-list {
   container-type: inline-size
}

.person-flags {
   display: flex;
   align-items: center;
   justify-content: flex-end;
   gap: 7px;
   margin-left: auto;
   flex-wrap: wrap
}

.person-flags .status-badge {
   font-size: 10px;
   padding: 3px 7px;
   gap: 4px
}

.person-name strong {
   white-space: nowrap;
   overflow: hidden;
   min-width: 0
}

.person-name>span {
   white-space: nowrap;
   overflow: hidden;
   text-overflow: ellipsis
}

@container (max-width:560px) {
   .person-row {
      display: grid;
      grid-template-columns: auto minmax(0, 1fr) auto;
      column-gap: 10px;
      row-gap: 7px;
      align-items: center
   }

   .person-row>.avatar {
      grid-area: 1/1/2/2
   }

   .person-row>.person-name {
      grid-area: 1/2/2/3
   }

   .person-row>.person-caret,
   .person-row>.app-icon {
      grid-area: 1/3/2/4;
      margin: 0
   }

   .person-row>.person-flags {
      grid-area: 2/1/3/4;
      margin-left: 44px;
      justify-content: flex-start
   }
}

/* ==========================================================================
   Advisory blue — the fourth annunciator hue
   The palette above drains blue out of the chrome so that hue only ever means
   state. That rule is kept here: this blue is not affordance, it is a state, and
   it appears on nothing but a flight's own status badge.
   A scheduled leg is pending, not confirmed, so it must not borrow the green that
   means the work is done — blue is the standard advisory colour beside the red,
   amber and green already in use. Same "dim mark on a neutral chip" treatment as
   the other tones, matched to green's weight: 5.77:1 on the light chip against
   green's 5.74, and 5.06:1 on the dark chip against green's 5.09.
   ========================================================================== */
.status-badge.blue {
   background: #f1f1f1;
   color: #1e5ea8
}

[data-theme=dark] .status-badge.blue {
   background: #1c1c1c;
   color: var(--state-advisory)
}

/* ==========================================================================
   Selection indicator — one marker, tinted by the row's own severity
   Every row is now unmarked until it is the open flight, so the left edge means
   exactly one thing: "this is the flight you are looking at." It takes the colour
   the row already carries, so selecting a warning flight does not drop a neutral
   grey bar and a grey border onto a red row. Placed last so it wins over the
   neutral selected border above.
   ========================================================================== */
.flight-row.is-selected.attention-caution:before {
   background: #c87800
}

.flight-row.is-selected.attention-warning:before {
   background: #bf332a
}

.flight-row.is-selected.attention-caution,
.flight-row.is-selected.attention-caution:hover {
   border-color: #d3a03a;
   background-image: linear-gradient(110deg, #fff8ee88, #fffaf4dd)
}

.flight-row.is-selected.attention-warning,
.flight-row.is-selected.attention-warning:hover {
   border-color: #d08079;
   background-image: linear-gradient(110deg, #fff2f088, #fff7f6dd)
}

[data-theme=dark] .flight-row.is-selected.attention-caution:before {
   background: var(--state-caution)
}

[data-theme=dark] .flight-row.is-selected.attention-warning:before {
   background: var(--state-warning)
}

[data-theme=dark] .flight-row.is-selected.attention-caution,
[data-theme=dark] .flight-row.is-selected.attention-caution:hover {
   border-color: #8a6b28;
   background-image: linear-gradient(110deg, #ffc2331a, #ffc2330a)
}

[data-theme=dark] .flight-row.is-selected.attention-warning,
[data-theme=dark] .flight-row.is-selected.attention-warning:hover {
   border-color: #6d332c;
   background-image: linear-gradient(110deg, #ff5f561a, #ff5f560a)
}

/* ==========================================================================
   The operations wall is dark in both themes
   `.tower` renders on a near-black surface whatever the app theme is, so it has to
   read from the dark palette. Under the light theme it was resolving the light
   tokens — tuned for a white page — and put caution text at 4.25:1 on the wall,
   below AA on the one screen meant to be read from across a room. Re-pointing the
   tokens at the tower root fixes every var() lookup inside it at once.
   ========================================================================== */
.tower {
   --state-normal: #34d399;
   --state-caution: #ffc233;
   --state-warning: #ff5f56;
   --state-info: #34d399;
   --state-inactive: #8d8d8d
}

/* ── Messages hub ────────────────────────────────────────────────────────────
   The hub is a top-level place, not a card inside a flight, so it fills the
   workspace instead of sitting at the flight tab's fixed height.

   It is sized like a mail client: the shell claims the viewport once, and every
   list inside it scrolls in its own box. The page itself never scrolls. Before
   this the rail set the height — sixteen flights expanded made the workspace
   6000px tall and pushed the composer that far down the document, so replying
   meant scrolling past every other conversation to reach the box. The height
   chain below (shell → view → workspace → pane) is load-bearing: each link needs
   `min-height:0`, because a flex/grid child defaults to its content's height and
   one `auto` anywhere lets the rail push the whole column open again. */
.hub-shell {
   display: flex;
   flex-direction: column;
   height: 100dvh;
   overflow: hidden
}

.hub-shell>.app-header {
   flex: 0 0 auto
}

.hub-view {
   display: flex;
   flex-direction: column;
   padding: 26px 32px;
   max-width: 1500px;
   width: 100%;
   margin: 0 auto;
   flex: 1;
   min-height: 0;
   overflow: hidden
}

.hub-workspace {
   flex: 1;
   height: 100%;
   min-height: 0;
   /* The rail carries two levels — a flight header and the channels under it,
      each with a message preview — so it needs more room than the flight tab's
      flat 240px list, and on a wide window there is nothing to spend that width
      on but the thread. A percentage here resolves against the workspace, which
      is capped at 1500px, so the rail tracks the pane it lives in rather than a
      window that may be far wider. The clamp keeps it legible on a laptop and
      stops it turning into a second reading column on a large display. */
   grid-template-columns: clamp(268px, 26%, 400px) minmax(0, 1fr)
}

/* The rail is the only thing in the hub long enough to need its own scrollbar,
   and now that it has one its heading can actually stay put while it moves. */
.hub-rail {
   min-height: 0;
   overflow-y: auto;
   overscroll-behavior: contain
}

.hub-heading {
   display: flex;
   flex-wrap: wrap;
   align-items: baseline;
   gap: 4px 10px;
   position: sticky;
   top: 0;
   z-index: 2;
   background: var(--ops-surface, #fff)
}

.hub-heading h3 {
   flex: 1 0 auto
}

.hub-heading p {
   flex: 1 0 100%
}

/* A switch reports a standing state; the button beside it performs an action.
   They are deliberately shaped differently — a filter you leave on should not look
   like a command you fire. */
.hub-tools {
   display: flex;
   flex-wrap: wrap;
   align-items: center;
   gap: 8px 14px;
   flex: 1 0 100%;
   margin-top: 11px
}

.switch {
   display: inline-flex;
   align-items: center;
   gap: 8px;
   font-size: 11px;
   color: var(--muted)
}

.switch-track {
   position: relative;
   flex: none;
   width: 28px;
   height: 16px;
   border-radius: 999px;
   /* Mid grey, not a hairline: the track is the component, and 1.4.11 wants it at
      3:1 against the surface behind it whether it is on or off. */
   background: #8e8e8e;
   transition: background .18s var(--ease-entrance)
}

.switch.is-on .switch-track {
   background: #1f6fd0
}

.switch-thumb {
   position: absolute;
   top: 2px;
   left: 2px;
   width: 12px;
   height: 12px;
   border-radius: 50%;
   background: #fff;
   transition: transform .18s var(--ease-entrance)
}

.switch.is-on .switch-thumb {
   transform: translateX(12px)
}

.switch.is-on .switch-label {
   color: var(--ink)
}

.hub-tool {
   display: inline-flex;
   align-items: center;
   gap: 6px;
   font-size: 11px;
   color: var(--muted);
   border: 1px solid var(--line);
   border-radius: 6px;
   padding: 4px 9px
}

/* The chevron points the way the rail is about to move: down to fold it away,
   right to open it back up. */
.hub-tool>.app-icon {
   transform: rotate(90deg);
   transition: transform .18s var(--ease-entrance)
}

.hub-tool.is-folded>.app-icon {
   transform: rotate(0deg)
}

[data-theme=dark] .switch-track {
   background: #6e6e6e
}

[data-theme=dark] .switch.is-on .switch-track {
   background: var(--state-advisory)
}

/* The group is the heading, the row is the thing you pick. In the Messages hub the
   group is a flight and the row is a channel; in the Contacts hub the group is a
   category of people and the row is a person. Same control, so the same rules —
   `.hub-section` is the category header, `.hub-flight` the route one, which also
   carries the monospaced route treatment a dispatcher scans for. */
.hub-flight,
.hub-section {
   display: flex;
   align-items: center;
   gap: 9px;
   width: 100%;
   text-align: left;
   padding: 12px 15px;
   border-bottom: 1px solid var(--line);
   background: var(--ops-soft, #f6f6f6)
}

.hub-flight>.app-icon:last-child,
.hub-section>.app-icon:last-child {
   color: var(--muted);
   transition: transform .18s ease
}

.hub-flight[aria-expanded=true]>.app-icon:last-child,
.hub-section[aria-expanded=true]>.app-icon:last-child {
   transform: rotate(90deg)
}

.hub-route {
   flex: 1;
   min-width: 0
}

.hub-route strong {
   display: flex;
   align-items: center;
   gap: 4px;
   font-size: 11px;
   font-family: var(--font-mono);
   letter-spacing: .02em
}

.hub-route small {
   display: block;
   font-size: 10px;
   color: var(--muted);
   margin-top: 3px
}

.hub-rollup {
   min-width: 18px;
   height: 18px;
   padding: 0 5px;
   border-radius: 9px;
   background: #1f6fd0;
   color: #fff;
   font-family: var(--font-mono);
   font-size: 10px;
   font-weight: 700;
   display: grid;
   place-items: center
}

.hub-channel {
   display: flex;
   gap: 10px;
   align-items: center;
   text-align: left;
   width: 100%;
   padding: 13px 15px 13px 24px;
   border-bottom: 1px solid var(--line)
}

.hub-channel>span:nth-child(2) {
   flex: 1;
   min-width: 0
}

.hub-channel strong {
   display: block;
   font-size: 11px
}

.hub-channel small {
   display: block;
   font-size: 10px;
   color: var(--muted);
   margin-top: 5px;
   white-space: nowrap;
   text-overflow: ellipsis;
   overflow: hidden
}

.hub-channel.active {
   background: var(--ops-soft, #f1f1f1);
   box-shadow: inset 3px 0 0 #1f6fd0
}

/* A thread lifted out of its flight has to name the flight it came from, and
   offer the way in. Without this the hub is just the old ambiguity, wider. */
.hub-thread-flight {
   display: flex;
   align-items: center;
   gap: 10px;
   padding: 12px 20px;
   border-bottom: 1px solid var(--line);
   background: var(--ops-soft, #f6f6f6)
}

.hub-thread-flight>span:nth-child(2) {
   flex: 1;
   min-width: 0
}

.hub-thread-flight strong {
   display: block;
   font-size: 13px;
   font-family: var(--font-mono);
   letter-spacing: .02em
}

.hub-thread-flight small {
   display: block;
   font-size: 10px;
   color: var(--muted);
   margin-top: 3px
}

.hub-empty {
   padding: 34px 20px
}

[data-theme=dark] .hub-heading {
   background: var(--ops-surface)
}

[data-theme=dark] .hub-filter.active {
   background: var(--state-advisory);
   border-color: var(--state-advisory);
   color: #04121f
}

[data-theme=dark] .hub-rollup {
   background: var(--state-advisory);
   color: #04121f
}

[data-theme=dark] .hub-channel.active {
   box-shadow: inset 3px 0 0 var(--state-advisory)
}

@media(max-width:700px) {
   .hub-view {
      padding: 0
   }

   .hub-workspace {
      border: 0;
      border-radius: 0;
      height: 100%;
      min-height: 0
   }

   .hub-channel {
      padding-left: 18px
   }
}

/* ── Contacts hub ────────────────────────────────────────────────────────────
   Same two-pane hub as Messages, inverted: the group is a category of people, the
   row is a person, and the detail pane is that person's day. It reuses the rail
   (`.channel-list`, `.hub-*`) so the two header destinations are visibly the same
   kind of place, and only the right-hand pane is new. */
.hub-search {
   flex: 1 0 100%;
   margin-top: 12px
}

.hub-section-label {
   flex: 1;
   min-width: 0
}

.hub-section-label strong {
   display: block;
   font-size: 11px
}

.hub-section-label small {
   display: block;
   font-size: 10px;
   color: var(--muted);
   margin-top: 3px
}

/* A person row carries an avatar where a channel row carries an icon, so it keeps
   the channel row's padding and only the leading element differs. */
.hub-contact>.avatar {
   width: 26px;
   height: 26px;
   font-size: 9px
}

.hub-detail {
   min-width: 0;
   min-height: 0;
   display: flex;
   flex-direction: column
}

.contact-identity {
   display: flex;
   align-items: center;
   gap: 14px;
   padding: 18px 20px;
   border-bottom: 1px solid var(--line);
   background: var(--ops-soft, #f6f6f6)
}

.contact-identity>div:nth-child(2) {
   flex: 1;
   min-width: 0
}

.contact-identity .avatar.large {
   width: 46px;
   height: 46px;
   font-size: 15px
}

.contact-identity h3 {
   display: flex;
   align-items: center;
   gap: 8px;
   font-size: 17px
}

.contact-identity p {
   font-size: 11px;
   color: var(--muted);
   margin-top: 4px
}

.contact-detail-body {
   flex: 1;
   min-height: 0;
   overflow: auto;
   padding: 20px
}

.contact-legs {
   margin-top: 22px
}

.contact-legs-heading h4 {
   font-size: 13px
}

.contact-legs-heading p {
   font-size: 10px;
   color: var(--muted);
   margin: 5px 0 12px
}

.contact-leg-section {
   margin-bottom: 18px
}

.contact-leg-section h5 {
   display: flex;
   align-items: baseline;
   gap: 8px;
   font-size: 10px;
   text-transform: uppercase;
   letter-spacing: .08em;
   color: var(--muted);
   margin-bottom: 8px
}

.contact-leg-section h5 span {
   font-size: 10px;
   letter-spacing: 0;
   text-transform: none
}

/* One leg, one row. The route is the heading, the badge is the state, and the
   control only appears where check-in is still a live gate. */
.contact-leg {
   display: flex;
   align-items: center;
   gap: 12px;
   padding: 11px 13px;
   border: 1px solid var(--line);
   border-radius: 8px;
   margin-bottom: 8px;
   background: var(--ops-surface, #fff)
}

.contact-leg.is-waiting {
   border-left: 3px solid var(--amber)
}

.contact-leg-route {
   flex: 1;
   min-width: 0
}

.contact-leg-route strong {
   display: flex;
   align-items: center;
   gap: 5px;
   font-size: 12px;
   font-family: var(--font-mono);
   letter-spacing: .02em
}

.contact-leg-route small {
   display: flex;
   align-items: center;
   gap: 5px;
   flex-wrap: wrap;
   font-size: 10px;
   color: var(--muted);
   margin-top: 5px
}

.contact-leg-route small .tail-plate {
   font-size: 10px;
   padding: 1px 5px
}

.contact-leg .custom-select-control {
   width: 138px;
   flex: none
}

.contact-leg .custom-select-trigger {
   font-size: 11px;
   padding: 6px 9px;
   min-height: 32px
}

[data-theme=dark] .contact-identity {
   background: var(--ops-soft)
}

[data-theme=dark] .contact-leg {
   background: var(--ops-surface)
}

[data-theme=dark] .contact-leg.is-waiting {
   border-left-color: var(--state-caution)
}

@media(max-width:1180px) {
   /* The select is the first thing to fall below the route: a 138 px control beside
      a route, a badge and a link stops fitting before any of them do. */
   .contact-leg {
      flex-wrap: wrap
   }

   .contact-leg-route {
      flex: 1 0 100%
   }
}

@media(max-width:700px) {
   .hub-detail {
      display: none;
      height: 100%
   }

   .thread-open .hub-detail {
      display: flex
   }

   .contact-identity {
      flex-wrap: wrap;
      padding: 15px 20px
   }

   .contact-identity>.btn {
      flex: 1 0 100%
   }

   .contact-detail-body {
      padding: 16px
   }
}

/* A tail number is how this industry finds a flight — it is the search key, not a
   footnote after the route. Everywhere it appears it now reads as the same token:
   monospaced so digits and letters line up down a column, plated so the eye can
   catch it without reading the line around it. */
.tail-plate {
   font-family: var(--font-mono);
   font-size: 12px;
   font-weight: 700;
   letter-spacing: .03em;
   color: var(--ink);
   background: #f2f2f2;
   border: 1px solid #e2e2e2;
   border-radius: 5px;
   padding: 2px 6px;
   white-space: nowrap
}

.flight-header .tail-plate {
   font-size: 13px;
   padding: 3px 8px
}

[data-theme=dark] .tail-plate {
   color: #ededed;
   background: #2e2e2e;
   border-color: #414141
}

.flight-row.is-selected .tail-plate {
   border-color: #d4d4d4
}

[data-theme=dark] .flight-row.is-selected .tail-plate {
   border-color: #4f4f4f
}

/* ==========================================================================
   Messages — the one surface that spends identity colour
   ==========================================================================
   Everywhere else in this app colour means state: red blocks a leg, amber has
   work outstanding, green is confirmed, and a normal flight sits unlit so the
   exceptions are the only lit things on the board. That rule is what makes the
   board scannable, and nothing below touches it.

   Blue is not in that vocabulary. It is the brand hue — the header band and
   `--category-messages` already carry it — so there is no blue alert anywhere
   for a blue button to be confused with. Spending it here is therefore additive
   rather than a hole in the dark-cockpit rule: the Messages hub is a place where
   nothing is wrong by definition, and it was reading as dead grey chrome because
   `--blue` was neutralised to #6e6e6e along with the rest of the app.

   The accent IS the Messages category hue, not a new blue, so the tab icon
   inside a flight, the hub's chrome and the thread all name the same thing. It
   is defined on the messages surfaces only, so it cannot leak onto the board,
   the flight workspace or the tower wall.

   `--on-accent` is the only part that has to fork by theme: the light accent is
   dark enough to carry white, the dark accent is light enough to need near-black.
   Everything else follows `--category-messages`, which already flips on its own. */
:root {
   --accent-blue: var(--category-messages);
   --accent-blue-soft: var(--category-messages-soft);
   --accent-blue-line: color-mix(in srgb, var(--category-messages) 34%, transparent);
   --on-accent-blue: #ffffff
}

:root[data-theme=dark] {
   --on-accent-blue: #04121f
}

/* ── The rail's chrome ────────────────────────────────────────────────────── */
.hub-heading h3 {
   color: var(--accent-blue)
}

/* Both hub controls are now visibly controls. The switch reports a standing
   state and the button fires an action, so they keep their different shapes —
   the accent is what they have in common, not what makes them the same. */
.hub-view .switch.is-on .switch-track,
[data-theme=dark] .hub-view .switch.is-on .switch-track {
   background: var(--accent-blue)
}

.hub-view .hub-tool {
   color: var(--accent-blue);
   background: var(--accent-blue-soft);
   border-color: var(--accent-blue-line);
   font-weight: 500
}

/* An unread count is the one number this hub exists to show, so it is the one
   tally that earns the accent — the neutral `.count` treatment stays everywhere
   else, where a tally really is just a tally. The flight rollup and the channel
   badge are the same number at two levels, so they are the same chip. */
.hub-view .hub-rollup,
[data-theme=dark] .hub-view .hub-rollup,
.hub-rail .status-badge.count,
[data-theme=dark] .hub-rail .status-badge.count {
   background: var(--accent-blue);
   color: var(--on-accent-blue)
}

/* ── The selected conversation ────────────────────────────────────────────── */
.hub-view .hub-channel.active,
[data-theme=dark] .hub-view .hub-channel.active,
.messages-workspace .channel-list>button.active {
   background: var(--accent-blue-soft);
   box-shadow: inset 3px 0 0 var(--accent-blue)
}

.hub-view .hub-channel.active strong,
.hub-view .hub-channel.active .channel-icon,
.messages-workspace .channel-list>button.active strong,
.messages-workspace .channel-list>button.active .channel-icon,
/* The dark theme carries three separate `.channel-list button.active` rules left
   over from the neutralisation passes, all of them at least as specific as the
   light selectors above. Restating the dark case is the honest fix: relying on
   file order against three rules that already disagree with each other is how the
   category hues were lost the first time. */
[data-theme=dark] .hub-view .hub-channel.active strong,
[data-theme=dark] .hub-view .hub-channel.active .channel-icon,
[data-theme=dark] .messages-workspace .channel-list>button.active strong,
[data-theme=dark] .messages-workspace .channel-list>button.active .channel-icon {
   color: var(--accent-blue)
}

/* Tinting the selected row toward the accent costs the preview line contrast, the
   same way the hover wash does — measured in the light theme it fell to 4.41:1 at
   10px, under AA, having been fine at 4.6:1 on plain white. So the preview lifts
   to full ink at the same moment the row takes the tint. That is the rule the
   interaction system already applies to the wash, and it is right here for a second
   reason: this is the conversation you are reading, so its last line is the one
   preview in the rail that should not be whispering. */
.hub-view .hub-channel.active small,
.messages-workspace .channel-list>button.active small {
   color: var(--ink)
}

/* A row holding unread lights its icon. The badge already says how many; this is
   the same fact at a glance, for the scan down the rail rather than the read. */
.hub-channel:has(.status-badge.count) .channel-icon,
[data-theme=dark] .hub-channel:has(.status-badge.count) .channel-icon {
   color: var(--accent-blue)
}

/* In the dark theme a channel icon sits on a grey chip. An accented glyph on a
   neutral chip reads as a patch that missed the tint, so the chip takes the hue
   too — at a fraction of the strength, because it is a backing, not a mark. */
[data-theme=dark] .hub-view .hub-channel.active .channel-icon,
[data-theme=dark] .messages-workspace .channel-list>button.active .channel-icon,
[data-theme=dark] .hub-channel:has(.status-badge.count) .channel-icon {
   background: color-mix(in srgb, var(--accent-blue) 15%, transparent)
}

/* ── The thread ───────────────────────────────────────────────────────────── */
.hub-thread-flight>.text-button {
   padding: 6px 10px 6px 12px;
   border-radius: 6px;
   background: var(--accent-blue);
   color: var(--on-accent-blue);
   font-weight: 500
}

.message-thread .conversation-audience>.soft-icon,
.mobile-message-back {
   color: var(--accent-blue)
}

.conversation-tabs button.active {
   color: var(--accent-blue)
}

.conversation-tabs button.active:after {
   background: var(--accent-blue)
}

/* Your own messages. The bubble is tinted rather than filled: a wall of solid
   accent would out-shout the thing the thread is actually for, which is reading
   what other people said. */
.chat-message.own .chat-message-content>p,
[data-theme=dark] .chat-message.own .chat-message-content>p {
   background: var(--accent-blue-soft);
   border-color: var(--accent-blue-line);
   color: var(--ink)
}

/* Send is the primary action on this surface, so it is the brightest thing on
   it — and it had no disabled rule at all in the light theme, which was survivable
   while the fill was grey and is not now that it is blue. */
.chat-composer button[type=submit],
[data-theme=dark] .chat-composer button[type=submit] {
   background: var(--accent-blue);
   color: var(--on-accent-blue)
}

/* Disabled is exempt from AA, but "exempt" is not "invisible" — the icon still has
   to read as a send button you cannot press yet, so it clears 3:1 against its own
   surface rather than sitting at the 2.76:1 a first pass landed on. */
.chat-composer button[type=submit]:disabled {
   background: #ededed;
   color: #767676
}

[data-theme=dark] .chat-composer button[type=submit]:disabled {
   background: #2b2b2b;
   color: #8d8d8d
}

/* ==========================================================================
   The inbox filter stack — a clickable thing is sized like a control
   ==========================================================================
   Measured in this rail before the rules below: eight different heights on
   things you are meant to press — 17, 27, 31, 32, 34, 36, 40 and 44px — with
   nothing deciding which got which. The date-range trigger was the worst of it
   at 304×17: a bare icon-and-label line with no border, no background and no
   caret, so nothing about it said "press me", and at 17px high it also missed
   the 24×24 minimum in WCAG 2.5.8.

   The group toggles were already 44px, so 44 is the size this rail had in fact
   chosen for a control — everything else had simply never been brought to it.
   One ladder now, three rungs, each with a reason:

     --control-h    44px   a primary control: search, its filter button, the
                           segmented tabs, the date trigger, a group toggle
     --control-sm   36px   something nested inside one of those, or secondary
     --control-xs   32px   a chip in a row of chips

   Compact steps the whole ladder down together rather than letting each control
   drift on its own, and its smallest rung is still above 24px. */
.flight-inbox {
   --control-h: 44px;
   --control-sm: 36px;
   --control-xs: 32px
}

[data-density=compact] .flight-inbox {
   --control-h: 38px;
   --control-sm: 32px;
   --control-xs: 28px
}

.flight-inbox .search-box {
   min-height: var(--control-h);
   padding: 0 12px
}

/* The input stretches to fill the field. The wrapping label was already the real
   44px target — clicking the padding focuses the input — but leaving the input
   itself 20px tall meant the thing under the pointer disagreed with the thing
   being clicked, which is the same confusion in miniature. */
.flight-inbox .search-box input {
   align-self: stretch
}

.flight-inbox .search-row .square-button {
   width: var(--control-h);
   height: var(--control-h)
}

.flight-inbox .filter-tabs {
   padding: 4px;
   gap: 4px
}

.flight-inbox .filter-tabs button {
   min-height: var(--control-sm);
   padding: 0 10px
}

.flight-inbox .group-index-chip {
   min-height: var(--control-xs)
}

.flight-inbox .inbox-top .app-button {
   min-height: var(--control-sm)
}

/* ── The date range trigger ───────────────────────────────────────────────── */
/* It is a disclosure, so it is drawn as one: the same height and edge as the
   search field above it, and a caret that turns to say which way it is about to
   move. `list-style` is cleared because a summary still paints a marker in some
   engines even when it is a flex box. */
.date-filter {
   margin: 8px 20px 10px
}

.date-filter summary {
   min-height: var(--control-h);
   padding: 0 12px;
   gap: 10px;
   font-size: 12px;
   border: 1px solid var(--line);
   border-radius: 6px;
   background: var(--ops-surface);
   list-style: none
}

.date-filter summary::-webkit-details-marker {
   display: none
}

.date-filter summary>span:first-of-type {
   flex: 1;
   min-width: 0
}

.date-filter summary>.app-icon:last-child {
   color: var(--muted);
   transition: transform .18s var(--ease-standard)
}

.date-filter[open] summary>.app-icon:last-child {
   transform: rotate(90deg)
}

/* A filter that is hiding flights has to say so on the control itself, not only
   inside the panel you have to open to find out. It is a neutral chip, not a
   coloured one: on this rail colour means a flight needs something, and a filter
   you switched on yourself is not a problem to be solved. */
.date-filter.is-set summary {
   border-color: var(--muted-strong)
}

.date-filter-state {
   flex: none;
   font-size: 10px;
   font-weight: 600;
   letter-spacing: .04em;
   text-transform: uppercase;
   padding: 3px 7px;
   border-radius: 4px;
   background: var(--ops-soft);
   color: var(--ink)
}

.date-filter input {
   min-height: var(--control-sm);
   padding: 0 9px;
   font-size: 11px
}

[data-theme=dark] .date-filter summary {
   border-color: #333333;
   background: #161616
}

[data-theme=dark] .date-filter-state {
   background: #2f2f2f;
   color: #ececec
}

/* ==========================================================================
   The button vocabulary wears the accent
   ==========================================================================
   Same argument as the Messages hub, applied to the workspace: colour on this
   app means state, but blue is not in the state vocabulary — red, amber, green
   and grey are. So a blue control cannot be misread as a flight that needs
   something, which is exactly why it is free to be used for the one other thing
   that has to be obvious at a glance: this is a thing you press.

   It was needed. Every action in the workspace had been neutralised to #1a1a1a
   text on a near-white chip, so "Verify identities" sitting in a red attention
   row was the quietest thing in it.

   WHAT IS NOT IN THIS LIST, and why:
     .annunciator, .workspace-tabs, .attention-items rows, .readiness-row,
     .flight-row, .board-chip, .map-marker, .wx-hour, .status-badge
   Every one of those reports what a flight is doing. They keep red/amber/green,
   and the accent never touches them — a row stays amber while the button inside
   it turns blue, which is the whole point: the colour tells you it is a problem,
   the blue tells you where to click.

   The board is excluded outright. It is the dark-cockpit scan surface where a
   clean day is meant to be nearly blank, and it has its own control classes
   (`.board-go`, `.board-chip`) that this list does not name. */
.app-shell:not(.board-shell) .app-button.primary,
.app-shell:not(.board-shell) .app-button.btn-primary,
[data-theme=dark] .app-shell:not(.board-shell) .app-button.primary,
[data-theme=dark] .app-shell:not(.board-shell) .app-button.btn-primary {
   background: var(--accent-blue);
   border-color: var(--accent-blue);
   color: var(--on-accent-blue)
}

.app-shell:not(.board-shell) .app-button.secondary,
[data-theme=dark] .app-shell:not(.board-shell) .app-button.secondary {
   color: var(--accent-blue);
   border-color: var(--accent-blue-line)
}

/* The two chip-shaped actions — "View crew", "Verify identities". These are the
   ones that were disappearing: a chip needs a surface as well as a label, so it
   takes the soft tint rather than only the hue. */
.app-shell:not(.board-shell) .soft-view-button,
.app-shell:not(.board-shell) .inline-action,
[data-theme=dark] .app-shell:not(.board-shell) .soft-view-button,
[data-theme=dark] .app-shell:not(.board-shell) .inline-action {
   background: var(--accent-blue-soft);
   border-color: var(--accent-blue-line);
   color: var(--accent-blue)
}

/* `.filled-action` is excluded rather than out-specified. A text button drawn as a
   filled button has already decided its label colour, and this rule is more
   specific than the one that decided it — left in, it repainted "Open flight" with
   the very blue it sits on: a solid blue rectangle with nothing in it, in both
   themes. Same shape of bug as `.board-go` before it, and `:not()` is the fix that
   holds, because it makes the two states mutually exclusive instead of leaving the
   winner to whichever rule lands later in a 9,800-line file. */
.app-shell:not(.board-shell) .text-button:not(.filled-action),
.app-shell:not(.board-shell) .card-footer-action,
[data-theme=dark] .app-shell:not(.board-shell) .text-button:not(.filled-action),
[data-theme=dark] .app-shell:not(.board-shell) .card-footer-action {
   color: var(--accent-blue)
}

/* A control's own on/off is a control state, not a flight state, so the two
   toggles in the rail read as pressed in the accent rather than in grey. */
.flight-inbox .square-button.selected,
[data-theme=dark] .flight-inbox .square-button.selected {
   background: var(--accent-blue-soft);
   border-color: var(--accent-blue-line);
   color: var(--accent-blue)
}

.flight-inbox .filter-tabs button.selected,
[data-theme=dark] .flight-inbox .filter-tabs button.selected {
   color: var(--accent-blue)
}

/* ==========================================================================
   Step trackers — the step name is the information, so it is legible
   ==========================================================================
   The transport tracker set its labels at 9px (8px on a phone) in `--muted`, and
   they are the only thing on that row that says where the car actually is: the
   markers are six identical green checks. So the one piece of information in the
   component was the least readable thing in it.

   This is not a licence to whiten every muted label. The rule being applied is the
   one the catering tracker already follows — `.catering-progress .done strong`
   lifts to `--ink` — and it is specifically about the step NAME. The sub-status
   under a fuel step ("Complete", "Pending", "After payment") stays muted, because
   it repeats what the marker already shows; the name does not.

   So each tracker reads in three tiers, and only the first two are pertinent:
     current    ink + semibold   where the job is right now
     done       ink              what has actually happened
     upcoming   muted            not information yet, and shouldn't pretend to be */
.transport-progress small {
   font-size: 11px;
   max-width: 104px;
   line-height: 1.35
}

.transport-progress .done small {
   color: var(--ink)
}

.transport-progress .current small {
   color: var(--ink);
   font-weight: 600
}

/* The fuel tracker names its steps in `strong` and had them at a flat #6e6e6e
   whether the step had happened or not, so a finished order and an untouched one
   read identically. */
.fuel-progress .complete strong,
.fuel-progress .current strong {
   color: var(--ink)
}

.fuel-progress .current strong {
   font-weight: 600
}

@media(max-width:700px) {
   .transport-progress small {
      font-size: 10px;
      max-width: 88px
   }
}

/* ==========================================================================
   The flight status — one horizontal line, reporting in all three states
   ==========================================================================
   It used to be a stacked two-line block sitting next to a Conversation button,
   squeezing a wide header into a narrow column of tall chips. The button is gone
   (Messages is a tab on this workspace and a destination in the global nav, so it
   was the third route to the same place) and the width it was using now lets the
   status lay out as a single line: lamp, state, count.

   And it now reports when nothing is wrong. A control that only appears on failure
   leaves you unable to tell "this flight is clear" from "this did not load", which
   is the one thing a pre-departure check has to be certain about.

   The green state is deliberately NOT the filled treatment that amber and red get.
   A big green "all good" panel on black is backwards — normal recedes, and only an
   exception is allowed to pop. So the clear state keeps the plain surface and the
   ordinary border, and spends its colour on the lamp and the word. It reads as
   unmistakably green without competing with a caution three inches away. */
.flight-alerts {
   gap: 11px;
   padding: 0 15px;
   min-height: 44px
}

.flight-alerts strong {
   font-size: 13px;
   letter-spacing: 0;
   white-space: nowrap
}

/* The count steps back from the state word by WEIGHT and SIZE, not by colour —
   12px/400 against 13px/700. Fading it was the first attempt and it cost contrast
   the light theme could not afford: at 72% alpha the dark header measured exactly
   4.50:1, and in light the green fell to 3.74:1, because fading toward a white
   background eats far more contrast than fading toward a black one. A hierarchy
   built on weight costs nothing in either theme. The separator keeps its alpha —
   it is a rule between two labels, not something anyone has to read. */
.flight-alerts .annunciator-detail {
   font-size: 12px;
   white-space: nowrap;
   padding-left: 11px;
   border-left: 1px solid color-mix(in srgb, currentColor 28%, transparent)
}

/* Confirmed sits on the surface and carries a dim green mark. */
/* #147653 is the green the status badges already use for a confirmed state, and it
   is dark enough to clear AA on the light header — the lighter #2f7d5f a first pass
   used only reached 4.98:1. */
.flight-alerts.normal {
   color: #147653;
   border-color: var(--line);
   background: transparent
}

.flight-alerts.normal .annunciator-lamp {
   background: #1a936f;
   box-shadow: 0 0 8px #1a936f7a
}

[data-theme=dark] .flight-alerts.normal {
   color: #45b98d;
   border-color: #2f2f2f
}

[data-theme=dark] .flight-alerts.normal .annunciator-lamp {
   background: #45b98d;
   box-shadow: 0 0 8px #45b98d7a
}

/* Keep the alert label and its count legible on phone layouts. */
@media(max-width:700px) {
   .flight-alerts {
      padding: 0 12px;
      gap: 9px
   }

   .flight-alerts .annunciator-detail {
      padding-left: 9px
   }
}

/* The long-form all-clear note is dismissible — the header status is the durable
   report, so this one is allowed to be got rid of. The control is quiet because
   the thing it closes is itself the quietest thing on the page. */
.banner-dismiss {
   margin-left: auto;
   align-self: flex-start;
   width: 30px;
   height: 30px;
   display: grid;
   place-items: center;
   border-radius: 6px;
   color: var(--muted);
   flex-shrink: 0
}

/* Shared reading sizes for supporting text across the working app. */
.app-shell :is(
   .route-heading p, .schedule small, .zulu-time, .flight-row-meta,
   .direction-label, .flight-reason, .inbox-top p, .workspace-footnote,
   .activity-strip .time, .timeline-item>div>span, .person-name>span,
   .channel-heading p, .hub-route small, .hub-channel small,
   .hub-section-label small, .hub-thread-flight small, .contact-identity p,
   .contact-legs-heading p, .contact-leg-section h5,
   .contact-leg-section h5 span, .contact-leg-route small,
   .switch, .hub-tool, .text-button, .soft-view-button, .inline-action,
   .fuel-numbers>div>span, .field-hint
) {
   font-size: 12px;
   line-height: 1.45
}

.app-shell :is(
   .card-heading p, .section-heading p, .attention-heading p,
   .attention-items div span, .readiness-detail, .activity-strip,
   .activity-strip strong, .person-name strong, .hub-channel strong,
   .hub-section-label strong, .comments, .delivery-note
) {
   font-size: 13px;
   line-height: 1.5
}

/* Supporting facts stay neutral, with enough contrast to read at these sizes. */
.app-shell :is(
   .route-heading p, .schedule span, .schedule small, .zulu-time,
   .card-heading p, .section-heading p, .readiness-detail,
   .person-name>span, .workspace-footnote, .field-hint
) {
   color: var(--muted-strong)
}

.app-shell .attention-items strong {
   font-size: 14px
}

.app-shell .readiness-detail {
   white-space: normal;
   overflow-wrap: anywhere
}

/* Keep compact flight rows scannable without squeezing the route off-screen. */
.app-shell .flight-row-top .zulu-time {
   font-size: 11px
}

/* Pilot header: route, two timing columns, then a separate full-width alert row. */
@media (max-width: 999px) {
   .role-pilot .flight-header {
      flex-direction: column;
      align-items: stretch !important;
      gap: 22px;
      padding: 20px 18px 18px
   }
   .role-pilot .flight-header .route-heading {
      gap: 12px;
      min-width: 0;
      overflow: visible
   }
   .role-pilot .route-heading>div { min-width: 0; flex: 1 }
   .role-pilot .route-heading .eyebrow { display: none }
   .role-pilot .flight-header .flight-symbol {
      display: none
   }
   .role-pilot .flight-header h2 {
      font-size: 28px;
      font-weight: 700;
      letter-spacing: -.035em;
      line-height: 1.2;
      gap: 14px;
      margin: 0 0 10px
   }
   .role-pilot .route-heading h2>.app-icon { --icon-size: 22px !important }
   .role-pilot .route-heading p {
      flex-wrap: wrap;
      gap: 6px 10px;
      white-space: normal;
      overflow-wrap: anywhere;
      margin: 0
   }
   .role-pilot .flight-header .tail-plate {
      font-size: 12px;
      font-weight: 600;
      line-height: 1.45;
      padding: 0 10px 0 0;
      border: 0;
      border-right: 1px solid var(--line);
      border-radius: 0;
      background: transparent;
      color: var(--ink)
   }
   .role-pilot .flight-aircraft-description { font-size: 12px; line-height: 1.45 }
   .role-pilot .flight-header-right.d-flex {
      display: flex !important;
      flex-direction: column;
      align-items: stretch !important;
      gap: 12px;
      width: 100%;
      max-width: none
   }
   .role-pilot .flight-header-right>.schedule {
      display: grid !important;
      grid-template-columns: repeat(2, minmax(0, 1fr));
      align-items: start;
      gap: 16px;
      width: 100%;
      margin: 0;
      padding: 0 0 14px;
      border-right: 0;
      border-bottom: 1px solid var(--line);
      text-align: left
   }
   .role-pilot .schedule>div { gap: 6px; min-width: 0 }
   .role-pilot .schedule .schedule-label {
      font-size: 12px;
      font-weight: 500;
      line-height: 1.4
   }
   .role-pilot .flight-header-right>.schedule strong {
      font-size: 18px;
      font-weight: 600;
      font-variant-numeric: tabular-nums;
      letter-spacing: -.025em;
      line-height: 1.3
   }
   .role-pilot .schedule strong small { font-size: 12px; font-weight: 500; letter-spacing: 0 }
   .role-pilot .schedule .zulu-time { font-size: 12px; line-height: 1.4 }
   .role-pilot .schedule-duration>.zulu-time { display: none }
   .role-pilot .flight-header-right>.flight-alerts {
      width: 100%;
      min-width: 0;
      min-height: 44px;
      padding: 10px 12px;
      gap: 10px
   }
   .role-pilot .flight-alerts .annunciator-detail {
      margin-left: auto;
      border-left: 0;
      padding-left: 0
   }
}
/* Aircraft workspace: one identity card, then one focused detail section. */
.aircraft-view {
   display: grid;
   gap: 24px;
   min-width: 0;
   container-type: inline-size
}

.aircraft-identity-card {
   background: var(--ops-surface, #fff);
   border: 1px solid var(--line);
   border-radius: 12px;
   overflow: hidden
}

.aircraft-view .aircraft-summary {
   padding: 20px;
   gap: 16px;
   border: 0;
   border-radius: 0;
   background: transparent
}

.aircraft-view .aircraft-large-icon {
   width: 56px;
   height: 56px;
   flex-shrink: 0;
   background: var(--ops-soft, #f4f4f4);
   border: 1px solid var(--line)
}

.aircraft-identity-copy { min-width: 0; flex: 1 }
.aircraft-identity-label { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; font-size: 12px; color: var(--muted) }
.aircraft-view .aircraft-summary h3 { font-size: 22px; line-height: 1.25; margin: 7px 0 4px }
.aircraft-view .aircraft-summary p { font-size: 13px; color: var(--muted) }
.aircraft-identity-status { display: flex; flex-direction: column; align-items: flex-end; gap: 8px; flex-shrink: 0 }
.aircraft-meta-label { font-size: 12px; color: var(--muted) }

.aircraft-action-bar { padding: 12px 20px; border-top: 1px solid var(--line); background: var(--ops-soft, #f6f6f6) }
.aircraft-action-bar:empty { display: none }
.aircraft-action-bar .workflow-action-row { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 }
.aircraft-action-bar .app-button { font-size: 12px; min-height: 36px; padding: 8px 12px }
.aircraft-action-bar .mechanical-banner { margin-bottom: 12px }

/* Pilot actions form a single column, including inside the phone preview. */
.role-pilot .aircraft-action-bar .workflow-action-row {
   display: grid;
   grid-template-columns: minmax(0, 1fr);
   gap: 10px
}
.role-pilot .aircraft-action-bar .app-button {
   width: 100%;
   min-height: 46px;
   justify-content: flex-start;
   padding: 12px 14px;
   font-size: 13px;
   gap: 10px
}
.role-pilot .aircraft-action-bar .app-button>.app-icon {
   --icon-size: 20px !important;
   flex-shrink: 0
}

.aircraft-view .aircraft-panes { gap: 22px; min-width: 0 }
.aircraft-view .aircraft-pane-switch {
   flex-wrap: nowrap;
   gap: 22px;
   border-bottom: 1px solid var(--line);
   overflow-x: auto;
   scrollbar-width: thin
}
.aircraft-view .aircraft-pane-button {
   flex-shrink: 0;
   padding: 0 0 13px;
   border: 0;
   border-bottom: 2px solid transparent;
   border-radius: 0;
   background: transparent;
   color: var(--muted);
   font-size: 13px
}
.aircraft-view .aircraft-pane-button.active {
   color: var(--ink);
   border-bottom-color: var(--ink);
   background: transparent
}
.aircraft-pane-button .status-badge { padding: 2px 6px; font-size: 11px }
.aircraft-view .aircraft-pane-body,
.aircraft-trip-details { display: grid; gap: 18px; min-width: 0 }
.aircraft-view .section-heading { gap: 16px; align-items: flex-start !important; margin: 0 }
.aircraft-view .section-heading h3 { font-size: 18px }
.aircraft-view .section-heading p { margin-top: 5px }
.aircraft-view .section-heading>.status-badge { flex-shrink: 0; margin-top: 3px }

.aircraft-view .services-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px }
.aircraft-view .service-card { padding: 18px; gap: 16px; background: var(--ops-surface, #fff) }
.aircraft-view .service-card.tone-amber { background: color-mix(in srgb, var(--ops-surface, #fff) 94%, #c98a16) }
.aircraft-view .service-card.tone-red { background: color-mix(in srgb, var(--ops-surface, #fff) 94%, #c0392f) }
.aircraft-view .service-card-heading { display: grid; grid-template-columns: 30px minmax(0, 1fr) auto; gap: 10px; align-items: center }
.aircraft-view .service-card-heading h4 { font-size: 14px; line-height: 1.35 }
.aircraft-view .service-card-heading>.status-badge { font-size: 11px }
.aircraft-view .service-item-list { gap: 12px }
.aircraft-view .service-item-note { font-size: 12px; line-height: 1.5 }
.aircraft-view .service-card-link { padding-top: 10px; border-top: 1px solid var(--line); width: 100%; justify-content: space-between }
.aircraft-view .two-column { align-items: stretch; gap: 18px; min-width: 0 }
.aircraft-view .details-list>div { gap: 14px }
.aircraft-view .details-list dd { overflow-wrap: anywhere }
.aircraft-view .itinerary { gap: 14px }
.aircraft-view .itinerary>div { flex: 1; min-width: 0 }
.aircraft-view .itinerary>div>span:last-child { font-size: 12px; line-height: 1.5 }
.aircraft-view .itinerary>.app-icon { flex-shrink: 0 }

@container (min-width: 1100px) {
   .aircraft-view .services-grid { grid-template-columns: repeat(3, minmax(0, 1fr)) }
}

@container (max-width: 760px) {
   .aircraft-action-bar .workflow-action-row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)) }
   .aircraft-action-bar .app-button { justify-content: center; white-space: normal }
}

@container (max-width: 640px) {
   .aircraft-view .services-grid,
   .aircraft-view .two-column { grid-template-columns: 1fr }
   .aircraft-view .aircraft-summary { padding: 16px; gap: 12px; flex-wrap: wrap }
   .aircraft-view .aircraft-summary h3 { font-size: 20px }
   .aircraft-view .aircraft-pane-switch { gap: 18px }
   .aircraft-view .section-heading { flex-wrap: wrap }
   .aircraft-action-bar { padding: 12px 16px }
   .aircraft-view .card-heading { flex-wrap: wrap }
}

@container (max-width: 380px) {
   .aircraft-identity-label>span:last-child { display: none }
   .aircraft-view .aircraft-large-icon { width: 44px; height: 44px }
   .aircraft-identity-status { flex-direction: row; align-items: center; width: 100%; justify-content: space-between; padding-top: 12px; border-top: 1px solid var(--line) }
   .aircraft-view .service-card { padding: 14px }
   .aircraft-view .service-card-heading { gap: 8px }
}
/* Message search — the field, the scope chips and the marks
 * ============================================================================
 *
 * NO SYSTEM CHROME, ANYWHERE IN HERE
 * Every part of a search is something a browser will happily draw for you, and
 * every one of them is drawn here instead:
 *
 *   `<input type=search>`   WebKit adds `::-webkit-search-cancel-button`, a grey
 *                           glyph that ignores the page's colours and cannot be
 *                           restyled. The input is `type=text`; the clear control
 *                           is `.msg-search-clear`.
 *   autofill / autocorrect  Chrome's suggestion menu is native chrome rendered
 *                           over the app. `autoComplete=off` and friends are set
 *                           on the input, and `:-webkit-autofill` is neutralised.
 *   the focus ring          the input's own outline is removed and the ring is
 *                           painted on the wrapper, so the whole field lights up
 *                           rather than a rectangle inside it.
 *   `<mark>`                the UA paints `background: mark` — system yellow with
 *                           system black on it, one of the few colours in a
 *                           browser that never follows a dark theme.
 *   `<kbd>`                 defaults to the platform monospace with no box.
 *
 * WHAT THE COLOUR MEANS
 * The hub already owns one accent: `--accent-blue`, which IS the Messages
 * category hue, and nothing on these surfaces is ever "wrong" — so search chrome
 * takes that same hue rather than introducing a second one. A highlight is the
 * app pointing at something, which is the same act as the rail's selected row,
 * so it is the same colour.
 *
 * THE MARK IS NOT ONLY A COLOUR
 * A tint alone puts the whole answer in one channel, so the mark carries an
 * underline too (1.4.1). It is painted with `color-mix` against `--accent-blue`
 * and takes `color: inherit`, which is what lets one declaration sit correctly on
 * white, on the tinted selected row and on the dark theme's near-black.
 */

/* The rail's own control scale — the `.flight-inbox` ladder is scoped to the
   board and is a size larger than anything in this rail. The field is the primary
   control here; a chip is a chip. Both clear the 24px minimum target. */
.msg-search {
   --search-h: 38px;
   --scope-h: 26px;
   flex: 1 0 100%;
   display: flex;
   align-items: center;
   gap: 8px;
   min-width: 0;
   height: var(--search-h);
   margin-top: 12px;
   padding: 0 8px 0 11px;
   border: 1px solid var(--line);
   border-radius: 8px;
   background: var(--ops-surface, #fff);
   color: var(--muted-strong);
   transition: border-color .14s var(--ease-standard), box-shadow .14s var(--ease-standard)
}

.msg-search>.app-icon {
   flex: none
}

.msg-search input {
   flex: 1;
   min-width: 0;
   align-self: stretch;
   appearance: none;
   border: 0;
   outline: 0;
   background: transparent;
   font: inherit;
   font-size: 12px;
   color: var(--ink)
}

.msg-search input::placeholder {
   color: var(--muted-strong);
   opacity: 1
}

/* Belt and braces: the input is `type=text` so none of these should ever be
   rendered, but a stray `type=search` in a later edit must not silently hand the
   field back to the platform. */
.msg-search input::-webkit-search-cancel-button,
.msg-search input::-webkit-search-decoration,
.msg-search input::-webkit-search-results-button,
.msg-search input::-webkit-contacts-auto-fill-button {
   appearance: none;
   display: none
}

/* Autofill paints its own background and text colour through an internal shadow
   that `background` cannot override — an inset shadow the size of the field is
   what actually repaints it. */
.msg-search input:-webkit-autofill,
.msg-search input:-webkit-autofill:focus {
   -webkit-text-fill-color: var(--ink);
   box-shadow: inset 0 0 0 100vmax var(--ops-surface, #fff)
}

/* The ring is on the wrapper, so focus lights the control rather than a box
   inside it. This IS the focus indicator for the input — the input's own outline
   is gone — so it is a full 3px against an accent border, not a hairline. */
.msg-search:focus-within {
   border-color: var(--accent-blue);
   box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent-blue) 22%, transparent)
}

.msg-search-clear {
   flex: none;
   width: 24px;
   height: 24px;
   display: grid;
   place-items: center;
   border-radius: 6px;
   color: var(--muted-strong)
}

/* The shortcut hint occupies the clear button's slot, so the field does not change
   width the moment you type into it. */
.msg-search-key {
   flex: none;
   font-family: var(--font-mono);
   font-size: 10px;
   line-height: 1;
   letter-spacing: .02em;
   color: var(--muted-strong);
   background: var(--ops-soft, #f1f1f1);
   border: 1px solid var(--line);
   border-radius: 5px;
   padding: 4px 6px
}

/* ── The scope chips ──────────────────────────────────────────────────────────
   They appear only while something is typed, because until then they would be
   five controls describing a search nobody has started. Each carries what it
   would find: the number is the promise, and a chip with nothing behind it goes
   quiet and unclickable rather than becoming a dead end. */
.msg-scopes {
   flex: 1 0 100%;
   display: flex;
   flex-wrap: wrap;
   gap: 6px;
   margin-top: 9px;
   animation: motionSettle var(--dur-fast) var(--ease-entrance) both
}

.msg-scope {
   display: inline-flex;
   align-items: center;
   gap: 6px;
   min-height: var(--scope-h, 26px);
   padding: 0 9px;
   border: 1px solid var(--line);
   border-radius: 999px;
   font-size: 12px;
   line-height: 1;
   color: var(--muted-strong)
}

.msg-scope>span {
   font-family: var(--font-mono);
   font-size: 10px;
   font-weight: 700;
   color: var(--muted-strong)
}

.msg-scope.active {
   background: var(--accent-blue);
   border-color: var(--accent-blue);
   color: var(--on-accent-blue);
   font-weight: 500
}

.msg-scope.active>span {
   color: color-mix(in srgb, var(--on-accent-blue) 78%, transparent)
}

/* Empty is not decoration — it is the chip answering "nothing down there", which
   is a useful answer and has to be readable to give it. It is a disabled control
   and so exempt from 1.4.3, but exempt is not invisible: the first pass dimmed it
   with `opacity: .55`, which took #717171 on the rail to an effective 2.17:1 and
   made the answer harder to read than the question. An explicit grey instead, at
   the same 3:1 the switch track is held to and for the same reason — it clears
   3.24:1 on the light rail and 5.35:1 on the dark one from one declaration, and it
   leaves the border alone, which opacity did not. */
.msg-scope.is-empty:not(.active),
.msg-scope.is-empty:not(.active)>span {
   color: #8e8e8e;
   cursor: default
}

/* ── What a row matched on ────────────────────────────────────────────────────
   A filter that silently removes rows is asking to be trusted. These say why each
   survivor is here, in the precise word — "Destination", not "Route" — so the
   chip that searched it and the fact it found are never confused. */
.hub-why {
   display: flex;
   flex-wrap: wrap;
   gap: 4px;
   margin-top: 6px
}

.hub-why em {
   font-style: normal;
   font-size: 10px;
   line-height: 1.5;
   letter-spacing: .05em;
   text-transform: uppercase;
   padding: 1px 5px;
   border: 1px solid var(--line);
   border-radius: 4px;
   color: var(--muted-strong);
   white-space: nowrap
}

/* The count of matching messages is the one that came from the thread itself
   rather than from the flight record, so it is the one wearing the hue. */
.hub-why em.is-text {
   color: var(--accent-blue);
   border-color: var(--accent-blue-line);
   background: var(--accent-blue-soft)
}

/* ── The row Enter will open ──────────────────────────────────────────────────
   The rail keeps schedule order, because that is how a day is read — so the best
   match is marked where it sits instead of being dragged to the top. The tint is
   deliberately fainter than the selected row's: this is a row you have not chosen
   yet. Declared before `.hub-channel.active`'s own surface so that a row which is
   both simply reads as selected. */
.hub-channel[data-top-hit] {
   background: color-mix(in srgb, var(--accent-blue) 6%, transparent)
}

.hub-enter {
   flex: none;
   min-width: 19px;
   height: 19px;
   display: grid;
   place-items: center;
   font-family: var(--font-mono);
   font-size: 11px;
   line-height: 1;
   color: var(--accent-blue);
   background: var(--accent-blue-soft);
   border: 1px solid var(--accent-blue-line);
   border-radius: 4px
}

/* ── The mark ─────────────────────────────────────────────────────────────────
   One declaration for the rail preview and for the thread, because they are the
   same act. `color: inherit` is what makes it correct on white, on the selected
   row's tint and in the dark theme without a single fork — and the underline is
   what keeps it from being a colour-only signal. */
.messages-workspace mark {
   background: color-mix(in srgb, var(--accent-blue) 24%, transparent);
   color: inherit;
   box-shadow: inset 0 -1.5px 0 var(--accent-blue);
   border-radius: 2px;
   padding: 0 1px
}

/* ── The thread says what was found in it ─────────────────────────────────────
   Without this, opening a result that matched on its tail looks like the
   highlighting is broken — the thread is right, and nothing in it is marked. */
.thread-match-note {
   display: flex;
   align-items: center;
   gap: 8px;
   flex: none;
   margin: 14px 18px 0;
   padding: 8px 12px;
   font-size: 12px;
   border-radius: 8px;
   color: var(--accent-blue);
   background: var(--accent-blue-soft);
   border: 1px solid var(--accent-blue-line)
}

.thread-match-note>.app-icon {
   flex: none
}

/* "You are not looking at a result" is not a finding, so it does not wear the
   hue the findings wear. It is the thread explaining itself, in the voice the rest
   of the app uses for a supporting fact. */
.thread-match-note.is-aside {
   color: var(--muted-strong);
   background: var(--ops-soft, #f6f6f6);
   border-color: var(--line)
}

/* ── Nothing found ────────────────────────────────────────────────────────────
   The one moment somebody is definitely looking for a better way to ask, so it is
   where the syntax is explained — rather than in a permanent hint line under the
   field, which would spend rail height every day on a question people have once. */
.search-tips {
   list-style: none;
   display: grid;
   gap: 7px;
   width: 100%;
   max-width: 250px;
   margin: 15px auto 17px;
   padding: 13px 14px;
   text-align: left;
   border: 1px solid var(--line);
   border-radius: 9px;
   background: var(--ops-soft, #f6f6f6);
   font-size: 12px;
   color: var(--muted-strong)
}

.search-tips b {
   display: block;
   font-family: var(--font-mono);
   font-size: 11px;
   font-weight: 700;
   color: var(--accent-blue);
   margin-bottom: 2px
}

.hub-empty .hub-tool {
   margin-inline: auto
}

/* ── Dark theme ───────────────────────────────────────────────────────────────
   Only the two surfaces that are literal colours rather than tokens need saying
   again. Everything else follows `--accent-blue` and `--ops-*`, which already
   flip. */
[data-theme=dark] .msg-search {
   background: var(--ops-soft, #131313);
   border-color: var(--line)
}

[data-theme=dark] .msg-search input:-webkit-autofill,
[data-theme=dark] .msg-search input:-webkit-autofill:focus {
   box-shadow: inset 0 0 0 100vmax var(--ops-soft, #131313)
}

[data-theme=dark] .msg-search-key,
[data-theme=dark] .search-tips {
   background: color-mix(in srgb, var(--ink) 7%, transparent)
}

/* ── Phone ────────────────────────────────────────────────────────────────────
   No keyboard, so no shortcut hint; and the chips get the full rail width to wrap
   into, which they have on a phone because the rail is the whole screen. */
@media (max-width:700px) {
   .msg-search-key {
      display: none
   }

   .msg-search {
      --search-h: 42px
   }
}
/* Interaction states — one rule for "the pointer is on this"
 * ============================================================================
 *
 * WHAT WAS WRONG
 * Hover had been written per surface, so it had no direction. In the light theme
 * most rows darkened (`#f9f9f9`, `#f5f5f5`, `#ededed`) but an attention item
 * *brightened* to `#fff` and dropped the lift its resting state had, so pointing
 * at it made it recede. A flight row darkened, moved up a pixel and grew a
 * shadow; nothing else moved at all. Three separate `[data-theme=dark]
 * .flight-row:hover` rules disagreed (`#323232`, `#252525`, `#1f1f1f`) and the
 * last one in the file silently won. Some controls strengthened their border,
 * others removed it, most ignored it. A board chip used `filter: brightness()`,
 * which brightens in both themes and is therefore the wrong direction in one of
 * them. And several clickable things had no hover at all.
 *
 * THE RULE
 * **Hover moves a surface one step toward its own foreground.** Written against
 * `currentColor`, that single declaration is correct everywhere without a theme
 * fork and without a per-surface value:
 *
 *   - a light row with dark text gets darker
 *   - the same row in the dark theme, with light text, gets lighter
 *   - a filled primary button — dark fill, white label — gets lighter
 *   - an amber attention row washes warmer rather than going neutral grey,
 *     so it stays recognisably amber while it responds
 *
 * It is painted as an inset shadow rather than a background so it composites
 * *over* whatever is underneath: a flat colour, the selected row's gradient, or
 * an amber tint. That is why the four hand-written tinted-row hovers could be
 * deleted outright — they now come out right on their own.
 *
 * THE TIERS
 * Depth of response tracks how much of a commitment the click is, and nothing
 * else varies:
 *
 *   1. Row / list item      wash only. No edge, no movement.
 *   2. Bordered control     wash + the edge strengthens.
 *   3. Filled control       a deeper wash. The fill never inverts on hover.
 *   4. Text link            underline only. No wash — there is no surface.
 *
 * Nothing moves on hover any more. In this app motion means a state actually
 * changed — a row pulses when its flight changes, the annunciator when an item
 * arrives — so spending movement on "the pointer is here" was borrowing from the
 * one vocabulary that has to stay trustworthy.
 *
 * The app header keeps its own hover (`--header-hover`). It is the one surface
 * that is black in both themes, so it has no theme to follow.
 */

:root {
   --hover-strength: 6%;
   --hover-strength-strong: 10%;
   --hover-edge: var(--muted-strong);
}

:root[data-theme=dark] {
   --hover-edge: #6a6a6a;
}

/* BOOTSTRAP DOES NOT GET TO PAINT A HOVER
   Bootstrap 5.3 is loaded from a CDN and the app puts its classes on real controls
   — `.dropdown-item`, `.btn`, `.form-control`. Bootstrap then paints its own hover
   background on them:

     .dropdown-item:focus,.dropdown-item:hover {
        color: var(--bs-dropdown-link-hover-color);
        background-color: var(--bs-dropdown-link-hover-bg) }

   and it themes off `data-bs-theme`, which this app never sets — it sets
   `data-theme`. So Bootstrap is stuck in light mode forever. In the dark theme a
   hovered dropdown item got Bootstrap's near-white #f8f9fa background underneath
   this file's near-white `--ink` label: 1.12:1, a white bar with the option name
   invisible inside it. Rest was 10.29:1, so it read perfectly until you pointed at
   it.

   This is the same defect as `.board-go` — a hover whose background and foreground
   are set by two rules that do not know about each other — except the two rules are
   in different stylesheets and one of them is a minified CDN file. Overriding the
   paint would leave Bootstrap still fighting for it, so instead its own variables
   are pointed at what this system wants: nothing for the background, so the wash
   below is the only thing that paints, and `--ink` for the label, which is what the
   lift sets anyway. Bootstrap's rule still wins the cascade and now agrees with us.

   `:focus` is in that same Bootstrap selector, but `.custom-select-menu
   .dropdown-item:focus` in styles.css is more specific and keeps its own surface. */
.app-shell .custom-select-menu {
   --bs-dropdown-link-hover-bg: transparent;
   --bs-dropdown-link-hover-color: var(--ink);
}

/* THE CURRENT ITEM DOES NOT RESPOND
   The selected flight row, the active tab, the chosen filter and the selected
   hour are where you already are. A hover response on those advertises a change
   that clicking will not produce, so each is excluded below rather than left out
   by accident — which is what had happened: they were simply never covered.
   The selected row is also the one element that owns a drop shadow, and the wash
   is painted as a shadow, so covering it would have silently eaten that. */

/* The wash. `currentColor` is what makes one value work on every surface. */
.flight-row:not(.is-selected):hover,
.readiness-row:hover,
.person-row:hover,
.notification-item:hover,
.chat-order-card:hover,
.card-footer-action:hover,
.attention-items>button:hover,
.custom-select-menu .dropdown-item:hover,
.public-flight-row:hover,
.group-toggle:hover,
.leg-card:hover,
.service-card-link:hover,
.workspace-tabs button:not(.active):hover,
.filter-tabs button:not(.selected):hover,
.date-filter summary:hover,
.activity-strip:hover,
.map-marker:hover,
.wx-hour:not(.is-selected):hover,
.mobile-role-nav button:hover,
.dev-segmented button:hover,
.tower-row:hover,
.board-ident:hover,
.board-attn:hover,
.app-button.secondary:hover,
.soft-view-button:hover,
.square-button:hover,
.aircraft-pane-button:not(.active):hover,
.group-index-chip:hover,
.hub-tool:hover,
.msg-search-clear:hover,
.msg-scope:not(.active):not(:disabled):hover,
.banner-dismiss:hover,
.inline-action:hover,
.card-footer-action:hover,
.annunciator:hover,
.dev-launcher:hover,
.dev-roles button:hover,
.dev-links button:hover {
   box-shadow: inset 0 0 0 100vmax color-mix(in srgb, currentColor var(--hover-strength), transparent);
}

/* Tier 2 — a bordered control also firms up its edge, so an outline reads as a
   control you are about to press rather than a panel you happen to be over. */
.app-button.secondary:hover,
.soft-view-button:hover,
.square-button:hover,
.aircraft-pane-button:not(.active):hover,
.group-index-chip:hover,
.hub-tool:hover,
.msg-scope:not(.active):not(:disabled):hover,
.dev-roles button:hover,
.dev-links button:hover {
   border-color: var(--hover-edge);
}

/* THE LABEL LIFTS WITH THE WASH — and this is not decoration, it is what keeps
   the model legible. Washing a surface *toward its own foreground* necessarily
   closes the gap between them, so on a label that is already quiet the wash alone
   costs contrast: measured on the light theme, the activity strip fell to 4.03:1,
   the date disclosure to 4.10:1 and the card footer action to 4.39:1 — all under
   AA, all of them fine at rest. Taking the label to full ink at the same moment
   more than repays the wash, so hovering makes a control easier to read rather
   than harder, in both themes.

   State-coloured controls are excluded on purpose. A tab is amber or red because
   it has work outstanding; the annunciator and the board chips are reporting what
   a flight is doing. Overwriting any of those with ink would let the pointer
   outrank the state, which is the one thing this palette never allows. They are
   excluded by `:not()` rather than by specificity, because they tie with this rule
   and would otherwise be decided by file order. */
.square-button:not(.selected):hover,
.aircraft-pane-button:not(.active):hover,
.group-index-chip:hover,
.msg-search-clear:hover,
.msg-scope:not(.active):not(:disabled):hover,
.banner-dismiss:hover,
.workspace-tabs button:not(.active):not(.has-caution):not(.has-warning):hover,
.activity-strip:hover,
.date-filter summary:hover,
.notification-item:hover,
.chat-order-card:hover,
.custom-select-menu .dropdown-item:hover,
.leg-card:hover,
.group-toggle:hover,
.public-flight-row:hover {
   color: var(--ink);
}

/* ACCENT-BEARING CONTROLS ARE ABSENT FROM THE LIFT, for the same reason as a tab
   one step down. A button that wears the identity blue is wearing it to say "press
   me"; taking its label to ink would make pointing at it drain the colour out —
   the pointer undoing the affordance it is responding to. They keep the wash,
   which being `currentColor` washes them *bluer*, and firm their edge to the full
   accent instead of the neutral `--hover-edge`. So the response is the control
   committing to the colour it already had.

   This is safe for contrast in a way the neutral case was not: the labels start
   at 5.9–7.4:1 rather than the ~4.6:1 the muted greys started at, and the wash
   costs about half a point. Measured at the bottom of this file's companion audit:
   6.03 → 5.53 light, 7.36 → 6.63 dark. The lift exists to repay a wash that would
   otherwise break AA; here there is nothing to repay. */
.hub-view .hub-tool:hover,
.hub-view .hub-tool:focus-visible,
.app-shell:not(.board-shell) .app-button.secondary:hover,
.app-shell:not(.board-shell) .app-button.secondary:focus-visible,
.app-shell:not(.board-shell) .soft-view-button:hover,
.app-shell:not(.board-shell) .soft-view-button:focus-visible,
.app-shell:not(.board-shell) .inline-action:hover,
.flight-inbox .square-button.selected:hover {
   border-color: var(--accent-blue);
}

/* Tabs are deliberately absent from the rule above. They take the wash and
   nothing else: lifting a tab's label to ink on hover would overwrite the amber or
   red it is wearing because it has work outstanding, and state has to outrank the
   pointer. The same reasoning keeps the annunciator and the board chips out. */

/* Two controls that are drawn as an outline on a busy surface — a map pin and the
   date disclosure — where the wash alone is too quiet to read. */
.map-marker:hover,
.date-filter summary:hover {
   border-color: var(--hover-edge);
}

/* Tier 3 — filled controls go a step deeper, and never invert. */
.app-button.primary:hover,
.app-button.btn-primary:hover,
.board-go:hover,
.board-go:focus-visible,
.board-issue-go:hover,
.board-open-flight:hover,
.board-chip:hover,
.filled-action:hover,
.wx-motion:hover {
   box-shadow: inset 0 0 0 100vmax color-mix(in srgb, currentColor var(--hover-strength-strong), transparent);
}

/* Tier 4 — a link has no surface, so it gets the underline and nothing else. */
a:hover,
.text-button:not(.filled-action):hover,
.inline-action:hover {
   text-decoration: underline;
}

/* Keyboard parity. Anything that responds to a pointer responds to focus, or the
   affordance exists only for people using a mouse. The ring is the app's own; the
   wash is what makes focus and hover read as the same state. */
.flight-row:focus-visible,
.readiness-row:focus-visible,
.person-row:focus-visible,
.notification-item:focus-visible,
.chat-order-card:focus-visible,
.card-footer-action:focus-visible,
.attention-items>button:focus-visible,
.public-flight-row:focus-visible,
.group-toggle:focus-visible,
.leg-card:focus-visible,
.app-button.secondary:focus-visible,
.soft-view-button:focus-visible,
.square-button:focus-visible,
.aircraft-pane-button:focus-visible,
.group-index-chip:focus-visible,
.hub-tool:focus-visible,
.msg-search-clear:focus-visible,
.msg-scope:not(.active):focus-visible,
.banner-dismiss:focus-visible,
.filled-action:focus-visible {
   box-shadow: inset 0 0 0 100vmax color-mix(in srgb, currentColor var(--hover-strength), transparent);
}

/* The wash is a colour change, so it is safe under reduced motion; the
   transition that carries it is not always wanted. */
.flight-row,
.readiness-row,
.person-row,
.notification-item,
.chat-order-card,
.card-footer-action,
.attention-items>button,
.public-flight-row,
.group-toggle,
.leg-card,
.app-button,
.soft-view-button,
.square-button,
.aircraft-pane-button,
.group-index-chip,
.hub-tool,
.msg-search-clear,
.msg-scope,
.filled-action {
   transition: box-shadow .14s var(--ease-standard), border-color .14s var(--ease-standard), color .14s var(--ease-standard);
}

@media (prefers-reduced-motion: reduce) {

   .flight-row,
   .readiness-row,
   .person-row,
   .notification-item,
   .chat-order-card,
   .card-footer-action,
   .attention-items>button,
   .public-flight-row,
   .group-toggle,
   .leg-card,
   .app-button,
   .soft-view-button,
   .square-button,
   .aircraft-pane-button,
   .group-index-chip,
   .hub-tool,
   .msg-search-clear,
   .msg-scope,
   .filled-action {
      transition-duration: .001ms;
   }
}
/* Motion system — every entrance and transition in the platform is defined here,
   and nowhere else. Components add class names and data attributes; nothing
   computes an animation value in JavaScript.

   THE DIRECTION GRAMMAR
   The whole point of keeping this in one file is that motion never contradicts
   the information architecture. One relationship, one axis, always the same way:

     siblings in an ordered row   X   the workspace tab row, the drawer stack.
                                      A destination further along the row enters
                                      from the right and leaves to the left; going
                                      back is the exact reverse. Direction is read
                                      from the tab order in App.jsx — never guessed.
     overview -> detail           —   NO whole-screen move in either direction. A
                                      screen that scales to announce a depth change
                                      animates the furniture instead of the content,
                                      and it drowns out the list motion underneath
                                      it. Instead the flights themselves cascade in:
                                      the rail on the way into a flight, the board
                                      rows on the way back out. Going in also keeps
                                      a shared-element View Transition that carries
                                      the route and tail from the row into the
                                      workspace header — two specific facts moving
                                      to where they land, which is the opposite of
                                      moving everything.
     edge-anchored overlays       edge the drawer lives on the right edge, so it
                                      arrives from and leaves to the right. The
                                      toast lives in the bottom-right corner and
                                      arrives from it.
     same slot, new record        Y   picking another flight. A vertical list has
                                      no left or right, so nothing slides sideways
                                      — it cross-fades and settles upward.
     first paint                  Y   chrome settles in reading order: header,
                                      then the rail, then the workspace.

   Anything with no honest direction gets the vertical settle, not an invented
   sideways one. That is the rule that keeps "this should go right but it went
   left" from ever happening. */

:root {
  /* One timing scale. Duration and distance are set together on purpose: a short
     move over a short distance reads as a flicker rather than as movement, because
     the only thing the eye catches is the opacity change. Page-level motion is
     given both the time and the travel to be seen as travel.

     Hover and press feedback is deliberately NOT on this scale — that stays at the
     ~.15s in styles.css, because a control that answers late feels broken. This
     scale is for things that move you somewhere. */
  --dur-fast: 240ms;
  --dur-base: 380ms;
  --dur-slow: 520ms;
  /* Entrances decelerate into place; exits accelerate away. `--ease-standard` is a
     hard decelerate — most of its travel is over inside the first quarter, which is
     right for a 150 ms hover and wrong for a page, where it leaves a long invisible
     tail and reads as a snap. Entrances get a gentler curve that keeps moving for
     most of its duration. */
  --ease-entrance: cubic-bezier(.33, 1, .68, 1);
  --ease-exit: cubic-bezier(.4, 0, 1, 1);
  /* Cards settling behind a page change. Capped at four steps — 180 ms in total. */
  --stagger-step: 45ms;
  /* Rows in a list introducing itself. This is deliberately a large fraction of
     `--dur-fast` (which is what the rows animate at): at a 26 ms step against a
     380 ms row, fourteen rows are all mid-flight at once and the cascade reads as
     one soft blur rather than as rows arriving one after another. At 60 ms only
     about four overlap, which is what makes the sequence legible. The delay is
     capped at ten steps wherever it is used, so a full day still finishes. */
  --stagger-row: 60ms;
  /* Travel distances, set with the durations above rather than independently. */
  --shift-page: 36px;
  --shift-surface: 16px;
  --shift-row: 14px;
}

/* ---- keyframes --------------------------------------------------------- */
/* Named for the relationship they express, not for the direction they happen to
   travel, so a call site cannot pick a contradictory one by accident. */

@keyframes motionNext { from { opacity: 0; transform: translate3d(var(--shift-page), 0, 0) } }
@keyframes motionPrev { from { opacity: 0; transform: translate3d(calc(var(--shift-page) * -1), 0, 0) } }
@keyframes motionSwap { from { opacity: 0; transform: translate3d(0, var(--shift-surface), 0) } }
@keyframes motionSettle { from { opacity: 0; transform: translate3d(0, var(--shift-row), 0) } }
@keyframes motionFade { from { opacity: 0 } }
@keyframes motionFromTop { from { opacity: 0; transform: translate3d(0, -9px, 0) } }
@keyframes motionFromLeft { from { opacity: 0; transform: translate3d(-12px, 0, 0) } }

/* ---- first paint ------------------------------------------------------- */
/* `is-booting` is on the document element for the first 700 ms only, so the
   shell settles once on load and never again — switching tabs, flights or home
   views must not replay it. */

html.is-booting .app-header { animation: motionFromTop var(--dur-base) var(--ease-entrance) both }
html.is-booting .flight-inbox { animation: motionFromLeft var(--dur-base) var(--ease-entrance) 90ms both }
html.is-booting .workspace { animation: motionSwap var(--dur-slow) var(--ease-entrance) 150ms both }
html.is-booting .mobile-role-nav { animation: motionSwap var(--dur-base) var(--ease-entrance) 150ms both }

/* ---- the workspace content slot ---------------------------------------- */
/* App.jsx remounts this element on every tab or flight change (it is keyed), so
   the enter replays on its own. `data-motion` says which relationship the change
   was, and only the tab row is ever allowed to claim a side. */

.workspace-content { animation: motionSwap var(--dur-base) var(--ease-entrance) both }
.workspace-content[data-motion=next] { animation-name: motionNext }
.workspace-content[data-motion=prev] { animation-name: motionPrev }
.workspace-content[data-motion=swap] { animation-name: motionSwap }

/* The cards inside settle behind the slot itself rather than arriving with it,
   which is what makes a dense screen read as one movement instead of twelve.
   Capped at six — past that the last card would arrive after the eye has already
   moved on. */
.workspace-content > * { animation: motionFade var(--dur-base) var(--ease-entrance) both }
.workspace-content > :nth-child(1) { animation-delay: 0ms }
.workspace-content > :nth-child(2) { animation-delay: calc(var(--stagger-step) * 1) }
.workspace-content > :nth-child(3) { animation-delay: calc(var(--stagger-step) * 2) }
.workspace-content > :nth-child(4) { animation-delay: calc(var(--stagger-step) * 3) }
.workspace-content > :nth-child(n+5) { animation-delay: calc(var(--stagger-step) * 4) }

/* ---- the tab row ------------------------------------------------------- */
/* The active underline grows in the direction of travel: move right and it grows
   from its left edge rightward. It is the smallest possible confirmation that
   the screen went the way you asked it to. */

.workspace-tabs button.active:after {
  animation: motionUnderline var(--dur-base) var(--ease-entrance) both;
  transform-origin: left center;
}
.workspace-tabs[data-motion=prev] button.active:after { transform-origin: right center }
.workspace-tabs[data-motion=swap] button.active:after,
.workspace-tabs:not([data-motion]) button.active:after { animation-name: motionFade }
@keyframes motionUnderline { from { transform: scaleX(0) } }

/* ---- arriving anywhere -------------------------------------------------- */
/* Neither direction is a whole-screen move any more, and neither is a View
   Transition: the list you land on introduces itself instead. `data-enter` is set for the length of the cascade
   only (board.jsx drops it), so this plays on arrival and never again — typing
   in the search box or opening a row must not restage the whole day.

   The step is capped: past a dozen rows the delay stops growing, or the bottom of
   a full day would still be arriving after the eye has finished reading the top. */

/* This is the board's whole entrance, on first paint as well as on return — the
   container deliberately has no animation of its own. That is not only taste: an
   `is-booting` rule that swapped these rows to a different animation-name for the
   first 700 ms restarted them the moment the class came off, and the cascade
   visibly ran twice. One rule, one name, for the life of the animation. */
.board-view[data-enter] .board-row-wrap {
  animation: motionSettle var(--dur-fast) var(--ease-entrance) both;
  animation-delay: calc(min(var(--motion-index, 0), 10) * var(--stagger-row));
}

/* ---- disclosure --------------------------------------------------------- */
/* One mechanism for every region that grows from nothing to a height nobody knows
   in advance: the board's expanded flight, the Messages hub's flights. `0fr -> 1fr`
   is the only way to transition to an unknown height without measuring anything in
   JavaScript, and it runs in both directions from one declaration — so closing is
   as considered as opening, which is the half most disclosures get wrong.

   The content must stay mounted for that, which means it also has to be kept out of
   the tab order while closed: every call site marks it `inert`. The clipped child is
   the direct child, and it carries the padding — any padding outside it would keep
   the region from collapsing to nothing. */

[data-disclosure] {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--dur-fast) var(--ease-entrance);
}
[data-disclosure=open] { grid-template-rows: 1fr }
[data-disclosure] > * { min-height: 0; overflow: hidden }

@media (prefers-reduced-motion: reduce) {
  [data-disclosure] { transition: none }
}

/* ---- the toast --------------------------------------------------------- */
/* It lives in the bottom-right corner, so it arrives from that corner and leaves
   back into it. `layout.jsx` keeps the node mounted for the length of the exit —
   a toast that is simply cut at the end of its dwell is the one piece of motion
   everybody notices. */

.toast-message.is-closing { animation: motionToastOut var(--dur-fast) var(--ease-exit) forwards }
@keyframes motionToastOut { to { opacity: 0; transform: translate(10px, 14px) } }

/* ---- the drawer stack -------------------------------------------------- */
/* The drawer itself arrives from the right edge it is pinned to (styles.css owns
   that). Inside it, drilling deeper is the same sibling grammar as the tab row.
   Opening the drawer is not a push — the panel must not slide right while the
   drawer it sits in is also sliding right — so depth 0 -> 1 carries no direction.

   A popped page is revealed by dropping `hidden`, which puts it back in the box
   tree and restarts the animation without React remounting it. Nothing below the
   top of the stack loses its state. */

.dynamic-drawer[data-motion=push] .drawer-page:not([hidden]) { animation: motionNext var(--dur-base) var(--ease-entrance) both }
.dynamic-drawer[data-motion=pop] .drawer-page:not([hidden]) { animation: motionPrev var(--dur-base) var(--ease-entrance) both }

/* ---- reduced motion ---------------------------------------------------- */
/* styles.css carries the global net; this repeats it for the View Transition
   pseudo-elements, which that net cannot reach. */

@media (prefers-reduced-motion: reduce) {
  html.is-booting *,
  .workspace-content,
  .workspace-content > *,
  .board-view[data-enter] .board-row-wrap,
  .drawer-page { animation: none !important }
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) { animation: none !important }
}

/* ---- a flight introducing itself ---------------------------------------- */
/* Opening a flight used to morph the row's route and tail into the header and
   then hand you a finished screen. The morph is gone; the workspace states itself
   instead, in the order you would read it aloud: what it is, where it is going,
   which aircraft, when, and what it needs. Nothing here is decoration — every
   step is a fact landing, which is why they arrive one at a time rather than
   together.

   Indices are set by selector rather than inline, because the order IS the
   reading order of the header and belongs next to the rest of the grammar.
   `App.jsx` keys the header on the flight id, so this replays for each new
   record and not on every tab change. */

.flight-header .flight-symbol,
.flight-header .eyebrow,
.flight-header .route-heading h2,
.flight-header .route-heading p,
.flight-header-right > * {
  animation: motionSettle var(--dur-base) var(--ease-entrance) both;
}
.flight-header .flight-symbol,
.flight-header .eyebrow { animation-delay: 0ms }
.flight-header .route-heading h2 { animation-delay: calc(var(--stagger-step) * 1) }
.flight-header .route-heading p { animation-delay: calc(var(--stagger-step) * 2) }
.flight-header-right > :nth-child(1) { animation-delay: calc(var(--stagger-step) * 3) }
.flight-header-right > :nth-child(2) { animation-delay: calc(var(--stagger-step) * 4) }
.flight-header-right > :nth-child(3) { animation-delay: calc(var(--stagger-step) * 5) }

/* The tail is the search key in this industry, so it is the one fact that does
   more than settle: its plate draws itself in as the line lands. Only paint is
   animated — no letter-spacing, no padding — because the plate sits in a text
   line, and anything that changes its width would shove the aircraft type along
   beside it. A reveal must not become a layout shift. */
.flight-header .tail-plate { animation: motionPlate var(--dur-base) var(--ease-entrance) calc(var(--stagger-step) * 2) both }
@keyframes motionPlate {
  from { opacity: 0; border-color: transparent; background-color: transparent }
}

/* ---- tabs that need someone --------------------------------------------- */
/* Once the header has finished, the tabs holding open work light up like a tube
   and then go out. Fast attack, long decay — roughly a tenth of the time coming
   up and the rest fading — which is what separates a glow from a pulsing alarm.
   One bloom, never a loop: it is a glance on arrival, not a state. The colour
   underneath already says "this needs someone" and keeps saying it afterwards.

   The label, the icon glyph and the count all light together, because a tube glows
   along its whole length, not in one spot — and since the count lost its pill they
   are all simply text now, which `text-shadow` reaches in one declaration.
   `text-shadow` inherits, so the button hands it to the label and the icon for
   free.

   `--neon` is a literal hue, not a token: `--state-caution` and `--state-warning`
   are themselves theme-dependent, so borrowing them lit the light theme with its
   own deep #a32b23 text red — a dark blur, the exact opposite of a glow. These two
   values are the dark palette's hues, which makes this true neon on the near-black
   surface it was designed for and a lit halo around the deeper text in light. */
.workspace-tabs .has-caution { --neon: #ffc233 }
.workspace-tabs .has-warning { --neon: #ff5f56 }

.workspace-tabs .has-caution,
.workspace-tabs .has-warning { animation: motionNeon 1500ms linear var(--neon-delay) both }
.workspace-tabs .has-caution:before,
.workspace-tabs .has-warning:before { animation: motionNeonBar 1500ms linear var(--neon-delay) both }

.workspace-tabs { --neon-delay: calc(var(--stagger-step) * 6) }

@keyframes motionNeon {
  0%   { text-shadow: 0 0 0 transparent }
  11%  { text-shadow: 0 0 6px var(--neon), 0 0 17px var(--neon) }
  100% { text-shadow: 0 0 0 transparent }
}
@keyframes motionNeonBar {
  0%   { box-shadow: 0 0 0 0 transparent }
  11%  { box-shadow: 0 0 9px 1px var(--neon), 0 0 24px 2px var(--neon) }
  100% { box-shadow: 0 0 0 0 transparent }
}

@media (prefers-reduced-motion: reduce) {
  .flight-header .flight-symbol,
  .flight-header .eyebrow,
  .flight-header .route-heading h2,
  .flight-header .route-heading p,
  .flight-header .tail-plate,
  .flight-header-right > *,
  .workspace-tabs .has-caution,
  .workspace-tabs .has-warning,
  .workspace-tabs .has-caution:before,
  .workspace-tabs .has-warning:before { animation: none !important }
}
