/* Schedule-specific styling. Every colour, space and radius comes from the
   Nocturne tokens in nocturne.css — see that file's :root block. The two
   exceptions are the status hues below, which carry meaning rather than
   decoration and are shared with the admin workbench. */

:root {
  /* cyan = protected (hatched), yellow = training (dashed).
     Pattern and label carry the meaning; hue is the third channel, never
     the only one. */
  --st-protect-mid: #2f7f92;
  --st-protect-deep: #123039;
  --st-protect-line: #7fd8e8;
  --st-protect-text: #dff6fb;
  --st-train-line: #d8b23a;
  --st-train-text: #f2dc9b;

  --name-col: 124px;
  --cell-h: 26px;
  --cell-font: 9px;
}

body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
  -webkit-font-smoothing: antialiased;
}

.page {
  min-height: 100vh;
  max-width: 1500px;
  margin: 0 auto;
  padding: 14px 16px 40px;
}

.muted { color: color-mix(in srgb, var(--color-text) 50%, transparent); }
.muted-2 { color: color-mix(in srgb, var(--color-text) 42%, transparent); }

.eyebrow {
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--color-text) 55%, transparent);
}

/* Rules fade at their ends rather than stopping cleanly — a Nocturne trait. */
.fade-rule {
  height: 1px;
  background: linear-gradient(to right, var(--color-divider), var(--color-divider) calc(100% - 48px), transparent);
  margin-bottom: 16px;
}

/* ── masthead ─────────────────────────────────────────── */

.masthead {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  padding-bottom: 10px;
}

.masthead img {
  width: 148px;
  height: auto;
  flex: none;
  margin-bottom: -6px;
}

.masthead-text {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding-left: 14px;
  border-left: 1px solid var(--color-divider);
}

.tail {
  font-family: var(--font-heading);
  font-weight: 500;
  font-size: 20px;
  letter-spacing: 0.06em;
  line-height: 1.1;
}

.tail-sub {
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--color-text) 50%, transparent);
}

/* Pushed to the far right of the masthead. These are one-time setup steps, so
   they belong with the page identity rather than beside the month controls,
   which are for getting around the schedule day to day. */
.masthead-actions {
  margin-left: auto;
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  justify-content: flex-end;
}

.masthead-action {
  min-width: 0;
  white-space: nowrap;
}

/* The workbench is for one person out of everyone who reads this page, so it
   sits alongside the others without competing with them. */
.masthead-action.is-quiet {
  color: color-mix(in srgb, var(--color-text) 55%, transparent);
  border-color: color-mix(in srgb, var(--color-text) 14%, transparent);
}
.masthead-action.is-quiet:hover { color: var(--color-text); }

/* ── today ────────────────────────────────────────────── */

.today-strip {
  display: flex;
  gap: 18px;
  flex-wrap: wrap;
  align-items: stretch;
  margin-bottom: 18px;
}

.today-card {
  flex: 0 0 auto;
  min-width: 156px;
  padding: 12px 16px 12px 0;
  border-right: 1px solid var(--color-divider);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

/* One reading order for both layouts — FRIDAY JUL 31 2026 — whether the parts
   are stacked down the card or laid along a line. Set here rather than per
   layout so the two cannot end up saying the date differently. */
.today-card .eyebrow { order: 1; }
.today-dow { order: 2; }
.today-day { order: 3; }
.today-year { order: 4; }

.today-card .eyebrow { color: var(--color-accent); }

.today-day {
  font-family: var(--font-heading);
  font-size: 34px;
  line-height: 1.05;
  margin-top: 2px;
}

.today-dow {
  font-size: 13px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--color-text) 62%, transparent);
}

.today-year {
  font-size: 11px;
  margin-top: 8px;
  color: color-mix(in srgb, var(--color-text) 50%, transparent);
}

.crew-list {
  flex: 1 1 320px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 6px 0;
}

.crew-row {
  display: grid;
  grid-template-columns: 44px 1fr auto;
  align-items: center;
  gap: 10px;
  padding: 5px 0;
  border-bottom: 1px solid color-mix(in srgb, var(--color-text) 8%, transparent);
}

.crew-name {
  display: flex;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
}

.crew-name b {
  font-family: var(--font-heading);
  font-weight: 500;
  font-size: 15px;
}

.crew-name span {
  font-size: 10px;
  letter-spacing: 0.1em;
  color: color-mix(in srgb, var(--color-text) 45%, transparent);
}

.crew-status {
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  white-space: nowrap;
  text-align: right;
  color: color-mix(in srgb, var(--color-text) 50%, transparent);
}

/* Text, not a second chip. The bare [data-status] rules paint anything
   carrying the attribute and are declared later in this file, so clearing the
   fill, outline and weight needs the extra specificity of naming both. Only
   the colour survives, which is what makes the word readable at a glance. */
.crew-status[data-status] {
  background: none;
  box-shadow: none;
  border: 0;
  text-shadow: none;
  font-weight: 400;
}

.crew-status[data-status='on'] { color: var(--color-text); }
.crew-status[data-status='vac'],
.crew-status[data-status='pers'] { color: var(--st-protect-line); }
.crew-status[data-status='trn'],
.crew-status[data-status='trv'] { color: var(--st-train-text); }

.crew-through {
  font-size: 11px;
  text-align: right;
  min-width: 104px;
  color: color-mix(in srgb, var(--color-text) 52%, transparent);
}

/* ── show filter + month navigation ───────────────────── */

.monthbar {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}

.filter-strip {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
}

.filter-btn {
  font: inherit;
  font-size: 11px;
  letter-spacing: 0.06em;
  padding: 3px 9px;
  border-radius: 4px;
  text-decoration: none;
  background: transparent;
  border: 1px solid var(--color-divider);
  color: color-mix(in srgb, var(--color-text) 70%, transparent);
  white-space: nowrap;
}

.filter-btn:hover {
  border-color: color-mix(in srgb, var(--color-accent) 55%, transparent);
  color: var(--color-text);
}

.filter-btn.is-active {
  background: color-mix(in srgb, var(--color-accent) 16%, transparent);
  border-color: var(--color-accent);
  color: var(--color-accent);
}

.filter-btn:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

.hidden-note {
  font-size: 10px;
  letter-spacing: 0.06em;
  margin-left: 4px;
  color: color-mix(in srgb, var(--color-text) 42%, transparent);
}

/* Row names double as filter toggles. */
a.rowname {
  text-decoration: none;
  color: inherit;
  cursor: pointer;
}

a.rowname:hover b { color: var(--color-accent-300); }
a.rowname.is-selected b { color: var(--color-accent); }

a.rowname:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: -2px;
}

.monthbar .spacer { margin-left: auto; }

/* Reusing the base .nav class for its layout brings a page-header's padding
   with it, which here just made the controls row taller than its buttons. */
.monthbar .nav {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 0;
  font-size: inherit;
}

.month-label {
  font-family: var(--font-heading);
  font-size: 14px;
  min-width: 74px;
  text-align: center;
  letter-spacing: 0.02em;
}

/* Divided off from the month arrows: both sets are small square buttons, and
   without the rule you reach for the wrong pair. */
.monthbar .zoom {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-left: 4px;
  padding-left: 8px;
  border-left: 1px solid var(--color-divider);
}

.btn.zoom-btn {
  min-width: 30px;
  padding: 2px 8px;
  font-size: 15px;
  line-height: 1.2;
}

/* Between the two buttons, so the pair reads as one control rather than as
   two more square buttons next to the month arrows. */
.zoom-label {
  white-space: nowrap;
  color: color-mix(in srgb, var(--color-text) 45%, transparent);
}

.btn:disabled { opacity: 0.45; pointer-events: none; }

/* Its own row under the controls. "Jump to Today" is the one long label up
   here, and centring it keeps the controls row from wrapping unevenly. */
.todaybar {
  display: flex;
  justify-content: center;
  margin-bottom: 10px;
}

.btn.nav-btn { min-width: 32px; padding: 3px 9px; }
.btn.today-btn { padding: 3px 14px; }

a.btn { text-decoration: none; display: inline-flex; align-items: center; justify-content: center; }

.btn[aria-disabled='true'] {
  opacity: 0.45;
  pointer-events: none;
}

/* ── month board ──────────────────────────────────────── */

.board-scroller {
  overflow-x: auto;
  padding-bottom: 6px;
}

/* One day column's width, and with it how many days fit before you scroll.
   The zoom buttons overwrite it on .board; these are the no-JavaScript
   defaults. Where the board comes out narrower than the screen the 1fr columns
   stretch to fill anyway, so zooming out simply stops having an effect. */
.board {
  position: relative;
  --day-w: 40px;
  min-width: calc(var(--name-col) + var(--days) * var(--day-w));
}

.grid {
  display: grid;
  grid-template-columns: var(--name-col) repeat(var(--days), minmax(0, 1fr));
  gap: 2px;
  margin-bottom: 2px;
}

.grid > .sticky {
  position: sticky;
  left: 0;
  z-index: 2;
  background: var(--color-bg);
}

.band {
  font-size: 8.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 2px 0 3px;
  color: color-mix(in srgb, var(--color-text) 34%, transparent);
  border-bottom: 1px solid color-mix(in srgb, var(--color-text) 8%, transparent);
  white-space: nowrap;
  overflow: hidden;
}

.dayhead {
  text-align: center;
  padding-bottom: 3px;
  color: color-mix(in srgb, var(--color-text) 60%, transparent);
}

.dayhead .dow { font-size: 8px; letter-spacing: 0.04em; opacity: 0.6; }
.dayhead .n { font-family: var(--font-heading); font-size: 12px; line-height: 1.2; }
.dayhead.is-today { color: var(--color-accent); }
.dayhead.is-past { opacity: 0.45; }

.rowname {
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding-right: 10px;
  border-right: 1px solid var(--color-divider);
}

.rowname b { font-family: var(--font-heading); font-weight: 500; font-size: 13px; }
.rowname span { font-size: 9px; letter-spacing: 0.1em; opacity: 0.5; }

/* ── cells ────────────────────────────────────────────── */

.cell {
  height: var(--cell-h);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--cell-font);
  letter-spacing: 0.02em;
  font-weight: 600;
  border-radius: 2px;
}

/* A 3px gutter marks each Wednesday changeover. */
.cell.block-start,
.dayhead.block-start,
.band + .band { margin-left: 3px; }

.cell.is-past { opacity: 0.4; }
.cell.is-today { box-shadow: 0 0 0 1.5px var(--color-accent); }

[data-status='on'] {
  background: var(--color-neutral-300);
  color: #161826;
}

[data-status='off'] {
  background: color-mix(in srgb, var(--color-text) 4%, transparent);
  color: color-mix(in srgb, var(--color-text) 58%, transparent);
}

/* Vacation and personal days carry different codes but deliberately identical
   treatment — the same hatch, outline and weight, so both read as equally
   unavailable. Only the three-letter code tells them apart. */
[data-status='vac'],
[data-status='pers'] {
  background: repeating-linear-gradient(135deg,
    var(--st-protect-mid) 0 2px, var(--st-protect-deep) 2px 6px);
  color: var(--st-protect-text);
  font-weight: 700;
  box-shadow: inset 0 0 0 1.5px var(--st-protect-line);
  text-shadow: 0 0 4px #161826, 0 0 2px #161826;
}

/* Training and travel are one commitment — you travel to training — so they
   share the amber family. Travel is the fainter of the two: dotted rather than
   dashed, barely any fill. A training trip then reads as a solid centre with
   lighter days at each end, which is what it actually is. */
/* Training and travel carry different codes but deliberately identical
   treatment, the same way vacation and personal do. Travel to training is the
   same commitment as the training itself — the day is spoken for either way —
   so only the three-letter code tells them apart.

   Drawn as an outline rather than a border: a border is part of the box and
   steals width from the text inside, which on a phone is the difference between
   TRV fitting in a Wednesday column and not. Outlines cost no layout at all. */
[data-status='trn'],
[data-status='trv'] {
  background: color-mix(in srgb, var(--st-train-line) 14%, transparent);
  color: var(--st-train-text);
  outline: 1px dashed var(--st-train-line);
  outline-offset: -1px;
}

[data-status='unknown'] {
  background: transparent;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--color-text) 7%, transparent);
}

.cell.is-today[data-status='vac'],
.cell.is-today[data-status='pers'] {
  box-shadow: inset 0 0 0 1.5px var(--st-protect-line), 0 0 0 1.5px var(--color-accent);
}

/* ── aircraft row ─────────────────────────────────────── */

.ac-slot {
  grid-row: 1;
  height: var(--cell-h);
  border-radius: 2px;
  background: color-mix(in srgb, var(--color-text) 3%, transparent);
}

.ac-seg {
  grid-row: 1;
  height: var(--cell-h);
  display: flex;
  align-items: center;
  padding-left: 6px;
  border-radius: 2px;
  font-family: var(--font-heading);
  font-size: 11px;
  letter-spacing: 0.06em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ac-seg.trip {
  background: color-mix(in srgb, var(--color-accent) 14%, transparent);
  box-shadow: inset 0 0 0 1px var(--color-accent-500);
  color: var(--color-accent-200);
}

.ac-seg.mnt {
  background: repeating-linear-gradient(90deg,
    color-mix(in srgb, var(--color-text) 10%, transparent) 0 4px, transparent 4px 8px);
  box-shadow: inset 0 0 0 1px var(--color-neutral-700);
  color: var(--color-neutral-300);
}

.ac-seg.clip-l { border-top-left-radius: 0; border-bottom-left-radius: 0; }
.ac-seg.clip-r { border-top-right-radius: 0; border-bottom-right-radius: 0; }

.today-line {
  position: absolute;
  top: 18px;
  bottom: 0;
  width: 1px;
  background: color-mix(in srgb, var(--color-accent) 55%, transparent);
  box-shadow: 0 0 8px 1px color-mix(in srgb, var(--color-accent) 35%, transparent);
  pointer-events: none;
}

/* ── notices ──────────────────────────────────────────── */

.notice {
  margin: 14px 0 0;
  padding: 9px 12px;
  border-left: 2px solid var(--color-accent-600);
  background: color-mix(in srgb, var(--color-accent) 7%, transparent);
  font-size: 11.5px;
  line-height: 1.5;
  color: color-mix(in srgb, var(--color-text) 72%, transparent);
  text-wrap: pretty;
}

/* ── subscribe page ───────────────────────────────────── */

.lede {
  font-size: 13.5px;
  line-height: 1.6;
  max-width: 620px;
  color: color-mix(in srgb, var(--color-text) 78%, transparent);
  text-wrap: pretty;
}

.sect {
  font-family: var(--font-heading);
  font-weight: 500;
  font-size: 15px;
  letter-spacing: 0.02em;
  margin: 26px 0 4px;
}

.sect-note {
  font-size: 12px;
  line-height: 1.55;
  max-width: 620px;
  margin: 0 0 12px;
  color: color-mix(in srgb, var(--color-text) 52%, transparent);
  text-wrap: pretty;
}

.sect-note a { color: var(--color-accent-300); }

.feed-list { display: flex; flex-direction: column; }

.feed-row {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  padding: 9px 0;
  border-bottom: 1px solid color-mix(in srgb, var(--color-text) 8%, transparent);
}

.feed-who {
  display: flex;
  flex-direction: column;
  gap: 1px;
  flex: 0 0 auto;
  min-width: 170px;
}

.feed-who b { font-family: var(--font-heading); font-weight: 500; font-size: 13.5px; }
.feed-who span { font-size: 9px; letter-spacing: 0.12em; opacity: 0.45; }

.feed-url {
  flex: 1 1 300px;
  min-width: 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 11.5px;
  padding: 5px 8px;
  border-radius: 3px;
  background: color-mix(in srgb, var(--color-text) 5%, transparent);
  color: color-mix(in srgb, var(--color-text) 78%, transparent);
  overflow-x: auto;
  white-space: nowrap;
}

.feed-url.plain {
  font-family: var(--font-body);
  background: transparent;
  white-space: normal;
  color: color-mix(in srgb, var(--color-text) 50%, transparent);
}

.how-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 14px;
  margin-top: 4px;
}

.how {
  padding: 11px 13px;
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-md, 8px);
}

.how-title {
  font-family: var(--font-heading);
  font-weight: 500;
  font-size: 12.5px;
  margin-bottom: 5px;
}

.how-body {
  font-size: 11.5px;
  line-height: 1.55;
  color: color-mix(in srgb, var(--color-text) 62%, transparent);
  text-wrap: pretty;
}

/* ── legend ───────────────────────────────────────────── */

.legend {
  margin-top: 22px;
  padding-top: 12px;
  border-top: 1px solid var(--color-divider);
}

.legend-items {
  display: flex;
  gap: 20px;
  flex-wrap: wrap;
  align-items: flex-start;
}

.legend-item {
  display: flex;
  gap: 8px;
  align-items: center;
}

.legend-swatch {
  width: 38px;
  height: 20px;
  flex: none;
  border-radius: 2px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.03em;
}

.legend-label { font-size: 12px; font-family: var(--font-heading); font-weight: 500; }

.status-dot {
  width: 44px;
  height: 20px;
  border-radius: 2px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 9px;
  letter-spacing: 0.03em;
  font-weight: 600;
}

/* ── narrow screens ───────────────────────────────────── */

@media (max-width: 760px) {
  :root {
    --name-col: 46px;
    --cell-h: 30px;
    --cell-font: 7.5px;
  }
  .page { padding: 12px 10px 32px; }
  /* Three buttons need a second row here, and that row costs the calendar its
     place above the fold by a handful of pixels. Tightened rather than
     dropping a button. */
  .masthead { padding-bottom: 2px; gap: 10px; }
  .masthead img { width: 104px; }
  /* Sized per day rather than per board, so a 28-day February and a 31-day
     March both give a column the same width. 26px puts about twelve days in
     view before you scroll, and a one-day trip bar is only as
     wide as its single column. Squeezing the whole month onto the screen made
     every cell too narrow to say anything; zoom in from here to read a one-day
     trip bar. */
  .board { --day-w: 26px; }
  .cell { letter-spacing: 0; }
  /* No room to sit beside the tail number, so they wrap to their own line.
     Pinned right they would look stranded mid-row; sharing the full width
     reads as a pair of buttons. */
  .masthead-actions { margin-left: 0; width: 100%; }
  .masthead-action { flex: 1 1 auto; text-align: center; }

  /* Today's date collapses from a four-line card into a single line above the
     crew list. The date is one short fact; on a phone the tall version was
     costing about 100px of the calendar for it. Only the direction and the
     sizes change here — the reading order is set once, above. */
  .today-strip { gap: 0; }
  .today-card {
    flex-direction: row;
    align-items: baseline;
    gap: 7px;
    width: 100%;
    min-width: 0;
    padding: 0 0 8px;
    border-right: 0;
    border-bottom: 1px solid var(--color-divider);
  }
  .today-card .eyebrow { margin-right: 1px; }
  .today-dow { font-size: 12px; }
  .today-day { font-size: 15px; margin-top: 0; line-height: 1; }
  .today-year { margin-top: 0; }
  .rowname { padding-right: 5px; }
  .rowname b { font-size: 11px; }
  .rowname span { display: none; }
  /* Tracking costs a character's worth of width across a trip number, which on
     a one-day bar is the difference between reading it and not. */
  .ac-seg { padding-left: 3px; font-size: 10px; letter-spacing: 0.01em; }
  /* "Protected · vacation through AUG 4" is too long to hold on one line on a
     phone, so let it wrap rather than push the row sideways. */
  .crew-status { white-space: normal; text-wrap: balance; }
  .crew-row { gap: 8px; }
}

/* ── print ────────────────────────────────────────────── */

@media print {
  body { background: #fff !important; color: #000 !important; }
  .page { max-width: none; padding: 0; }
  [data-print='hide'] { display: none !important; }
  .board-scroller { overflow: visible !important; }
  .board { min-width: 0 !important; }
  .today-line { display: none !important; }

  .cell {
    color: #000 !important;
    box-shadow: inset 0 0 0 1px #000 !important;
    background: #fff !important;
    opacity: 1 !important;
  }
  [data-status='on'] { background: #000 !important; color: #fff !important; }
  [data-status='vac'],
  [data-status='pers'] {
    background: repeating-linear-gradient(135deg, #000 0 2px, #fff 2px 5px) !important;
    box-shadow: inset 0 0 0 1.5px #000 !important;
    text-shadow: none !important;
  }
  [data-status='trn'],
  [data-status='trv'] {
    background: #fff !important;
    box-shadow: none !important;
    outline: 1px dashed #000 !important;
    outline-offset: -1px;
  }
  [data-status='off'] {
    background: #fff !important;
    box-shadow: inset 0 0 0 1px #ccc !important;
    color: #999 !important;
  }
  .tail, .today-day, .rowname b, .crew-name b, .legend-label,
  .dayhead, .band, .muted, .muted-2, .eyebrow { color: #000 !important; }
  .ac-seg.trip, .ac-seg.mnt {
    background: #fff !important;
    box-shadow: inset 0 0 0 1px #000 !important;
    color: #000 !important;
  }
  .masthead-text, .today-card, .legend, .fade-rule { border-color: #000 !important; }
  .fade-rule { background: #000 !important; }
}
