{
  "version": 3,
  "sources": ["calendar_core.js"],
  "sourcesContent": ["/*\n * static/js/calendar_core.js \u2014 Pure, context-free month-grid maths for the\n * map's date picker (SNOW-792).\n *\n * The season scrubber is a ~300px track spanning a seven-month season, so a\n * pixel is about a day and landing on a chosen date is a fiddle. The\n * calendar popup is the precise route to the same commit point; this module\n * is the half of it that has no DOM in it, so the grid maths can be\n * unit-tested directly (tests/js/test_calendar_core.js) rather than through\n * a browser.\n *\n * Attached to ``window`` (not ``self``) \u2014 every consumer is a page script,\n * as with scrubber_core.js; there is no service-worker context to share\n * with.\n *\n * Deliberately dependency-free: every export is a pure function of its\n * arguments. The range bounds, the season bounds, the ratings cache and the\n * selected date are all passed in explicitly rather than read from\n * module-scope globals.\n *\n * Dates are handled as ``YYYY-MM-DD`` strings and UTC-midnight timestamps\n * throughout, matching scrubber_core.js. Constructing local-time Dates from\n * a date-only string is what makes a picker show the wrong day either side\n * of a DST boundary, and the whole season window straddles one.\n *\n * ## The reachable range is not the season\n *\n * The picker's bounds and the avalanche season are two different things,\n * and conflating them was this module's first mistake. The map carries\n * weather as well as bulletins, and weather has an answer for a day in\n * September; a picker that stopped at the end of May could not reach it.\n *\n * So the reachable range runs from the earliest day the site holds anything\n * for to the latest \u2014 both read off the ratings cache\n * (``earliestKnownDate`` / ``latestKnownDate``). The hard stop is what the\n * data covers, not the clock: SNOW-927 made the ceiling follow the payload\n * the way the floor always had, because the evening bulletin forecasts\n * TOMORROW and a picker fenced at today could not open the day it had\n * already been sent. Off season the ceiling stays at today, which is the\n * later of the two. The season is a HIGHLIGHT inside that range\n * (``inSeason`` on each cell), not a fence around it: it tells you where the\n * bulletins are without refusing the days either side.\n *\n * There is no second, per-day mark for \"this day actually has a bulletin\".\n * There was one \u2014 a dot, driven by the ratings cache \u2014 and it went because\n * the thing it distinguished, a gap in the archive inside the season, is an\n * operator's concern and not a visitor's. A visitor who lands on such a day\n * sees an uncoloured map, which is the same answer told once instead of\n * twice.\n *\n * Public API \u2014 attached to ``window.pwaCalendarCore``:\n *\n *   monthKeyOf(dateKey)\n *     ``'2026-02-16'`` \u2192 ``'2026-02'``. Empty string for anything\n *     unparseable, so a caller can test it without a second guard.\n *   shiftMonth(monthKey, delta)\n *     ``('2026-02', -1)`` \u2192 ``'2026-01'``. Wraps the year in both\n *     directions.\n *   clampMonthKey(monthKey, minKey, maxKey)\n *     The month, pulled inside the reachable range if it falls outside it.\n *     This is what stops prev/next walking off into 1970 or next year.\n *   buildMonthGrid(monthKey, opts)\n *     The cells for one month, Monday-first, as a flat array of 7\u00D7N\n *     entries. See the function docstring for the cell shape.\n *   earliestKnownDate(ratingsCache, fallbackKey)\n *     The earliest date the ratings cache carries, or ``fallbackKey`` when\n *     it carries nothing usable \u2014 the floor the month arrows stop at.\n *   latestKnownDate(ratingsCache, fallbackKey)\n *     SNOW-927: the ceiling, mirroring the floor above. The latest date the\n *     cache carries, or ``fallbackKey`` (today) when that is later \u2014 which\n *     off season it is, and must be. Capped at ``MAX_FORWARD_DAYS`` past\n *     the fallback.\n *   MAX_FORWARD_DAYS\n *     The cap above, exported so the scrubber's boot path can assume the\n *     same ceiling before the ratings payload has resolved.\n *   swipeStep(dx, dy)\n *     SNOW-1160: the month step a finger's travel asks for \u2014 ``1`` for a\n *     swipe left (next month), ``-1`` for a swipe right (previous), ``0``\n *     for a tap, a short nudge or a mostly-vertical drag.\n *   SWIPE_MIN_PX\n *     The horizontal travel below which ``swipeStep`` answers ``0``.\n */\n\n// @ts-check\n\n(function () {\n  'use strict';\n\n  var MS_PER_DAY = 86400000;\n\n  // SNOW-927: how far past today ``latestKnownDate`` may ever reach. See its\n  // docstring \u2014 a bad-data guard, not a product rule. Providers publish one\n  // day ahead, so three is clear of the real window and nowhere near a\n  // plausible typo. Exported because the scrubber's boot path has to make the\n  // same optimistic assumption before the payload has resolved, and the two\n  // must not drift.\n  var MAX_FORWARD_DAYS = 3;\n\n  // SNOW-1160: how far a finger has to travel sideways before the card reads\n  // it as a swipe rather than a tap that wobbled. 40px is roughly a day\n  // cell's width plus its gap \u2014 far enough that lifting off a cell is never\n  // a swipe, short enough that a flick across a 210px grid always is.\n  var SWIPE_MIN_PX = 40;\n\n  var DATE_KEY_RE = /^\\d{4}-\\d{2}-\\d{2}$/;\n  var MONTH_KEY_RE = /^\\d{4}-\\d{2}$/;\n\n  /**\n   * Format a UTC timestamp as a ``YYYY-MM-DD`` date key.\n   *\n   * @param {number} ms Epoch milliseconds.\n   * @returns {string}\n   */\n  function keyFromMs(ms) {\n    var d = new Date(ms);\n    var y = d.getUTCFullYear();\n    var m = String(d.getUTCMonth() + 1).padStart(2, '0');\n    var day = String(d.getUTCDate()).padStart(2, '0');\n    return y + '-' + m + '-' + day;\n  }\n\n  /**\n   * The month a date key belongs to.\n   *\n   * Works on the string rather than parsing to a Date: the input is\n   * already the canonical form, and a substring cannot drift a day the way\n   * a timezone-sensitive parse can.\n   *\n   * @param {string} dateKey A ``YYYY-MM-DD`` date key.\n   * @returns {string} A ``YYYY-MM`` month key, or ``''`` if unparseable.\n   */\n  function monthKeyOf(dateKey) {\n    if (typeof dateKey !== 'string' || !DATE_KEY_RE.test(dateKey)) return '';\n    return dateKey.slice(0, 7);\n  }\n\n  /**\n   * Step a month key forwards or backwards, wrapping the year.\n   *\n   * @param {string} monthKey A ``YYYY-MM`` month key.\n   * @param {number} delta Months to move; negative goes back.\n   * @returns {string} The shifted month key, or ``''`` if unparseable.\n   */\n  function shiftMonth(monthKey, delta) {\n    if (typeof monthKey !== 'string' || !MONTH_KEY_RE.test(monthKey)) return '';\n    var year = parseInt(monthKey.slice(0, 4), 10);\n    var month = parseInt(monthKey.slice(5, 7), 10) - 1 + (delta || 0);\n    // Floor-divide so a negative month index carries into the year\n    // correctly \u2014 ``-1`` is December of the previous year, not month -1.\n    year += Math.floor(month / 12);\n    month = ((month % 12) + 12) % 12;\n    return year + '-' + String(month + 1).padStart(2, '0');\n  }\n\n  /**\n   * Pull a month key inside the reachable range.\n   *\n   * The range is a date range, so its first and last months are partial;\n   * clamping is by month, and ``buildMonthGrid`` is what disables the days\n   * either side of the exact bounds \u2014 in practice only the tail of the\n   * month the ceiling falls in.\n   *\n   * @param {string} monthKey A ``YYYY-MM`` month key.\n   * @param {string} minKey Earliest reachable day as a ``YYYY-MM-DD`` key.\n   * @param {string} maxKey Latest reachable day as a key \u2014 today, or the\n   *   last day the payload covers when that is later (SNOW-927).\n   * @returns {string} The clamped month key, or ``''`` if unparseable.\n   */\n  function clampMonthKey(monthKey, minKey, maxKey) {\n    if (typeof monthKey !== 'string' || !MONTH_KEY_RE.test(monthKey)) return '';\n    var first = monthKeyOf(minKey);\n    var last = monthKeyOf(maxKey);\n    if (first && monthKey < first) return first;\n    if (last && monthKey > last) return last;\n    return monthKey;\n  }\n\n  /**\n   * The earliest date the ratings cache knows about.\n   *\n   * This is the floor the month arrows stop at. It comes from the cache\n   * rather than from the server because the alternative \u2014 asking the DB\n   * for its earliest row \u2014 is a query on the home page's critical path,\n   * and the home page has a query-count budget (docs/query-counts.md).\n   * The cache is already fetched for the scrubber, so this costs nothing.\n   *\n   * It is a floor on PAGING, not on selection: every day from here to\n   * today is pickable, including the ones with no ratings, because the\n   * map has weather to show for them.\n   *\n   * @param {Object|null} ratingsCache Date key \u2192 per-region ratings frame.\n   * @param {string} fallbackKey Returned when the cache has no usable key.\n   * @returns {string} A ``YYYY-MM-DD`` date key.\n   */\n  function earliestKnownDate(ratingsCache, fallbackKey) {\n    var earliest = '';\n    if (ratingsCache && typeof ratingsCache === 'object') {\n      for (var key of Object.keys(ratingsCache)) {\n        if (!DATE_KEY_RE.test(key)) continue;\n        if (!earliest || key < earliest) earliest = key;\n      }\n    }\n    if (!earliest) return fallbackKey || '';\n    // The season may start before the first day carrying a rating \u2014 an\n    // early-November window over an archive that begins mid-month. Take\n    // whichever is earlier so the highlight is never cut off by the floor.\n    if (fallbackKey && fallbackKey < earliest) return fallbackKey;\n    return earliest;\n  }\n\n  /**\n   * The latest date the ratings cache knows about.\n   *\n   * SNOW-927: the ceiling, and the mirror of ``earliestKnownDate`` above \u2014\n   * same cache, same reasoning about why it is read here rather than\n   * queried, opposite end.\n   *\n   * It exists because the ceiling used to be ``today``, full stop, while the\n   * floor had always come from the data. Providers publish twice a day and\n   * the evening issue forecasts TOMORROW\n   * (``apps/bulletins/services/day_rating.py``'s\n   * ``target_day_for_valid_from``), so from about 16:00 the cache carries a\n   * day the picker refused to offer \u2014 the one a person packing for the\n   * morning actually wants.\n   *\n   * ``fallbackKey`` is today, and **taking whichever is LATER is load-bearing\n   * rather than tidy**. Off season the archive ends in April while today is\n   * September; returning the cache's last day would put the ceiling below\n   * today and make today itself unselectable, which would break the one rule\n   * SNOW-793 lays down (the map may always default to today). The mirror\n   * image of the ``min`` ``earliestKnownDate`` takes for the season-start\n   * case, and load-bearing for the same kind of reason.\n   *\n   * Like the floor, this bounds the RANGE and says nothing about which day\n   * is chosen: a day inside it with no ratings is still pickable and simply\n   * paints uncoloured, exactly as an off-season today already does.\n   *\n   * The result is capped at ``fallbackKey + MAX_FORWARD_DAYS``. That cap is\n   * a guard on BAD DATA, not a product rule \u2014 one mis-dated provider\n   * timestamp or a bad backfill would otherwise hand the month arrows\n   * whatever year the bad row names. It lives here rather than in either\n   * caller because both surfaces have to agree on the ceiling to the day: a\n   * calendar that offers a date the scrubber then refuses on reload is the\n   * exact defect SNOW-794 was raised to fix, one end of the range along.\n   *\n   * @param {Object|null} ratingsCache Date key \u2192 per-region ratings frame.\n   * @param {string} fallbackKey Today. Returned when the cache has no usable\n   *   key, preferred whenever it is later than the cache's last day, and the\n   *   anchor the forward cap is measured from.\n   * @returns {string} A ``YYYY-MM-DD`` date key.\n   */\n  function latestKnownDate(ratingsCache, fallbackKey) {\n    var latest = '';\n    if (ratingsCache && typeof ratingsCache === 'object') {\n      for (var key of Object.keys(ratingsCache)) {\n        if (!DATE_KEY_RE.test(key)) continue;\n        if (!latest || key > latest) latest = key;\n      }\n    }\n    if (!latest) return fallbackKey || '';\n    if (fallbackKey && fallbackKey > latest) return fallbackKey;\n    var anchorMs = Date.parse(fallbackKey);\n    if (Number.isFinite(anchorMs)) {\n      var capKey = keyFromMs(anchorMs + MAX_FORWARD_DAYS * MS_PER_DAY);\n      if (latest > capKey) return capKey;\n    }\n    return latest;\n  }\n\n  /**\n   * Build one month's grid of day cells, Monday-first.\n   *\n   * The array is ALWAYS 42 cells \u2014 six weeks \u2014 however few the month needs.\n   * Leading and trailing padding cells (``{blank: true}``) make up the\n   * difference, so a caller can lay it out as a seven-column grid without\n   * doing any offset arithmetic of its own.\n   *\n   * Six rather than \"a whole number of weeks\" because the panel is\n   * bottom-anchored: a five-row month is shorter than a six-row one, and\n   * paging between them moved the popup's top edge and everything in it.\n   * A constant height costs one blank row on some months and makes the\n   * arrows a control you can press twice without the target moving.\n   *\n   * Six is always enough: the worst case is a 31-day month starting on a\n   * Sunday \u2014 six leading blanks plus 31 days is 37 cells, still inside 42.\n   *\n   * A day cell is::\n   *\n   *     {\n   *       blank: false,\n   *       dateKey: '2026-02-16',\n   *       day: 16,               // for the visible label\n   *       selectable: true,      // inside [min, max]\n   *       inSeason: true,        // inside the avalanche season: a HIGHLIGHT\n   *       rating: 3,             // EAWS danger int for the focused region,\n   *                              // or null \u2014 SNOW-794\n   *       selected: false,       // the date the map is currently showing\n   *       isToday: false,\n   *     }\n   *\n   * ``inSeason`` is deliberately separate from ``selectable`` rather than\n   * folded into it. A day outside the season is still a day the map has\n   * weather for \u2014 refusing it was the bug this shape exists to prevent.\n   * Unselectable means outside ``[min, max]`` and nothing else; SNOW-927\n   * moved ``max`` off the clock, so \"not the future\" is no longer what it\n   * comes to.\n   *\n   * @param {string} monthKey A ``YYYY-MM`` month key.\n   * @param {Object} opts Grid inputs.\n   * @param {string} [opts.min] Earliest reachable day ``YYYY-MM-DD``.\n   * @param {string} [opts.max] Latest reachable day ``YYYY-MM-DD`` \u2014 today,\n   *   or the last day the payload covers when that is later (SNOW-927).\n   * @param {string} [opts.seasonStart] Season start ``YYYY-MM-DD``.\n   * @param {string} [opts.seasonEnd] Season end ``YYYY-MM-DD``.\n   * @param {string} [opts.selected] The currently-showing date, or ''.\n   * @param {string} [opts.today] Today's date key, for the today marker.\n   * @param {Object<string, number>} [opts.ratings] SNOW-794: date key \u2192\n   *   EAWS danger int for the focused region. Days absent from it get\n   *   ``rating: null``. This is what lets the grid carry the danger colour\n   *   the scrubber ribbon paints into its track \u2014 the one thing the\n   *   scrubber gave a phone that the calendar did not, which is why the\n   *   scrubber can now be dropped entirely below 640px.\n   * @returns {Array<Object>} Cells, length a multiple of 7.\n   */\n  function buildMonthGrid(monthKey, opts) {\n    var options = opts || {};\n    if (typeof monthKey !== 'string' || !MONTH_KEY_RE.test(monthKey)) return [];\n\n    var min = options.min || '';\n    var max = options.max || '';\n    var seasonStart = options.seasonStart || '';\n    var seasonEnd = options.seasonEnd || '';\n    var selected = options.selected || '';\n    var today = options.today || '';\n    var ratings = options.ratings || null;\n\n    var firstMs = Date.parse(monthKey + '-01T00:00:00Z');\n    if (!Number.isFinite(firstMs)) return [];\n    var nextMonthMs = Date.parse(shiftMonth(monthKey, 1) + '-01T00:00:00Z');\n    var dayCount = Math.round((nextMonthMs - firstMs) / MS_PER_DAY);\n\n    // getUTCDay() is Sunday-first (0..6); the grid is Monday-first, so\n    // Sunday becomes 6 and every other day shifts down one.\n    var leading = (new Date(firstMs).getUTCDay() + 6) % 7;\n\n    var cells = [];\n    var i;\n    for (i = 0; i < leading; i++) cells.push({ blank: true });\n\n    for (i = 0; i < dayCount; i++) {\n      var dateKey = keyFromMs(firstMs + i * MS_PER_DAY);\n      cells.push({\n        blank: false,\n        dateKey: dateKey,\n        day: i + 1,\n        selectable: (!min || dateKey >= min) && (!max || dateKey <= max),\n        inSeason:\n          (!seasonStart || dateKey >= seasonStart) && (!seasonEnd || dateKey <= seasonEnd),\n        rating: ratings && ratings[dateKey] != null ? ratings[dateKey] : null,\n        selected: dateKey === selected,\n        isToday: dateKey === today,\n      });\n    }\n\n    // Pad to a constant six weeks \u2014 see the docstring for why the height\n    // must not depend on the month.\n    while (cells.length < 42) cells.push({ blank: true });\n\n    return cells;\n  }\n\n  /**\n   * The month step a touch's travel asks for (SNOW-1160).\n   *\n   * Swipe LEFT moves FORWARD, as a page turns: the next month comes in from\n   * the right. A drag counts only when it is mostly sideways \u2014 horizontal\n   * travel at least twice the vertical \u2014 because the card is a bounded,\n   * scrolling box, and a vertical scroll that drifts a little must not also\n   * page the month.\n   *\n   * @param {number} dx Horizontal travel, end minus start, in px.\n   * @param {number} dy Vertical travel, end minus start, in px.\n   * @returns {number} ``1``, ``-1`` or ``0``.\n   */\n  function swipeStep(dx, dy) {\n    if (!Number.isFinite(dx) || !Number.isFinite(dy)) return 0;\n    if (Math.abs(dx) < SWIPE_MIN_PX) return 0;\n    if (Math.abs(dx) < 2 * Math.abs(dy)) return 0;\n    return dx < 0 ? 1 : -1;\n  }\n\n  window.pwaCalendarCore = Object.freeze({\n    monthKeyOf: monthKeyOf,\n    shiftMonth: shiftMonth,\n    clampMonthKey: clampMonthKey,\n    earliestKnownDate: earliestKnownDate,\n    latestKnownDate: latestKnownDate,\n    MAX_FORWARD_DAYS: MAX_FORWARD_DAYS,\n    buildMonthGrid: buildMonthGrid,\n    swipeStep: swipeStep,\n    SWIPE_MIN_PX: SWIPE_MIN_PX,\n  });\n})();\n"],
  "mappings": "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",
  "names": ["MS_PER_DAY", "MAX_FORWARD_DAYS", "SWIPE_MIN_PX", "DATE_KEY_RE", "MONTH_KEY_RE", "keyFromMs", "ms", "d", "y", "m", "day", "monthKeyOf", "dateKey", "shiftMonth", "monthKey", "delta", "year", "month", "clampMonthKey", "minKey", "maxKey", "first", "last", "earliestKnownDate", "ratingsCache", "fallbackKey", "earliest", "key", "latestKnownDate", "latest", "anchorMs", "capKey", "buildMonthGrid", "opts", "options", "min", "max", "seasonStart", "seasonEnd", "selected", "today", "ratings", "firstMs", "nextMonthMs", "dayCount", "leading", "cells", "i", "swipeStep", "dx", "dy"]
}
