/*
 * The booking calendar.
 *
 * Two things carry it. A day where a stay begins or ends is occupied in half, and that half is a
 * band closing with an arc — the way an occupied stretch closes — so the cell reads as the end of
 * something rather than as a day cut in two. And the months are one strip in a scroll container
 * with snapping: the browser does the scrolling, the arrows only nudge it, so a trackpad, a finger
 * and the two buttons all do the same thing.
 */
/*
 * The palette is on the legend as well, because the owner's legend stands above the calendars rather
 * than inside one — and a key with no colour explains nothing.
 */
.bunky-calendar,
.bunky-calendar__legend {
    /*
     * For a guest, three colours and nothing else to learn: white is free, grey is not to be had —
     * taken or not offered, which is the same thing to them — and yellow, the site's own, is what
     * you chose.
     *
     * For the owner the grey splits in two, because those are two different things to her: an empty
     * grey is a night nobody offers, and yellow is a booking. Same palette, one more meaning.
     */
    --bunky-free: #ffffff;
    --bunky-taken: #e3e3e3;
    --bunky-unavailable: #e3e3e3;
    --bunky-booked: #ffe800;
    --bunky-selected: #ffe800;
    /* A night you chose and cannot have; for the owner, one she closed under a booking (I15). */
    --bunky-conflict: #d13b3b;
    --bunky-line: #cccccc;

    margin: 1.5rem 0;
    /* The arrows are laid over the strip, so they need something to be positioned against. */
    position: relative;
}

/*
 * The arrows sit on the line with the month names, each in its own corner. Laid over the strip
 * rather than placed above it: an arrow that comes and goes must not move the calendar under the
 * cursor, and the caption line is short enough to have room at both ends.
 */
.bunky-calendar__bar {
    display: flex;
    /* The next arrow keeps its corner even when the previous one is not there, which
       space-between cannot do: with one child it aligns to the start. */
    justify-content: flex-end;
    left: 0;
    margin: 0;
    /* Only the buttons themselves catch the mouse; the captions stay selectable. */
    pointer-events: none;
    position: absolute;
    right: 0;
    /* Lifted so the round buttons sit centred on the caption line, not on the weekdays below it. */
    top: -.15rem;
    z-index: 2;
}

.bunky-calendar__arrow {
    align-items: center;
    background: #ffffff;
    border: 1px solid var(--bunky-line);
    border-radius: 50%;
    /*
     * A white ring, not a border: the arrow lies over the strip, and this keeps a month name from
     * running into it. Drawn as a shadow so it takes no space and leaves `outline` to focus.
     */
    box-shadow: 0 0 0 5px #ffffff;
    color: #444444;
    cursor: pointer;
    display: inline-flex;
    height: 2rem;
    justify-content: center;
    padding: 0;
    pointer-events: auto;
    transition: border-color .15s, color .15s;
    width: 2rem;
}

/*
 * `hidden` has to be said again here: the attribute is a UA rule with the weakest specificity, and
 * the `display: inline-flex` above beats it — so the arrows stayed on screen with nowhere to go.
 */
.bunky-calendar__arrow[hidden] {
    display: none;
}

.bunky-calendar__arrow:hover {
    border-color: #222222;
    color: #222222;
}

.bunky-calendar__arrow--prev {
    margin-right: auto;
}

/* One drawn chevron, turned around for the other direction. */
.bunky-calendar__arrow--next svg {
    transform: rotate(180deg);
}

.bunky-calendar__track {
    display: flex;
    gap: 1.5rem;
    overflow-x: auto;
    /* Room for the scrollbar, so it never sits on the last row of days. */
    padding-bottom: .5rem;
    scroll-behavior: smooth;
    /* A month always lands on the left edge, whether it was a finger or an arrow that moved it. */
    scroll-snap-type: x mandatory;
}

@media (prefers-reduced-motion: reduce) {
    .bunky-calendar__track {
        scroll-behavior: auto;
    }
}

.bunky-calendar__month {
    border-collapse: collapse;
    /* Never shrunk to fit the strip: a month keeps its size and the strip scrolls instead. */
    flex: 0 0 auto;
    /* Fits a phone; on anything wider two or more sit side by side. */
    max-width: 100%;
    scroll-snap-align: start;
    /* Fixed layout, so a week with a two-digit day is not wider than one without. */
    table-layout: fixed;
    width: 17.5rem;
}

/*
 * A phone shows one month, which needs no rule of its own: the month is as wide as the strip and
 * snapping does the rest.
 */
@media (max-width: 39.999rem) {
    .bunky-calendar__track {
        gap: 1rem;
    }

    .bunky-calendar__day,
    .bunky-calendar__day > button,
    .bunky-calendar__day > span,
    .bunky-calendar__empty {
        /* A little taller, because a finger is not a mouse pointer. */
        height: 2.75rem;
        line-height: 2.75rem;
    }
}

.bunky-calendar__month caption {
    font-size: 1.05rem;
    font-weight: 700;
    padding-bottom: .5rem;
    /* Centred, which also leaves both ends of the line free for the arrows. */
    text-align: center;
}

.bunky-calendar__month th {
    font-size: .8rem;
    font-weight: 400;
    padding: .25rem;
}

.bunky-calendar__day {
    border: 1px solid var(--bunky-line);
    height: 2.5rem;
    padding: 0;
    /* The two halves and the hover tint are drawn inside the cell. */
    position: relative;
    text-align: center;
    width: 2.5rem;
}

/*
 * A selectable day holds a button and the others a span. Without this they are different boxes
 * with different line heights, and a row of cells ends up looking uneven for no reason a reader
 * could guess.
 *
 * Raised above the halves and the tint, which are absolutely positioned and would cover it.
 */
.bunky-calendar__day > button,
.bunky-calendar__day > span {
    box-sizing: border-box;
    display: block;
    font: inherit;
    height: 2.5rem;
    line-height: 2.5rem;
    margin: 0;
    padding: 0;
    position: relative;
    width: 100%;
    z-index: 1;
}

/*
 * The plain cell: left half takes its colour, right half its own. Both the same reads as one
 * colour, so a free day and a taken one need no rules of their own — and a selected term is one
 * more colour that lands in a half.
 *
 * Which colour a half is comes from the attribute PHP wrote, right here and not from the script: a
 * calendar has to have its colours without JavaScript, and the owner's — where nothing is picked and
 * the picking script never runs — has only these. Selecting a term overwrites them, an inline style
 * beating an attribute selector.
 */
.bunky-calendar__day {
    background-image: linear-gradient(to right, var(--bunky-left) 0 50%, var(--bunky-right) 50% 100%);
}

.bunky-calendar__day[data-left="free"] { --bunky-left: var(--bunky-free); }
.bunky-calendar__day[data-left="taken"] { --bunky-left: var(--bunky-taken); }
.bunky-calendar__day[data-left="unavailable"] { --bunky-left: var(--bunky-unavailable); }
.bunky-calendar__day[data-left="booked"] { --bunky-left: var(--bunky-booked); }
.bunky-calendar__day[data-left="conflict"] { --bunky-left: var(--bunky-conflict); }

.bunky-calendar__day[data-right="free"] { --bunky-right: var(--bunky-free); }
.bunky-calendar__day[data-right="taken"] { --bunky-right: var(--bunky-taken); }
.bunky-calendar__day[data-right="unavailable"] { --bunky-right: var(--bunky-unavailable); }
.bunky-calendar__day[data-right="booked"] { --bunky-right: var(--bunky-booked); }
.bunky-calendar__day[data-right="conflict"] { --bunky-right: var(--bunky-conflict); }

/*
 * A day split between two colours.
 *
 * Where two things meet, each closes with its own arc ('both'): the ground is the free colour, so a
 * half that is free draws white on white and only the other arc shows. Inside a chosen range that
 * would break the range into separate pills, so there the morning closes and the other colour
 * fills what the arc leaves ('left'). Which of the two it is comes from the day and from the
 * selection — CalendarDay::cap() and capFor() in calendar.js.
 */
.bunky-calendar__day[data-cap] {
    background-image: none;
}

.bunky-calendar__day[data-cap=""] {
    background-image: linear-gradient(to right, var(--bunky-left) 0 50%, var(--bunky-right) 50% 100%);
}

.bunky-calendar__day[data-cap="left"] { background-color: var(--bunky-right); }
.bunky-calendar__day[data-cap="both"] { background-color: var(--bunky-free); }

.bunky-calendar__day[data-cap="left"]::before,
.bunky-calendar__day[data-cap="both"]::before,
.bunky-calendar__day[data-cap="both"]::after {
    bottom: 0;
    content: '';
    position: absolute;
    top: 0;
    width: 50%;
}

.bunky-calendar__day[data-cap="left"]::before,
.bunky-calendar__day[data-cap="both"]::before {
    background: var(--bunky-left);
    /* Straight along the edge of the cell, an arc where the stretch ends. */
    border-radius: 0 60% 60% 0 / 0 50% 50% 0;
    left: 0;
}

.bunky-calendar__day[data-cap="both"]::after {
    background: var(--bunky-right);
    border-radius: 60% 0 0 60% / 50% 0 0 50%;
    right: 0;
}

/*
 * A day that cannot be booked: the number goes quiet with the cell — one grey for all of them.
 *
 * Two shades meant a grid of grey days where the past ones were a shade lighter, and the difference
 * said nothing a guest could use: neither can be had.
 */
.bunky-calendar--guest .bunky-calendar__day--unavailable,
.bunky-calendar--guest .bunky-calendar__day--full,
.bunky-calendar--guest .bunky-calendar__day--past { color: #999999; }

/*
 * The owner's calendar dims only what is not on offer. A booking is the thing she came to look at,
 * so it keeps the full black — and a past one is history, not noise.
 */
.bunky-calendar--owner .bunky-calendar__day--unavailable { color: #999999; }

.bunky-calendar__pick {
    background: none;
    border: 0;
    cursor: pointer;
}

.bunky-calendar__day[aria-selected="true"],
.bunky-calendar__day--in-range {
    color: #111111;
    font-weight: 600;
}

.bunky-calendar__empty {
    border: 0;
    /* Keeps the height of a row that has no days in it at all. */
    height: 2.5rem;
}

/*
 * The range under the cursor, before it is chosen: grey while every night in it is free, red the
 * moment one is not. A guest sees the answer while still deciding, not after clicking.
 *
 * Painted onto the box that holds the number, because both pseudo-elements of the cell can be
 * spoken for by the two halves — and that box lies above them, so a tinted day still shows what
 * it is.
 */
.bunky-calendar__day--preview > button,
.bunky-calendar__day--preview > span {
    box-shadow: inset 0 0 0 99rem rgba(0, 0, 0, .06);
}

.bunky-calendar__day--preview-blocked > button,
.bunky-calendar__day--preview-blocked > span {
    box-shadow: inset 0 0 0 99rem rgba(179, 32, 32, .14);
}

.bunky-calendar__legend {
    font-size: .85rem;
    margin: .5rem 0 0;
    /* Under a strip as wide as the content, a line of keys hanging on the left reads as left over. */
    text-align: center;
}

/* Hers stands above several calendars and left of them, where a heading would be. */
.bunky-calendar__legend--owner {
    text-align: left;
}

.bunky-calendar__key {
    border: 1px solid var(--bunky-line);
    display: inline-block;
    height: 1rem;
    margin: 0 .25rem 0 .75rem;
    position: relative;
    vertical-align: -.2rem;
    width: 1rem;
}

.bunky-calendar__key--free { background: var(--bunky-free); }
.bunky-calendar__key--taken { background: var(--bunky-taken); }
.bunky-calendar__key--unavailable { background: var(--bunky-unavailable); }
.bunky-calendar__key--booked { background: var(--bunky-booked); }
.bunky-calendar__key--conflict { background: var(--bunky-conflict); }

/* The same two shapes as in the grid, so the legend cannot describe something the days do not do. */
.bunky-calendar__key--departure,
.bunky-calendar__key--arrival {
    background: var(--bunky-free);
}

.bunky-calendar__key--departure::before,
.bunky-calendar__key--arrival::before {
    background: var(--bunky-taken);
    bottom: 0;
    content: '';
    position: absolute;
    top: 0;
    width: 50%;
}

.bunky-calendar__key--departure::before {
    border-radius: 0 60% 60% 0 / 0 50% 50% 0;
    left: 0;
}

.bunky-calendar__key--arrival::before {
    border-radius: 60% 0 0 60% / 50% 0 0 50%;
    right: 0;
}

/*
 * The owner's calendar stands on the admin's grey, so it needs a card of its own: without it the
 * white ring around an arrow reads as a hole rather than as a ring.
 */
.bunky-calendar--owner {
    background: #ffffff;
    border: 1px solid #dcdcde;
    margin: 0 0 1.5rem;
    padding: 1rem 1rem .5rem;
}

.bunky-calendar--owner .bunky-calendar__bar {
    left: 1rem;
    right: 1rem;
    top: .85rem;
}

/*
 * Smaller than the guest's, because nothing here is aimed at with a finger: a day is read, not hit.
 * More months fit on the screen at once, which is what the owner came for.
 */
.bunky-calendar--owner .bunky-calendar__month {
    width: 13.5rem;
}

.bunky-calendar--owner .bunky-calendar__track {
    gap: 1rem;
}

.bunky-calendar--owner .bunky-calendar__day,
.bunky-calendar--owner .bunky-calendar__day > span,
.bunky-calendar--owner .bunky-calendar__day > button,
.bunky-calendar--owner .bunky-calendar__empty {
    font-size: .82rem;
    height: 1.85rem;
    line-height: 1.85rem;
    width: 1.85rem;
}

.bunky-calendar--owner .bunky-calendar__month caption {
    font-size: .95rem;
    padding-bottom: .35rem;
}

.bunky-calendar--owner .bunky-calendar__month th {
    font-size: .7rem;
    padding: .15rem;
}

.bunky-calendar__legend--owner {
    font-size: .8rem;
    margin: 0 0 .75rem;
}

/*
 * The same focus ring as the form's, kept here as well: the admin loads this stylesheet and not
 * form.css, and the arrows and the strip are reachable by keyboard on both screens.
 */
.bunky-calendar :focus-visible {
    border-radius: 2px;
    outline: 3px solid var(--bunky-selected);
    outline-offset: 1px;
}

/* The track is scrollable, so it takes focus by mouse as well, and gets the same ring. */
.bunky-calendar__track:focus {
    outline: 3px solid var(--bunky-selected);
    outline-offset: 1px;
}
