/* ── Availability calendar ────────────────────────────────────────────────
   One calendar, three jobs:

     range    a guest draws a stay across it        (book-property)
     edit     a host opens and closes nights on it  (add-booking, edit-property)
     heatmap  occupancy density over a month        (booking analytics)

   The three share a grid, a header and a legend so a night means the same
   thing wherever it is drawn. What changes is what a click does and how a
   day is filled.

   Built on the page's own tokens (--zvv-ink, --zvv-line, --drac-*), so it
   follows the light/dark theme without a second set of rules. Accent washes are
   mixed from those same tokens rather than written as literal rgba(): the
   Dracula accents invert between themes — #7c3aed purple becomes #bd93f9 — and a
   tint frozen at the light value is invisible on a dark ground. For the same
   reason text sitting on an accent fill is --zvv-bg, not #fff: the fill is dark
   in the light theme and light in the dark one, and the page ground is always
   the opposite of its own ink. */

.zvv-acal {
    --acal-cell: 40px;
    --acal-gap: 4px;
    --acal-radius: 11px;
    --acal-booked: var(--drac-red, #dc2626);
    --acal-blocked: var(--drac-orange, #ea580c);
    --acal-open: var(--drac-green, #16a34a);
    --acal-pick: var(--drac-purple, #7c3aed);

    border: 1px solid var(--zvv-line, #e9e6ff);
    border-radius: 18px;
    padding: 14px;
    background: var(--zvv-card, #fff);
}

.zvv-acal[hidden] { display: none; }

/* ── Header ─────────────────────────────────────────────────────────── */

.zvv-acal-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 12px;
}

.zvv-acal-title {
    font-size: 0.95rem;
    font-weight: 800;
    color: var(--zvv-ink, #17123a);
    letter-spacing: -0.01em;
}

.zvv-acal-nav { display: flex; gap: 6px; }

.zvv-acal-nav button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    border: 1px solid var(--zvv-line, #e9e6ff);
    border-radius: 9px;
    background: transparent;
    color: var(--zvv-ink, #17123a);
    font-size: 13px;
    cursor: pointer;
    transition: background .14s, border-color .14s, opacity .14s;
}

.zvv-acal-nav button:hover:not(:disabled) {
    background: color-mix(in srgb, var(--acal-pick) 12%, transparent);
    border-color: var(--acal-pick);
}

.zvv-acal-nav button:disabled { opacity: .35; cursor: default; }

/* ── Months ─────────────────────────────────────────────────────────── */

/* auto-fit rather than a fixed column count: the same calendar sits in a wide
   admin page and in a narrow form column, and a second month forced into 240px
   is what makes a date grid look broken. Months drop to one per row on their
   own when the container cannot hold two. */
.zvv-acal-months {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(238px, 1fr));
    gap: 20px 24px;
}

.zvv-acal-month-name {
    margin-bottom: 8px;
    font-size: 0.78rem;
    font-weight: 800;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--zvv-muted, #6b7280);
}

/* Only the multi-month layouts need a per-month caption; a single month is
   already named by the header above it. */
.zvv-acal[data-months="1"] .zvv-acal-month-name { display: none; }

.zvv-acal-dow,
.zvv-acal-grid {
    display: grid;
    grid-template-columns: repeat(7, minmax(0, 1fr));
    gap: var(--acal-gap);
}

/* Anchor for the closed/booked chooser, which is absolutely positioned at the
   offset of the cell that opened it. */
.zvv-acal-grid { position: relative; }

.zvv-acal-dow {
    margin-bottom: 6px;
}

.zvv-acal-dow span {
    text-align: center;
    font-size: 10px;
    font-weight: 800;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--zvv-muted, #6b7280);
}

/* ── Days ───────────────────────────────────────────────────────────── */

.zvv-acal-day {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: var(--acal-cell);
    padding: 0;
    border: 1px solid transparent;
    border-radius: var(--acal-radius);
    background: transparent;
    color: var(--zvv-ink, #17123a);
    font-size: 0.82rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    cursor: pointer;
    transition: background .12s, color .12s, border-color .12s;
}

.zvv-acal-day.is-blank {
    cursor: default;
    pointer-events: none;
}

/* ── Priced days ─────────────────────────────────────────────────────
   When the rate moves by date the price is the thing being chosen, so the
   cell stacks: date above, its own price below. The number stays quiet —
   it is there to be compared across the month, not to shout. */
.zvv-acal[data-acal-prices] .zvv-acal-day {
    flex-direction: column;
    gap: 1px;
    min-height: calc(var(--acal-cell) + 16px);
    padding: 4px 2px;
}

.zvv-acal-num { line-height: 1.1; }

.zvv-acal-price {
    font-size: 9.5px;
    font-weight: 700;
    line-height: 1;
    color: var(--zvv-muted, #6b7280);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.zvv-acal-day.is-end .zvv-acal-price,
.zvv-acal-day.is-end .zvv-acal-num { color: var(--zvv-bg, #fff); }

.zvv-acal-day:disabled .zvv-acal-price { text-decoration: line-through; }

/* Scarcity, shown only when it is actually scarce (3 or fewer). */
.zvv-acal-left {
    font-size: 8.5px;
    font-weight: 800;
    line-height: 1;
    color: var(--acal-blocked);
    text-transform: uppercase;
    letter-spacing: .02em;
}

.zvv-acal-day.is-end .zvv-acal-left { color: var(--zvv-bg, #fff); }

/* The ends are excluded: the hover wash is the more specific selector and would
   strip their solid fill, leaving text picked for that fill sitting on a bare
   cell — invisible in either theme. They get their own hover below. */
.zvv-acal-day:hover:not(:disabled):not(.is-blank):not(.is-end) {
    background: color-mix(in srgb, var(--acal-pick) 14%, transparent);
}

/* Toward the page's own ink: deeper purple on the light theme, brighter lavender
   on the dark one, without either losing contrast against the label. */
.zvv-acal-day.is-end:hover:not(:disabled) {
    background: color-mix(in srgb, var(--acal-pick) 85%, var(--zvv-ink, #17123a));
}

.zvv-acal-day:focus-visible {
    outline: 2px solid var(--acal-pick);
    outline-offset: 1px;
}

/* Today gets a mark rather than a fill, so it never competes with selection. */
.zvv-acal-day.is-today::after {
    content: "";
    position: absolute;
    bottom: 5px;
    left: 50%;
    transform: translateX(-50%);
    width: 4px;
    height: 4px;
    border-radius: 50%;
    background: var(--acal-pick);
}

/* Unavailable — struck through rather than merely greyed, so the reason for
   a gap in the month is legible at a glance instead of looking like a
   rendering fault. */
.zvv-acal-day:disabled,
.zvv-acal-day.is-out {
    cursor: not-allowed;
    color: var(--zvv-muted, #6b7280);
    opacity: .55;
}

.zvv-acal-day.is-booked,
.zvv-acal-day.is-blocked,
.zvv-acal-day.is-closed {
    background-image: linear-gradient(
        to top left,
        transparent calc(50% - 0.6px),
        currentColor calc(50% - 0.6px),
        currentColor calc(50% + 0.6px),
        transparent calc(50% + 0.6px)
    );
}

.zvv-acal-day.is-booked  { color: var(--acal-booked); opacity: .8; }
.zvv-acal-day.is-blocked { color: var(--acal-blocked); opacity: .8; }
.zvv-acal-day.is-closed  { color: var(--zvv-muted, #6b7280); opacity: .4; }

/* ── Range selection ────────────────────────────────────────────────── */

/* The nights between the ends carry a flat band so the stay reads as one
   object rather than two dates that happen to be selected. Square inner
   edges are what join the cells into a bar despite the grid gap. */
.zvv-acal-day.is-within {
    background: color-mix(in srgb, var(--acal-pick) 16%, transparent);
    border-radius: 0;
    color: var(--zvv-ink, #17123a);
    opacity: 1;
}

.zvv-acal-day.is-end {
    background: var(--acal-pick);
    border-color: var(--acal-pick);
    color: var(--zvv-bg, #fff);
    opacity: 1;
}

.zvv-acal-day.is-end.is-start { border-radius: var(--acal-radius) 0 0 var(--acal-radius); }
.zvv-acal-day.is-end.is-finish { border-radius: 0 var(--acal-radius) var(--acal-radius) 0; }
.zvv-acal-day.is-end.is-start.is-finish { border-radius: var(--acal-radius); }

/* The band has to reach across the gap or it reads as separate chips. */
.zvv-acal-day.is-within::before,
.zvv-acal-day.is-end:not(.is-start)::before {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    left: calc(var(--acal-gap) * -1 - 1px);
    width: calc(var(--acal-gap) + 2px);
    background: color-mix(in srgb, var(--acal-pick) 16%, transparent);
    z-index: -1;
}

.zvv-acal-day.is-end::after { display: none; }

/* ── Edit mode ──────────────────────────────────────────────────────────
   A guest draws a stay; a host punches holes in a season. Same grid, opposite
   gesture — so here a night is a switch with two solid states rather than a
   range with two ends, and the strike-through the guest sees is dropped: to
   the host a closed night is a decision, not an obstacle. */

.zvv-acal-host { --acal-cell: 42px; }

.zvv-acal[data-mode="edit"] .zvv-acal-day {
    border-color: var(--zvv-line, #e9e6ff);
    background: var(--zvv-card, #fff);
}

.zvv-acal[data-mode="edit"] .zvv-acal-day:hover:not(:disabled) {
    border-color: var(--acal-blocked);
    background: color-mix(in srgb, var(--acal-blocked) 12%, transparent);
}

.zvv-acal[data-mode="edit"] .zvv-acal-day.is-blocked,
.zvv-acal[data-mode="edit"] .zvv-acal-day.is-blocked:hover {
    background: var(--acal-blocked);
    border-color: var(--acal-blocked);
    background-image: none;
    color: var(--zvv-bg, #fff);
    opacity: 1;
}

/* Booked nights are not the host's to move from here, so they read as fixed
   rather than merely unselected. */
.zvv-acal[data-mode="edit"] .zvv-acal-day.is-booked,
.zvv-acal[data-mode="edit"] .zvv-acal-day.is-booked:hover {
    background: color-mix(in srgb, var(--acal-booked) 16%, transparent);
    border-color: color-mix(in srgb, var(--acal-booked) 38%, transparent);
    background-image: none;
    color: var(--acal-booked);
    opacity: 1;
    cursor: not-allowed;
}

/* A night the host marked as booked elsewhere. It wears the booked colour
   because that is what it is, but it stays the host's to undo — unlike a real
   booking above, which is fixed. */
.zvv-acal[data-mode="edit"] .zvv-acal-day.is-host-booked,
.zvv-acal[data-mode="edit"] .zvv-acal-day.is-host-booked:hover {
    background: var(--acal-booked);
    border-color: var(--acal-booked);
    background-image: none;
    color: var(--zvv-bg, #fff);
    opacity: 1;
    cursor: pointer;
}

/* A sweep must not turn into a text selection halfway across the month. */
.zvv-acal.is-dragging { user-select: none; }
.zvv-acal.is-dragging .zvv-acal-day { cursor: crosshair; }

/* Picked, but not yet answered for — the run a sweep or a shift-click is about
   to mark. Deliberately not the closed colour: nothing has been decided yet,
   and the menu asking which colour it becomes is still open over it. */
.zvv-acal[data-mode="edit"] .zvv-acal-day.is-picking,
.zvv-acal[data-mode="edit"] .zvv-acal-day.is-picking:hover {
    border-color: var(--acal-pick);
    box-shadow: inset 0 0 0 2px var(--acal-pick);
    opacity: 1;
}

.zvv-acal[data-mode="edit"] .zvv-acal-day.is-picking:not(.is-blocked):not(.is-host-booked) {
    background: color-mix(in srgb, var(--acal-pick) 14%, transparent);
    color: var(--zvv-ink, #17123a);
}

/* ── Closed or booked? ──────────────────────────────────────────────────
   The menu a click on an open night opens, anchored to that night's cell.
   Two answers only: those are the two reasons a host takes a night off. */
.zvv-acal-pick {
    position: absolute;
    z-index: 30;
    transform: translateX(-50%);   /* left is the cell's centre */
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-width: 132px;
    padding: 7px;
    border-radius: 12px;
    border: 1px solid var(--zvv-line, rgba(124, 58, 237, 0.18));
    background: var(--zvv-panel, #fff);
    box-shadow: 0 18px 40px rgba(15, 10, 46, 0.24);
}

.zvv-acal-pick-day {
    padding: 1px 6px 4px;
    font-size: 10px;
    font-weight: 800;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--zvv-muted, #6b7280);
}

.zvv-acal-pick-opt {
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 7px 9px;
    border: 0;
    border-radius: 8px;
    background: none;
    color: var(--zvv-ink, #1f2937);
    font-size: 12.5px;
    font-weight: 700;
    text-align: left;
    cursor: pointer;
    transition: background 0.14s, color 0.14s;
}

.zvv-acal-pick-opt i { font-size: 13px; }
.zvv-acal-pick-opt.is-closed i { color: var(--acal-blocked); }
.zvv-acal-pick-opt.is-booked i { color: var(--acal-booked); }
.zvv-acal-pick-opt.is-open i   { color: var(--acal-open, #16a34a); }

.zvv-acal-pick-opt:hover,
.zvv-acal-pick-opt:focus-visible {
    background: color-mix(in srgb, var(--acal-blocked) 12%, transparent);
    outline: none;
}

.zvv-acal-pick-opt.is-booked:hover,
.zvv-acal-pick-opt.is-booked:focus-visible {
    background: color-mix(in srgb, var(--acal-booked) 14%, transparent);
}

.zvv-acal-pick-opt.is-open:hover,
.zvv-acal-pick-opt.is-open:focus-visible {
    background: color-mix(in srgb, var(--acal-open, #16a34a) 14%, transparent);
}

/* The reason a period was taken off the market, in the readback chips. */
.zvv-acal-span.is-booked .zvv-acal-span-n { color: var(--acal-booked); }

/* ── Closed periods, read back ──────────────────────────────────────────
   The signature of the host editor: thirty highlighted cells across two
   months cannot be checked at a glance, but "26–28 Aug · 3 nights" can. */

.zvv-acal-spans {
    display: flex;
    flex-wrap: wrap;
    gap: 7px;
    margin-top: 12px;
}

.zvv-acal-spans[hidden] { display: none; }

.zvv-acal-span {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 5px 5px 5px 11px;
    border: 1px solid color-mix(in srgb, var(--acal-blocked) 38%, transparent);
    border-radius: 999px;
    background: color-mix(in srgb, var(--acal-blocked) 12%, transparent);
    font-size: 0.75rem;
    font-weight: 700;
    color: var(--zvv-ink, #17123a);
}

.zvv-acal-span-n {
    color: var(--acal-blocked);
    font-weight: 800;
    font-variant-numeric: tabular-nums;
}

.zvv-acal-span-x {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: color-mix(in srgb, var(--acal-blocked) 20%, transparent);
    color: var(--acal-blocked);
    font-size: 12px;
    cursor: pointer;
    transition: background .14s, color .14s;
}

.zvv-acal-span-x:hover {
    background: var(--acal-blocked);
    color: var(--zvv-bg, #fff);
}

.zvv-acal-msg.is-shut { color: var(--acal-blocked); }

/* ── Heatmap mode ───────────────────────────────────────────────────── */

/* --heat is 0–1; the fill carries the density and the text flips to white
   once the ground is dark enough to need it. */
.zvv-acal[data-mode="heatmap"] .zvv-acal-day {
    cursor: default;
    background: color-mix(in srgb, var(--acal-pick) calc(var(--heat, 0) * 100%), transparent);
}

.zvv-acal[data-mode="heatmap"] .zvv-acal-day.is-hot { color: var(--zvv-bg, #fff); }
.zvv-acal[data-mode="heatmap"] .zvv-acal-day:hover { background: color-mix(in srgb, var(--acal-pick) calc(var(--heat, 0) * 100%), transparent); }

/* ── Status line + legend ───────────────────────────────────────────── */

.zvv-acal-msg {
    margin: 12px 0 0;
    font-size: 0.78rem;
    font-weight: 600;
    line-height: 1.5;
    color: var(--zvv-muted, #6b7280);
    min-height: 1.2em;
}

.zvv-acal-msg.is-ok   { color: var(--acal-open); }
.zvv-acal-msg.is-warn { color: var(--acal-booked); }

.zvv-acal-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 12px;
    padding-top: 11px;
    border-top: 1px solid var(--zvv-line, #e9e6ff);
}

.zvv-acal-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    font-size: 0.72rem;
    font-weight: 700;
    color: var(--zvv-muted, #6b7280);
}

.zvv-acal-legend span {
    display: inline-flex;
    align-items: center;
    gap: 5px;
}

.zvv-acal-key {
    width: 11px;
    height: 11px;
    border-radius: 4px;
    border: 1px solid currentColor;
}

.zvv-acal-key.is-booked  { background: color-mix(in srgb, var(--acal-booked) 28%, transparent); color: var(--acal-booked); }
.zvv-acal-key.is-blocked { background: color-mix(in srgb, var(--acal-blocked) 28%, transparent); color: var(--acal-blocked); }
.zvv-acal-key.is-open    { background: transparent; color: var(--zvv-line, #cbd5e1); }
.zvv-acal-key.is-pick    { background: var(--acal-pick); color: var(--acal-pick); }

.zvv-acal-clear {
    border: 0;
    background: none;
    padding: 0;
    color: var(--acal-pick);
    font-size: 0.75rem;
    font-weight: 800;
    cursor: pointer;
    text-decoration: underline;
}

.zvv-acal-clear[hidden] { display: none; }

/* ── Range-mode summary ─────────────────────────────────────────────── */

/* The two ends, as a control rather than a readout: tapping one says which
   end the next click sets, which is the only state the guest needs. */
.zvv-acal-ends {
    display: flex;
    align-items: stretch;
    gap: 6px;
    margin-bottom: 12px;
}

.zvv-acal-end {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 9px 11px;
    border: 1px solid var(--zvv-line, #e9e6ff);
    border-radius: 12px;
    background: transparent;
    text-align: left;
    cursor: pointer;
    transition: border-color .15s, background .15s, box-shadow .15s;
}

.zvv-acal-end small {
    font-size: 9.5px;
    font-weight: 800;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--zvv-muted, #6b7280);
}

.zvv-acal-end strong {
    font-size: 0.9rem;
    font-weight: 800;
    color: var(--zvv-ink, #17123a);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.zvv-acal-end strong.is-empty {
    color: var(--zvv-muted, #6b7280);
    font-weight: 600;
}

.zvv-acal-end.is-active {
    border-color: var(--acal-pick);
    background: color-mix(in srgb, var(--acal-pick) 10%, transparent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--acal-pick) 16%, transparent);
}

.zvv-acal-ends-arrow {
    display: flex;
    align-items: center;
    color: var(--zvv-muted, #6b7280);
    font-size: 12px;
}

/* JS replaces the native date inputs; without it they are the whole control. */
.zvv-acal-ready .zvv-acal-native { display: none; }

/* ── How to select more than one night ──────────────────────────────────
   Under the host's calendar. A sweep and a shift-click are not discoverable
   from the grid itself, so they are written down next to it. */
.zvv-avail-howto {
    display: grid;
    gap: 7px;
    margin: 12px 0 0;
    padding: 12px 14px;
    list-style: none;
    border: 1px dashed var(--zvv-line, #e9e6ff);
    border-radius: 14px;
    background: color-mix(in srgb, var(--acal-pick, #7c3aed) 4%, transparent);
    color: var(--zvv-muted, #6b7280);
    font-size: 12.5px;
    line-height: 1.5;
}

.zvv-avail-howto strong { color: var(--zvv-ink, #17123a); font-weight: 700; }

.zvv-avail-howto-key {
    display: inline-block;
    margin-right: 6px;
    padding: 2px 7px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--acal-pick, #7c3aed) 14%, transparent);
    color: var(--acal-pick, #7c3aed);
    font-size: 11px;
    font-weight: 800;
    letter-spacing: 0.02em;
    white-space: nowrap;
}

@media (max-width: 720px) {
    .zvv-acal { --acal-cell: 36px; padding: 12px; }
    .zvv-acal-host { --acal-cell: 38px; }
}

@media (prefers-reduced-motion: reduce) {
    .zvv-acal-day,
    .zvv-acal-end,
    .zvv-acal-span-x,
    .zvv-acal-nav button { transition: none; }
}

/* ── The date field's dropdown ────────────────────────────────────────────
   "Bookable from" and "Bookable until", which used to open the browser's own
   date popup — a grey box in Chrome's shape and Chrome's language, sitting on
   top of the calendar this file spends 300 lines drawing.

   So it is the same calendar, in a sheet under the field: .zvv-dpick is a
   .zvv-acal, and every day cell, weekday letter and month arrow below is the
   one the grid under it already uses. Nothing here re-describes a day — it
   only makes the card float, tightens the cell, and adds the two things a
   single-date field needs that a range calendar does not: a month jump and a
   way to say "no date at all".

   See the DatePicker block in assets/availability-calendar.js. */

/* The field itself. The form's own .zvv-ps-control draws the border, the icon
   and the focus ring; this only anchors the sheet to it and lays out what
   replaced the input. */
.zvv-dpick-host { position: relative; }

.zvv-dpick-trigger {
    flex: 1;
    min-width: 0;
    padding: 0;
    border: none;
    background: none;
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.zvv-dpick-trigger:focus { outline: none; }

.zvv-dpick-value {
    display: block;
    overflow: hidden;
    color: var(--zvv-ink, #17123a);
    font-size: 0.92rem;
    font-weight: 600;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Empty is not blank: each field says what its own emptiness means — "from
   today", "no end date" — so nobody has to read the hint underneath to find
   out whether they have to answer at all. */
.zvv-dpick-value.is-empty {
    color: var(--zvv-muted, #6b7280);
    font-weight: 500;
}

.zvv-dpick-clear,
.zvv-dpick-caret {
    flex: 0 0 auto;
    color: var(--zvv-muted, #6b7280);
    line-height: 1;
}

.zvv-dpick-clear {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: color-mix(in srgb, var(--zvv-ink, #17123a) 7%, transparent);
    font-size: 10px;
    cursor: pointer;
    transition: background .14s, color .14s;
}

.zvv-dpick-clear:hover {
    background: color-mix(in srgb, var(--drac-red, #dc2626) 15%, transparent);
    color: var(--drac-red, #dc2626);
}

.zvv-dpick-clear[hidden] { display: none; }

.zvv-dpick-caret { font-size: 11px; transition: transform .16s; }
.zvv-dpick-host:has(.zvv-dpick-trigger[aria-expanded="true"]) .zvv-dpick-caret { transform: rotate(180deg); }

/* ── The sheet ── */

.zvv-dpick {
    --acal-cell: 34px;
    --acal-gap: 3px;
    --acal-radius: 9px;

    position: absolute;
    top: calc(100% + 8px);
    left: 0;
    z-index: 60;
    width: min(300px, calc(100vw - 32px));
    padding: 12px;
    /* It floats over the form, so it needs a ground of its own and a shadow
       deep enough to sit on top of the calendar below it. */
    background: var(--zvv-card, #fff);
    box-shadow: 0 18px 44px -18px rgba(40, 20, 90, .45), 0 2px 10px -4px rgba(40, 20, 90, .18);
    animation: zvv-dpick-in .14s ease-out;
}

/* Opened upward where the page has run out of room below — see place(). */
.zvv-dpick.is-up { top: auto; bottom: calc(100% + 8px); }

@keyframes zvv-dpick-in {
    from { opacity: 0; transform: translateY(-4px); }
    to   { opacity: 1; transform: none; }
}

[data-bs-theme="dark"] .zvv-dpick {
    box-shadow: 0 18px 44px -16px rgba(0, 0, 0, .7), 0 2px 10px -4px rgba(0, 0, 0, .5);
}

.zvv-dpick .zvv-acal-head { margin-bottom: 10px; }

/* The month name is the control that opens the month grid, so it has to look
   pressable — but quietly, since it is also the sheet's title. */
.zvv-dpick-title {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 4px 8px;
    margin-left: -8px;
    border: none;
    border-radius: 9px;
    background: none;
    color: var(--zvv-ink, #17123a);
    font-family: inherit;
    font-size: 0.9rem;
    font-weight: 800;
    letter-spacing: -0.01em;
    cursor: pointer;
    transition: background .14s;
}

.zvv-dpick-title i { font-size: 11px; color: var(--acal-pick); }
.zvv-dpick-title:hover { background: color-mix(in srgb, var(--acal-pick) 12%, transparent); }
.zvv-dpick-title:focus-visible { outline: 2px solid var(--acal-pick); outline-offset: 1px; }

/* ── The month grid behind the title ── */

.zvv-dpick-months {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 6px;
}

.zvv-dpick-month {
    padding: 11px 4px;
    border: 1px solid transparent;
    border-radius: 10px;
    background: transparent;
    color: var(--zvv-ink, #17123a);
    font-family: inherit;
    font-size: 0.82rem;
    font-weight: 700;
    cursor: pointer;
    transition: background .12s, color .12s;
}

.zvv-dpick-month:hover:not(:disabled) {
    background: color-mix(in srgb, var(--acal-pick) 14%, transparent);
}

.zvv-dpick-month.is-picked {
    background: var(--acal-pick);
    border-color: var(--acal-pick);
    color: var(--zvv-bg, #fff);
}

.zvv-dpick-month:disabled { opacity: .35; cursor: not-allowed; }
.zvv-dpick-month:focus-visible { outline: 2px solid var(--acal-pick); outline-offset: 1px; }

/* ── Foot ──
   Today and Clear: the two answers that are never worth hunting for in a grid. */
.zvv-dpick-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px solid var(--zvv-line, #e9e6ff);
}

.zvv-dpick-foot button {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    padding: 5px 10px;
    border: none;
    border-radius: 8px;
    background: none;
    color: var(--acal-pick);
    font-family: inherit;
    font-size: 0.78rem;
    font-weight: 700;
    cursor: pointer;
    transition: background .14s;
}

.zvv-dpick-foot button:hover:not(:disabled) {
    background: color-mix(in srgb, var(--acal-pick) 13%, transparent);
}

.zvv-dpick-foot button:disabled { opacity: .4; cursor: not-allowed; }
.zvv-dpick-foot button[hidden] { display: none; }
.zvv-dpick-foot button:focus-visible { outline: 2px solid var(--acal-pick); outline-offset: 1px; }

/* Clear reads as the destructive one of the pair, because it empties a field
   the visitor has already answered. */
.zvv-dpick-foot [data-dpick-clear] { color: var(--zvv-muted, #6b7280); }

.zvv-dpick-foot [data-dpick-clear]:hover {
    background: color-mix(in srgb, var(--drac-red, #dc2626) 12%, transparent);
    color: var(--drac-red, #dc2626);
}

@media (prefers-reduced-motion: reduce) {
    .zvv-dpick { animation: none; }
    .zvv-dpick-caret,
    .zvv-dpick-title,
    .zvv-dpick-month,
    .zvv-dpick-clear,
    .zvv-dpick-foot button { transition: none; }
}
