/* availability-grid.css — the weekly day/hour grid, in one place.
 *
 * Two pages render this: muster/take.php builds it in JS for a respondent
 * to click, and muster/admin/results.php renders it server-side as a
 * heat map of what everyone answered. They are read against each other --
 * "is this what they ticked?" -- so any difference in geometry between
 * them is a difference the reader has to hold in their head. They were
 * separate copies under two class names, already agreeing only because
 * both were edited in the same sitting.
 *
 * Interaction states (.selected, .isNow, .nowCol) stay in take.css: only
 * the respondent grid has them.
 */
/* Positioned, because the crosshair overlay is measured against it. A
   container, so the labels can thin out by the width the grid actually has. */
/* Sideways only, and only when a narrow page forces it: seven rows are never scrolled up and down. Saying auto across
   makes the browser say auto down as well, and the hover's lines, laid over the cells by measure, come out a fraction of
   a pixel taller than the box at some zooms: a scrollbar down the side of a week with nothing to scroll to. */
.availGridScroll { overflow-x: auto; overflow-y: hidden; position: relative; container-type: inline-size; }

/* Nothing in an availability control is text to be selected. Dragging across
   a week or a month is the primary gesture here, and without this the browser
   reads it as "select these day numbers" and turns the drag blue. */
.availGridScroll, table.availGrid, .calPane, .monthGrid, .splitGrid, .yearGrid, .calViews {
    -webkit-user-select: none;
    user-select: none;
}

/* Two gold lines through the hovered cell's own edges, running the full width
   and full height of the grid.
   Highlighting the cell instead would say which cell you are on and nothing
   about where it IS, which on a 96-column grid is the only thing you need --
   a lit square in the middle of a week is still a square in the middle of a
   week. These point at the day label and the hour label either side of it.
   An overlay rather than lit borders: a border lit on one cell stops at that
   cell, and not stopping is the whole point. */
.gridCrossH, .gridCrossV {
    position: absolute;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.1s;
    z-index: 3;
}
/* Left edge starts where the cells do. Running across the day-label gutter
   struck through the very label the line exists to point at. --dayColW is the
   one place that width is written down. */
.gridCrossH { left: var(--dayColW); right: 0; top: 0; }
/* top and height are set by the crosshair script from the first and last
   cell, so the line spans the cells rather than the box -- which starts at the
   hour labels and made it overhang the top of the grid. */
.gridCrossV { top: 0; height: 0; left: 0; }
.gridCrossH::before, .gridCrossH::after,
.gridCrossV::before, .gridCrossV::after {
    content: ''; position: absolute; background: var(--gold);
}
.gridCrossH::before { left: 0; right: 0; top: 0; height: 1px; }
.gridCrossH::after  { left: 0; right: 0; bottom: 0; height: 1px; }
.gridCrossV::before { top: 0; bottom: 0; left: 0; width: 1px; }
.gridCrossV::after  { top: 0; bottom: 0; right: 0; width: 1px; }
.availGridScroll.crossOn .gridCrossH,
.availGridScroll.crossOn .gridCrossV { opacity: 1; }

/* The grid's own tokens, on the scroller and the table both; anything that
   needs them is inside the scroller.

   The bubble colour is the grid's own rather than --overlay-soft: that is
   tuned for text blocks, and on the light theme it gave a 3.5%-black cell on
   a near-white page, so the whole week read as one faint grey rectangle. */
.availGridScroll, table.availGrid {
    --cellBg: var(--overlay-soft);
    --dayColW: 34px;
}
:root[data-theme="light"] .availGridScroll,
:root[data-theme="light"] table.availGrid {
    --cellBg: #e9eef3;
}

/* Separate cells with a gap: each hour is its own bubble, and the gaps are
   the only lines the grid has. */
table.availGrid {
    border-collapse: separate;
    border-spacing: 2px;
    font-size: 0.7rem;
    width: 100%;
}

table.availGrid { table-layout: fixed; }
table.availGrid th { color: var(--text-muted); padding: 0; font-weight: 400; text-align: center; }

/* Hours across the top, days down the left. It used to be the other way round
   -- 24 rows of 7 -- which made a tall narrow column that dwarfed the form.

   Each column is an HOUR, so the axis with times on it is the axis that
   varies by time. 24 of them fit a phone without a scroller;
   .availGridScroll takes over if they ever do not. */
table.availGrid th.slotHead {
    position: relative;
    height: 14px;
    overflow: visible;
}
/* The label sits on the gap before its bubble rather than centred over it:
   on the gap it reads as "time starts here". */
table.availGrid .hourTick {
    position: absolute;
    left: 0;
    bottom: 2px;
    transform: translateX(-50%);
    font-size: 0.58rem;
    line-height: 1;
    white-space: nowrap;
    color: var(--text-muted);
    pointer-events: none;
}
/* Midnight has no room to straddle its line -- half the label would sit
   outside the table and get clipped, which is what turned "12am" into ".2am".
   It anchors to the line instead of centring on it. */
table.availGrid .hourTick[data-hour="0"] { transform: none; }

/* The day column needs a real width, in pixels.
   `width: 1%` asks the browser to shrink it to its content -- which is what
   auto layout does, but this table is `table-layout: fixed`, where a column
   is exactly as wide as it is told and content that does not fit simply
   overflows. So the column collapsed to a few pixels and "Wed" was painted
   straight across the first cells of its own row. Both the corner header and
   the label cell get the width, because under fixed layout the first row is
   what sets the columns. */
table.availGrid th.dayCorner,
table.availGrid td.dayLabel { width: var(--dayColW); }
table.availGrid td.dayLabel {
    color: var(--text);
    /* Left-aligned and flush. Right-aligned in a 54px column left 23px of
       nothing between the page's left edge and the "S" of Sun, so the days
       hung inboard of every other line on the page while the column itself
       was wider than the word in it. All seven names are three letters, so
       flush left is also flush right. The reclaimed width goes to the cells,
       which are the part of this grid that is short of it. */
    padding: 2px 8px 2px 0;
    text-align: left;
    white-space: nowrap;
    overflow: hidden;
    font-weight: 700;
    /* Held against the left edge, so the day a row belongs to is still on
       screen when the week is scrolled into the afternoon. */
    position: sticky;
    left: 0;
    z-index: 2;
    /* A sticky cell needs an opaque fill, or scrolled cells pass through it
       rather than behind it. --bg-card was a shade lighter than what this grid
       actually sits on and drew a visible panel behind the day names. Both
       pages that render this grid put it straight on the page, so --bg is the
       right default; --gridSurface is here for a caller that ever puts it on
       something else, so the fix is one declaration rather than a fork. */
    background: var(--gridSurface, var(--bg));
}
table.availGrid th.dayCorner { position: sticky; left: 0; z-index: 3; background: var(--gridSurface, var(--bg)); }
/* A bubble an hour wide. Under table-layout:fixed the width is a floor the
   columns share the rest of the row over, so the bubbles grow with the page
   and shrink to fit a phone. No borders: the gap between bubbles is the
   division, and an hour is the unit, so there is nothing inside one to rule
   off. */
table.availGrid td.cell {
    width: 20px;
    height: 24px;
    padding: 0;
    border: none;
    border-radius: 6px;
    background: var(--cellBg);
}
/* The grid reads as one object rather than as loose cells. */
/* No frame. The bubbles are the grid; a rectangle drawn round the day names
   and the hour labels boxed in two things that are axes rather than part of
   it. */
table.availGrid { border: none; }

/* A label every two hours where there is room for one, every four where
   there is not: on a phone the week is 24 bubbles ten pixels wide, and
   twelve labels across that is one smear. The bubbles sit lower too, so
   they stay bubbles rather than pills. */
@container (max-width: 600px) {
    table.availGrid .hourTick.isOdd { display: none; }
    table.availGrid td.cell { height: 18px; border-radius: 5px; }
    table.availGrid td.dayLabel { padding-top: 0; padding-bottom: 0; }
}

/* --- month: a day is the unit, so it carries its own hours ---
 *
 * Both pages draw this: take.php as the days a respondent clicks, results.php
 * as how many people are free on each. Same geometry, because the two get read
 * against each other -- the second was a table of 22px cells that looked
 * nothing like the thing being answered.
 *
 * --fill is the share of the day that is free (one person's hours in the form,
 * the share of the group in the results), so a glance across a month reads as
 * a gradient rather than as on/off.
 */
.monthGrid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.monthHead { font-size: 0.66rem; color: var(--text-muted); text-align: center; padding-bottom: 1px; }
/* The number in the top left corner, the hours in the bottom right: a day
   reads like a calendar's, and the cell can be any height. */
.monthDay {
    position: relative;
    display: grid; grid-template-rows: 1fr auto; gap: 0;
    min-height: 27px;
    padding: 2px 5px;
    border: 1px solid var(--border);
    border-radius: 5px;
    background: color-mix(in srgb, var(--gold) calc(var(--fill, 0) * 55%), var(--overlay-soft));
    font-family: var(--font-mono);
    line-height: 1.2;
}
.monthDay.outside { opacity: 0.35; }
.monthNum { font-size: 0.72rem; color: var(--text); justify-self: start; align-self: start; }
.monthHours { font-size: 0.64rem; color: var(--text-muted); justify-self: end; align-self: end; }
/* No "off". A day says the hours it carries, and zero is a number. */
