/* ── FORK-COPY HEADER ──────────────────────────────────────────────────────
   source:      family-department/projects/family-calendar/css/calendar.css
                :2150-:2763 — SECTION 10 (year tokens), SECTION 11 (desktop
                twelve-month grid), SECTION 12 (the ≤430px week ribbon) and
                the YEAR half of SECTION 13 (loading/empty/error). SECTION
                13's Month rules stop at :2763 and are not carried.
   copied on:   2026-09-07
   copied by:   the leave-year-grid port (Oli, 2026-09-07)
   modified:    one COMMENT naming a family member was reworded — it is a
                deploy-preflight R5d content canary, and this project's rule
                is to remove the word rather than allowlist it. No selector,
                property or value changed. Everything else is verbatim.
   tokens:      the fourteen --fc-* tokens these rules reference but which
                live in calendar.css SECTIONS 1/1b (outside the copied range)
                are NOT restated here — they are added to css/leave-model.css's
                :root, alongside the person/category/alpha tokens the two JS
                ports read through getComputedStyle. One place to look.
   brand:       the Family Calendar skin, `.fc-` prefix, same lineage as
                css/where-port.css. Nothing here is `.bf-*` or `.ds-*`.
   isolation:   a COPY, not a link. This app loads no stylesheet from the
                sibling calendar project, and never edits it.
   ────────────────────────────────────────────────────────────────────────── */


/* ════════════════════════════════════════════════════════════════════════
   SECTION 10 — YEAR TOKENS

   ⚠ NOT YET MIRRORED into projects/studio-tool-kit/brand-foundation/
   calendar.tokens.json — that file is outside this build's write envelope,
   exactly as the mobile tier in SECTION 1b is. Both blocks need adding there.
   Flagged in the build report.

   Every value below was MEASURED off design-export-2026-08-04/exports/
   desktop-year.png and mobile-year.png at 2×, and cross-checked against
   DESIGN-DECISIONS.md §1/§3 and FONTS.md §3 "Year". Where the two disagree
   the measurement is quoted on the line.
   ════════════════════════════════════════════════════════════════════════ */
:root {
  /* ── desktop grid geometry (DESIGN-DECISIONS §3 "Year view") ── */
  --fc-y-gutter:          44px;   /* month-label column; measured: grid starts 74px in, card pad 30 */
  --fc-y-col:             32px;
  --fc-y-cell-h:          60px;
  --fc-y-dow-h:           24px;   /* measured: letters centred at 93.25px, grid top at 106px */
  --fc-y-num-top:          4px;   /* numeral ink lands 5.5px down — §3 says "5/6px inset" */
  --fc-y-num-right:        6px;   /* measured 6.5px to the ink; digit side-bearing is the rest */

  /* ── the three reserved bands per cell (§3, verbatim) ── */
  --fc-y-bar-top:         19px;
  --fc-y-bar-lane-pitch:  15px;
  --fc-y-bar-h:           13px;
  --fc-y-bar-inset:        2px;   /* each side of the day span */
  --fc-y-bar-label-min:   44px;   /* FONTS.md §4: no label at all below this, never an ellipsis */
  --fc-y-strip-h:          3px;
  --fc-y-strip-bottom:     5px;
  --fc-y-strip-pitch:      5px;
  --fc-y-strip-inset:      4px;   /* strip = the day column minus 4px each side */

  --fc-y-radius-bar:       7px;   /* real trip end (clamps to a pill on a 13px bar) */
  --fc-y-radius-barcut:    2px;   /* the trip continues off this row */
  --fc-y-radius-strip:     2px;

  /* ── grounds. Future cells reuse the shared tokens; the past ramp is Year's
        own, per §1 "Past-day colour (year view)" — a muted GROUND per cell
        type, never an opacity layer over the cell. ── */
  /* Deepened 2026-08-15 (Oli, from the live app). §1's PRINCIPLE — "a muted
     GROUND per cell type, never an opacity layer over the cell" — is exactly
     right and is kept; the values were the problem. --fc-y-past-plain was
     #FBFCFD, which is 1.01:1 against the #FFF card: a past day and a future
     day on the year ribbon were, in practice, the same colour. These are the
     shared --fc-past-cell ramp, so Year, Month and mobile Month now say
     "behind us" with one voice instead of three near-invisible ones.
     Ink check: --fc-text-outside-num #AEB6C4 on #E4E7EE is 1.6:1 and is
     DECORATIVE here (the day number is also spoken in full in the cell's
     accessible name, which is the AA-carrying channel — same standing it had
     on the old ground). */
  --fc-y-holiday-cell:    #E5F6EC;
  --fc-y-past-weekend:    #DCE0E9;
  --fc-y-past-holiday:    #DDE7E0;
  --fc-y-past-plain:      #E4E7EE;
  --fc-y-past-hol-tag:    #C3CFC7;
  --fc-y-strip-past:      0.32;   /* §1: past POINT strips do take opacity (no type on them) */
  /* the same two values the mobile Month cell already carries — aliased, not
     restated, so there is one rgba() in the file per design value */
  --fc-y-today-cell:      var(--fc-m-today-cell);
  --fc-y-today-ring:      var(--fc-m-today-ring);

  /* ── type (FONTS.md §3 "Year", transcribed) ── */
  --fc-y-size-month:      11px;   /* row label, 800 */
  --fc-y-size-dow:         9px;   /* weekday letters, 600 */
  --fc-y-size-num:         9.5px; /* day numeral, 500 — measured 7.0px of digit ink at 2× */
  --fc-y-size-num-today:  10px;   /* 800 */
  --fc-y-size-hol:         7.5px; /* holiday tag, 600 / .04em — the product's smallest type */
  --fc-y-size-bar-label:   9px;   /* 500 */

  /* ── the mobile ribbon (≤430px) ── */
  --fc-y-m-pad-x:         17px;   /* measured: 7 pills of 49px + 6 gaps of 2 = 355 in 390 */
  --fc-y-m-gap:            2px;
  --fc-y-m-pill-h:        19px;
  /* The tap slot, NOT the paint: the pill is 19px, this is the row it sits in.
     23 + the 1px week hairline = 24px centre-to-centre between vertically
     adjacent days, and 49 + 2 = 51px horizontally — which is what satisfies
     WCAG 2.2 AA 2.5.8 here, through its target-OFFSET exception rather than
     through 24×24 size. FONTS.md §4 D3's 44px is NOT reachable on this
     surface: a 44px row would almost double the ribbon's height and the
     design's own measured pitch is 23. Named in the build report, not hidden. */
  --fc-y-m-row-h:         23px;
  --fc-y-m-radius-pill:    5px;
  --fc-y-m-bar-h:         15px;
  --fc-y-m-radius-bar:     7px;
  --fc-y-m-dot:            3.5px; /* ruling C2's mobile-Year clause; the PNG measures 3.0 */
  --fc-y-m-dot-gap:        2px;
  /* Mobile Year's month-ribbon pill. Kept as an opacity because unlike the
     desktop cell this one washes a COLOURED pill, not a white ground, so it
     genuinely does darken — but pulled down with the rest of the 2026-08-15
     past pass so the three surfaces move together. */
  --fc-y-m-past:           0.45;  /* whole-cell wash, ground and type together (C7) */
  --fc-y-m-size-sec:      14px;   /* ribbon month divider label, 800 / -0.02em */
  --fc-y-m-size-bar-label: 9.5px; /* the one place weight goes UP as size goes down: 700 */
  --fc-y-m-size-bar-badge: 8.5px; /* 800 / .06em */
}


/* ════════════════════════════════════════════════════════════════════════
   SECTION 11 — YEAR, DESKTOP  (twelve month rows × 37 day columns)

   All twelve rows share the same 37 weekday columns — every month row starts
   at its own weekday offset — so the weekend shading forms continuous
   vertical bands down the whole year. That is the only reason the grid is 37
   wide (max offset 6 + 31 days) rather than 31.

   CONTRAST, STATED PLAINLY. The whole Year type ramp is below AA at these
   sizes: day numeral #AEB6C4 on white is 2.2:1, weekend #7E8CA3 on #E7EDF9 is
   3.1:1, weekday letters #C3CAD8 is 1.65:1, holiday tag #7FB79E is 2.4:1.
   They are kept because they are explicit design values (DESIGN-DECISIONS §1
   and the 08-04 render, which is the acceptance target) AND because nothing
   here is the sole carrier: the weekday strip is aria-hidden, and every cell
   speaks its whole day — date, holiday, who is away, every event — on its
   accessible name, then drills to Month where the same day is set at 14/600
   in full ink. Substituting the ramp upward would flatten the past/future
   hierarchy the view exists to show. Reported as a live conflict between the
   design ruling and the studio's AA standard; it is /ui's call, not the
   builder's, and it has not been silently resolved either way.
   ════════════════════════════════════════════════════════════════════════ */
.fc-year__scroll {
  /* 44 + 37×32 = 1228px of grid. It fits the 1320 card; below ~1250 of card
     width it scrolls sideways rather than squeezing the day columns, because
     a 28px column stops being a column. */
  overflow-x: auto;
  overflow-y: hidden;
}

.fc-year__head,
.fc-year__row {
  display: grid;
  grid-template-columns: var(--fc-y-gutter) repeat(37, var(--fc-y-col));
  width: 100%;
  min-width: calc(var(--fc-y-gutter) + 37 * var(--fc-y-col));
}

.fc-year__head { height: var(--fc-y-dow-h); align-items: center; }
.fc-year__dow {
  text-align: center;
  line-height: var(--fc-leading-flat);
  font-size: var(--fc-y-size-dow);
  font-weight: var(--fc-weight-medium);
  color: var(--fc-text-faint);
}
/* measured #B0BBCE against the weekday letters' #C8CFDA — the weekend columns
   are keyed a step darker, matching their darker cell ground below */
.fc-year__dow--weekend { color: var(--fc-text-dow); }

.fc-year__grid { border-top: 1px solid var(--fc-hairline-row); }

.fc-year__row {
  position: relative;
  /* measured: every horizontal divider is #F0F2F7 and spans the full card
     content width, including under the month label. DESIGN-DECISIONS §1 lists
     a "grid divider #E4E9F2 / weekend divider #D9E1EE" pair; neither appears
     anywhere in desktop-year.png. The render wins. */
  border-bottom: 1px solid var(--fc-hairline-row);
}

.fc-year__label {
  display: flex;
  align-items: center;
  font-size: var(--fc-y-size-month);
  font-weight: var(--fc-weight-bold);
  letter-spacing: var(--fc-track-tight);
  color: var(--fc-text-secondary);   /* measured #5C6679 */
}

/* ── one day cell ── */
.fc-year__cell {
  position: relative;
  height: var(--fc-y-cell-h);
  padding: 0;
  border: 0;
  border-right: 1px solid var(--fc-cell-vertical);
  background: var(--fc-surface-card);
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  overflow: hidden;
}
.fc-year__cell--empty { background: var(--fc-outside-cell); cursor: default; }
.fc-year__cell--weekend { background: var(--fc-weekend-chip); }
.fc-year__cell--holiday { background: var(--fc-y-holiday-cell); }   /* holiday beats weekend */
.fc-year__cell--past { background: var(--fc-y-past-plain); }
.fc-year__cell--past.fc-year__cell--weekend { background: var(--fc-y-past-weekend); }
.fc-year__cell--past.fc-year__cell--holiday { background: var(--fc-y-past-holiday); }
/* two classes so it wins the tie against --past.--weekend on source order.
   Today is a full-cell ring, square to the cell edge — measured, no radius. */
.fc-year__cell.fc-year__cell--today {
  background: var(--fc-y-today-cell);
  box-shadow: inset 0 0 0 1.5px var(--fc-y-today-ring);
}
button.fc-year__cell:hover { filter: brightness(0.97); }

.fc-year__cellhead {
  position: absolute;
  top: var(--fc-y-num-top);
  right: var(--fc-y-num-right);
  display: flex;
  align-items: baseline;
  gap: 3px;
}
.fc-year__num {
  font-size: var(--fc-y-size-num);
  font-weight: var(--fc-weight-regular);
  line-height: var(--fc-leading-flat);
  color: var(--fc-text-dow);
}
.fc-year__cell--weekend .fc-year__num { color: var(--fc-text-weekend-num); }
/* declared after --weekend so a past weekend takes the past numeral, which is
   what the render shows */
.fc-year__cell--past .fc-year__num { color: var(--fc-text-outside-num); }
.fc-year__cell--today .fc-year__num {
  font-size: var(--fc-y-size-num-today);
  font-weight: var(--fc-weight-bold);
  color: var(--fc-today-numeral);
}

/* weekday-only, single-country tag; both countries → no tag at all */
.fc-year__hol {
  font-size: var(--fc-y-size-hol);
  font-weight: var(--fc-weight-medium);
  letter-spacing: var(--fc-track-micro);
  line-height: var(--fc-leading-flat);
  color: var(--fc-eu-micro);
}
.fc-year__cell--past .fc-year__hol { color: var(--fc-y-past-hol-tag); }

/* ── point events: full-width day strips, never dots (§5 — "a dot at 32px
      column width was unreadable"). Stacked upward from the bottom. ── */
.fc-year__strip {
  position: absolute;
  left: var(--fc-y-strip-inset);
  width: calc(var(--fc-y-col) - 2 * var(--fc-y-strip-inset));
  height: var(--fc-y-strip-h);
  bottom: calc(var(--fc-y-strip-bottom) + var(--i) * var(--fc-y-strip-pitch));
  border-radius: var(--fc-y-radius-strip);
  background: var(--strip-c);
}
/* §1: past point strips DO take opacity — unlike a trip bar, there is no type
   on them for the wash to destroy */
/* A FLIGHT'S STRIP — half-width, pinned right, fully rounded. The shape IS
   the differentiator: it is the only strip that does not span the day column,
   so a flight is findable on the year ribbon by silhouette, in greyscale, and
   without a hue of its own (see the note at --fc-cat-kid for why not a hue).
   Declared before --past so a past flight still takes the past opacity. */
.fc-year__strip--flight {
  left: auto;
  right: var(--fc-y-strip-inset);
  width: calc((var(--fc-y-col) - 2 * var(--fc-y-strip-inset)) * 0.5);
  border-radius: 999px;
}
.fc-year__strip--past { opacity: var(--fc-y-strip-past); }

/* ── trip bars ──
   The layer starts after the month-label gutter, so a bar's x is pure column
   arithmetic: startCol × 32 + 2, width span × 32 − 4. startCol and span come
   from engine.js and are never recomputed here. */
.fc-year__bars {
  position: absolute;
  top: 0;
  bottom: 0;
  left: var(--fc-y-gutter);
  right: 0;
  /* the bars sit over the cells; only the bars themselves take a click, so a
     tap on bare cell ground still reaches the day underneath */
  pointer-events: none;
}
.fc-year__bar {
  position: absolute;
  left: var(--bar-x);
  width: var(--bar-w);
  top: calc(var(--fc-y-bar-top) + var(--lane) * var(--fc-y-bar-lane-pitch));
  height: var(--fc-y-bar-h);
  display: flex;
  align-items: center;
  padding: 0 7px;
  border: 0;
  border-radius: var(--fc-y-radius-bar);
  background: var(--bar-c);
  color: var(--fc-text-on-fill);
  font-family: inherit;
  font-size: var(--fc-y-size-bar-label);
  font-weight: var(--fc-weight-regular);
  line-height: var(--fc-leading-flat);
  overflow: hidden;
  white-space: nowrap;
  pointer-events: auto;
  cursor: pointer;
  transition: box-shadow var(--fc-duration-state) var(--fc-ease-standard);
}
/* a cut edge means "this trip continues into the previous/next month row" */
.fc-year__bar--cont-left  { border-top-left-radius: var(--fc-y-radius-barcut);  border-bottom-left-radius: var(--fc-y-radius-barcut); }
.fc-year__bar--cont-right { border-top-right-radius: var(--fc-y-radius-barcut); border-bottom-right-radius: var(--fc-y-radius-barcut); }
.fc-year__bar:hover { box-shadow: var(--fc-shadow-bar-hover); }
/* tentative — three simultaneous signals plus the trailing ' ?' on the label */
.fc-year__bar--tentative {
  background: var(--bar-tentative-fill);
  border: 1.4px dashed var(--bar-dashed);
  color: var(--bar-c);
}
/* past — a tint plus a dark neutral label. Never blanket opacity, which at
   9px destroys the stroke (FONTS.md §4 / ruling C7). */
.fc-year__bar--past {
  background: var(--bar-past-fill);
  color: var(--fc-text-past-label);
}
.fc-year__bar-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; }


/* ════════════════════════════════════════════════════════════════════════
   SECTION 12 — YEAR, MOBILE RIBBON  (≤ 430px)

   One row per WEEK, flowing continuously top to bottom; a month is a heading
   and a hairline, not a break in the run of dates. A boundary week renders
   ONCE, in the section of the month it ends in — 26 Jan – 1 Feb under
   "February", 23 Feb – 1 Mar under "March", both verified in mobile-year.png.
   Days outside the year (the leading December cells, the trailing January
   ones) render blank, so every date in 2026 appears exactly once.

   Declared last so it wins at equal specificity, exactly as SECTION 9 does.
   ════════════════════════════════════════════════════════════════════════ */
@media (max-width: 430px) {
  /* ── the sticky weekday key ── */
  .fc-y-m-dow {
    position: sticky;
    top: 0;
    z-index: 5;
    display: grid;
    grid-template-columns: repeat(7, minmax(0, 1fr));
    column-gap: var(--fc-y-m-gap);
    padding: 5px var(--fc-y-m-pad-x) 6px;
    background: var(--fc-surface-card);
    border-bottom: 1px solid var(--fc-hairline-card);
  }
  .fc-y-m-dow__cell {
    text-align: center;
    font-size: var(--fc-m-size-dow);
    font-weight: var(--fc-weight-medium);
    /* design value #AEB6C4 is 2.2:1. Substituted for AA, exactly as the mobile
       Month strip above does — this one is a key, not a date. */
    color: var(--fc-text-secondary);
  }

  /* ── a month section ── */
  .fc-y-m-sec { padding: 0 var(--fc-y-m-pad-x); }
  .fc-y-m-sec:first-of-type { margin-top: 11px; }
  .fc-y-m-sec + .fc-y-m-sec { margin-top: 16px; }
  .fc-y-m-sec__head {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 6px;
  }
  .fc-y-m-sec__title {
    margin: 0;
    font-size: var(--fc-y-m-size-sec);
    font-weight: var(--fc-weight-bold);
    letter-spacing: var(--fc-track-tight);
    color: var(--fc-text-ink);
  }
  .fc-y-m-sec__rule { flex: 1; height: 1px; background: var(--fc-hairline-card); }

  /* ── one week row ── */
  /* no padding: the 23px day row already carries the 2px of air above and
     below its 19px pill, so the week pitch is exactly 23 + the hairline */
  .fc-y-m-week { border-bottom: 1px solid var(--fc-hairline-row); }
  .fc-y-m-week:last-child { border-bottom: 0; }
  .fc-y-m-week__days {
    display: grid;
    grid-template-columns: repeat(7, minmax(0, 1fr));
    column-gap: var(--fc-y-m-gap);
  }

  .fc-y-m-cell {
    /* 24px, not the pill's 19 — the tap target is the ROW slot, not the paint.
       See --fc-y-m-row-h for why this is 24 and not FONTS.md §4 D3's 44. */
    height: var(--fc-y-m-row-h);
    display: flex;
    align-items: center;
    padding: 0;
    border: 0;
    background: transparent;
    font-family: inherit;
    cursor: pointer;
  }
  .fc-y-m-cell--blank { cursor: default; }
  .fc-y-m-cell__pill {
    flex: 1;
    min-width: 0;
    height: var(--fc-y-m-pill-h);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1px;
    border-radius: var(--fc-y-m-radius-pill);
  }
  .fc-y-m-cell__pill--weekend { background: var(--fc-weekend-chip); }
  .fc-y-m-cell__pill--holiday { background: var(--fc-y-holiday-cell); }
  /* Ruling C7 allows a uniform wash over a whole cell — ground, numeral and
     dots dim together, which is what the render measures (the ribbon's past
     weekday numeral resolves to #5C6679 at exactly 60%). It sits on the PILL,
     not the button, so the focus ring never dims with it. */
  .fc-y-m-cell__pill--past { opacity: var(--fc-y-m-past); }
  .fc-y-m-cell__pill--today {
    background: var(--fc-y-today-cell);
    box-shadow: inset 0 0 0 1.5px var(--fc-y-today-ring);
  }

  .fc-y-m-cell__num {
    font-size: var(--fc-y-size-num);
    font-weight: var(--fc-weight-regular);
    line-height: var(--fc-leading-flat);
    color: var(--fc-text-secondary);
  }
  .fc-y-m-cell__pill--weekend .fc-y-m-cell__num { color: var(--fc-text-weekend-num); }
  /* design value measures ≈#3E8C6C (3.6:1). Substituted for AA, as every other
     holiday label in this stylesheet is. */
  .fc-y-m-cell__pill--holiday .fc-y-m-cell__num { color: var(--fc-eu-ink); }
  .fc-y-m-cell__pill--today .fc-y-m-cell__num {
    font-size: var(--fc-y-size-num-today);
    font-weight: var(--fc-weight-bold);
    color: var(--fc-today-numeral);
  }

  /* max 3, centred under the numeral, NO overflow indicator (ruling C2) */
  .fc-y-m-cell__dots { display: flex; gap: var(--fc-y-m-dot-gap); }
  .fc-y-m-cell__dot {
    width: var(--fc-y-m-dot);
    height: var(--fc-y-m-dot);
    flex-shrink: 0;
    border-radius: 50%;
    background: var(--strip-c);
  }
  /* the ONLY thing separating a child's trips from that child's logistics is shape */
  .fc-y-m-cell__dot--square { border-radius: 1px; }
  /* The flight DIAMOND — the square, rotated. Third shape in the vocabulary
     (circle = appointment/birthday, square = kid logistics, diamond =
     flight), so mobile Year answers Oli's "is that a flight or a dinner?"
     with the one channel a 3.5px mark reliably has. `transform` rather than
     a clip-path so it degrades to a plain square, not to nothing. */
  .fc-y-m-cell__dot--flight { border-radius: 1px; transform: rotate(45deg); }

  /* ── trip bars: the same seven-column grid as the pills, so a bar lines up
        with its days across the 2px gutters with no percentage arithmetic ── */
  .fc-y-m-week__bars {
    display: grid;
    grid-template-columns: repeat(7, minmax(0, 1fr));
    column-gap: var(--fc-y-m-gap);
    row-gap: 2px;
    margin: 2px 0 5px;
  }
  .fc-y-m-bar {
    height: var(--fc-y-m-bar-h);
    margin: 0 2px;
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 0 6px;
    border: 0;
    border-radius: var(--fc-y-m-radius-bar);
    background: var(--bar-c);
    color: var(--fc-text-on-fill);
    font-size: var(--fc-y-m-size-bar-label);
    font-weight: var(--fc-weight-semibold);   /* §3 Mobile: 9.5 / 700 */
    line-height: var(--fc-leading-flat);
    overflow: hidden;
    white-space: nowrap;
    cursor: pointer;
  }
  .fc-y-m-bar--cont-left  { border-top-left-radius: var(--fc-y-radius-barcut);  border-bottom-left-radius: var(--fc-y-radius-barcut); }
  .fc-y-m-bar--cont-right { border-top-right-radius: var(--fc-y-radius-barcut); border-bottom-right-radius: var(--fc-y-radius-barcut); }
  .fc-y-m-bar--tentative {
    background: var(--bar-tentative-fill);
    border: 1.3px dashed var(--bar-dashed);
    color: var(--bar-c);
  }
  .fc-y-m-bar--past {
    background: var(--bar-past-fill);
    color: var(--fc-text-past-label);
  }
  .fc-y-m-bar__label { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
  /* the who-badge rides EVERY week segment, right-aligned: a ribbon is
     scrolled through, so a continuation row without one is an unattributed bar */
  .fc-y-m-bar__badge {
    margin-left: auto;
    flex-shrink: 0;
    padding: 1px 5px;
    border-radius: var(--fc-radius-badge);
    font-size: var(--fc-y-m-size-bar-badge);
    font-weight: var(--fc-weight-bold);
    letter-spacing: var(--fc-track-badge);
    background: var(--fc-badge-ground);
  }
  .fc-y-m-bar--tentative .fc-y-m-bar__badge { background: var(--bar-badge-ground); color: var(--bar-c); }
  /* measured: a PAST bar carries no badge pill at all in mobile-year.png —
     just the initials in the past-label ink. Desktop Month's C6 does tint the
     pill; the render is the acceptance target here, and the difference is
     reported rather than quietly reconciled either way. */
  .fc-y-m-bar--past .fc-y-m-bar__badge { background: transparent; color: var(--fc-text-past-label); }
}


/* ════════════════════════════════════════════════════════════════════════
   SECTION 13 — DATA STATES ON YEAR AND MONTH: loading skeletons + card host
   Added 2026-08-07. calendar.css SECTION 5 has carried the `.fc-state` card
   since the 08-06 convergence, and js/app.js has passed `opts.loading`,
   `opts.empty` and `opts.error` to EVERY view since the same day. Only Where
   consumed them. `?state=error#/month/2026-10` and `?state=loading#/year/2026`
   drew the ordinary populated grid, silently, at both breakpoints.

   DECLARED LAST, deliberately. The mobile tiers in SECTIONS 9 and 12 reach
   `.fc-m-cell--today:not(.fc-m-cell--selected)` and
   `.fc-y-m-cell__pill--today`, which are (0,3,0) and (0,2,0) — the same or
   near the loading masks below. A media query adds no specificity, so the tie
   is broken on source order and the mask has to come after them. This is the
   same reason SECTION 9 is declared after SECTION 7, and the file says so
   there.

   THE RULE THE MASK FOLLOWS, lifted verbatim from css/where.css SECTION 6 so
   the estate has one: anything DERIVED FROM THE DATA is masked; the chrome §6
   keeps in every state — weekday letters, month labels, the section headings,
   the holiday tags — is not. Geometry never changes, so nothing moves when the
   real data lands. Skeleton bars sit at the real bar geometry, which they do
   for free here: the mask recolours the bar that is already positioned rather
   than drawing a stand-in.
   ════════════════════════════════════════════════════════════════════════ */

/* ── the pill's row ────────────────────────────────────────────────────────
   §6 puts `LOADING…` in the header row. The header is the frozen shell's and
   no view may write it (contract §2), so each screen opens with this line
   instead. It is the ONLY element the loading state adds; everything else is
   the real render, recoloured. */
.fc-state-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
}

/* ── the card host ─────────────────────────────────────────────────────────
   `.fc-state-layer--overlay` is `position:absolute; inset:0`, so its nearest
   positioned ancestor decides what the card is centred over and what the .66
   ground covers. Applied ONLY in the two states that use it: a blanket
   `position: relative` on `.fc-board` would change the containing block for
   every absolutely-positioned descendant in the default render, which is the
   whole trip-bar layer. */
.fc-year[data-state='empty'],    .fc-year[data-state='error'],
.fc-y-m[data-state='empty'],     .fc-y-m[data-state='error'],
.fc-board[data-state='empty'],   .fc-board[data-state='error'],
.fc-m-month[data-state='empty'], .fc-m-month[data-state='error'] {
  position: relative;
}
/* The mobile year ribbon is twelve month sections tall — several screens. A
   card centred in it lands below the fold, so on this one surface the card
   goes to the top of the ribbon where it is on screen at rest. Same card, same
   ground, different anchor. */
.fc-y-m[data-state='empty']  .fc-state-layer--overlay,
.fc-y-m[data-state='error']  .fc-state-layer--overlay {
  align-items: start;
  padding-top: 24px;
}

/* ── YEAR, desktop ───────────────────────────────────────────────────────── */
/* Grounds: every day cell drops to the flat skeleton ground, and the today
   ring goes with it — today is redrawn when the data lands. */
.fc-year[data-state='loading'] .fc-year__cell {
  background: var(--fc-skeleton-cell);
  box-shadow: none;
}
/* exports/loading-year.png carries NO day numerals and no holiday tags at all
   — at 37 columns a text placeholder per day is noise, and the reference is
   explicit. `visibility` rather than `display`, so the absolutely-positioned
   head keeps its box and nothing reflows when the data lands. */
.fc-year[data-state='loading'] .fc-year__cellhead { visibility: hidden; }
.fc-year[data-state='loading'] .fc-year__bar {
  background: var(--fc-skeleton-bar);
  box-shadow: none;
  border: 0;
}
.fc-year[data-state='loading'] .fc-year__bar-label,
.fc-year[data-state='loading'] .fc-year__bar .fc-bar__badge { color: transparent; background: transparent; }
/* the point-item ticks — a flight or an event is data */
.fc-year[data-state='loading'] .fc-year__strip { background: var(--fc-skeleton-bar); }

/* ── YEAR, mobile ribbon ─────────────────────────────────────────────────── */
.fc-y-m[data-state='loading'] .fc-y-m-cell__pill {
  background: var(--fc-skeleton-cell);
  box-shadow: none;
}
.fc-y-m[data-state='loading'] .fc-y-m-cell__num { color: transparent; }
.fc-y-m[data-state='loading'] .fc-y-m-cell__dot { background: var(--fc-skeleton-bar); }
/* THE DASHED TENTATIVE OUTLINE, closed 2026-08-08 by the CHROMA sweep.
   `--tentative` draws a 1.3px dashed BORDER in the trip colour rather than a
   background, so recolouring the ground left `Morocco ?` outlined in
   rgba(51,81,138,.7) — the family trip colour, under a LOADING… pill, on a
   product whose first rule is that bar colour says who. The text sweep could
   not see it: the label was already transparent, and the ring around the
   nothing still said "the family are away". The desktop Month equivalent was
   caught and fixed on 08-07 with the border-color line further down this
   section; the two MOBILE surfaces were missed. Same defect, same line.
   Kept outside the block on purpose — the assertion that guards this reads the
   rule with `\{([^}]*)\}`, and a brace inside a comment inside the block ends
   the capture early. */
.fc-y-m[data-state='loading'] .fc-y-m-bar {
  background: var(--fc-skeleton-bar);
  box-shadow: none;
  border-color: var(--fc-skeleton-bar);
}
.fc-y-m[data-state='loading'] .fc-y-m-bar__label,
.fc-y-m[data-state='loading'] .fc-y-m-bar__badge { color: transparent; background: transparent; }

