/* The Scheduling page's Availability tab — every rule the page used to carry
   in its five inline <style> blocks, extracted verbatim (2026-09-03). Loaded
   last in base.html so the cascade order the inline blocks had (after every
   linked sheet) is preserved. Sections below keep the blocks' original order:
   tab toolbar, shared card chrome, the mode-shared body, org mode, personal
   mode. */

/* ── Tab toolbar (bucket picker + mode toggle) ── */
/* Seated in the tab strip's actions slot, so the strip's own card supplies  */
/* the layout box and the gap below it. No margin here: an empty cluster —   */
/* a coordinator with no bucket renders no controls — would otherwise push   */
/* the tab content down for nothing.                                         */
/* `min-width: 0` is the load-bearing line here, not housekeeping. A flex item */
/* defaults to `min-width: auto`, which means it may not shrink below its own  */
/* min-content — so with a 46-character schedule name this cluster measured    */
/* 393px inside a 327px card at 390px, and everything it contains was handed   */
/* that too-wide box. The label's `max-width: 100%` then resolved against 364  */
/* and never ellipsized, and the mode switch painted 52px past the card's      */
/* rounded corner onto the page. Both are the same one refusal to shrink.      */
/* Every box between the card and the text needs this, or the last one in the  */
/* chain is measuring against a lie.                                           */
/* `flex-wrap: wrap` belongs here and not in a media query. It was a phone     */
/* rule until 2026-07-29, so between 576 and 767 — where the cluster has a row */
/* of its own but the card is only 513px wide and the three controls ask for   */
/* 559 — nowrap held, and the picker painted on top of the Personal segment,   */
/* which read "ersonal". Nothing about that band is special; it is just the    */
/* first width where they do not fit, and the same three controls with a long  */
/* name run out of room at other widths too. A row that may wrap has no such   */
/* band: the controls take the next line wherever they stop fitting, and above */
/* that they fit and it never fires.                                           */
.calendar-avail-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--spacing-sm);
    min-width: 0;
}
.calendar-avail-header-bucket-picker {
    position: relative;
    z-index: 1;
    min-width: 0;
}
/* ── Mockup A (2026-07-29): the mode switch rides beside the tabs ──         */
/* Personal|Organization answers "whose schedule am I looking at", which is   */
/* the same question the tabs answer — it belongs with them, not 556px away   */
/* at the other end of the strip with the two controls that ACT on a          */
/* schedule. The cluster keeps its one DOM location and everything below is   */
/* about where that lands on screen; the `min-width: 576px` block further     */
/* down is where the switch is actually put beside the tabs.                  */
/* The seam between "which tab" and "whose schedule". The strip's own 0.75rem */
/* gap already sits to its left, so only the right side needs making up to    */
/* the 12px the mockup asks for — the toolbar's 8px gap does the rest. Above  */
/* 576 the row supplies both sides and takes this margin back off; see there. */
/* Height is the switch's height less 7px of air top and bottom, not a flat   */
/* 22px: on a coarse pointer every control on this row grows to a 44px tap    */
/* target (tokens.css), and a fixed rule would come out half the height of    */
/* the thing it is dividing.                                                  */
.calendar-avail-toolbar__divider {
    flex: 0 0 auto;
    width: 1px;
    height: calc(var(--control-h-base) - 14px);
    margin: 0 0.25rem 0 0;
    background: var(--color-border);
}
.calendar-avail-toolbar__right {
    display: flex;
    align-items: center;
    gap: var(--spacing-md);
    margin-left: auto;
    min-width: 0;
}
/* The picker was the one control on the row with nothing to say it was a     */
/* control: no fill, no icon, a chevron small enough to miss. Next to a       */
/* segmented switch it read as one more segment. A calendar mark names what   */
/* it picks and settles that at a glance.                                     */
.calendar-avail-header-bucket-icon {
    flex-shrink: 0;
    font-size: var(--font-size-sm);
    color: var(--color-text-light);
}
/* One height and one baseline for everything in the cluster. They ran       */
/* 36/28/35px against each other while they were three unrelated controls in */
/* three places; sharing a line makes the mismatch the first thing you see.  */
/* The segmented switch is the third of those three and takes the same       */
/* --control-h-base, but from components/segmented.css now — its strip rule  */
/* covers both scheduling tabs, so naming it again here would be a copy.     */
.calendar-avail-toolbar .calendar-avail-header-add-btn,
.calendar-avail-toolbar .calendar-avail-header-bucket-btn {
    height: var(--control-h-base);
}
.calendar-avail-header-bucket-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    height: 28px;
    padding: 0 0.625rem;
    border-radius: var(--radius-md);
    border: 1px solid var(--color-border);
    background: var(--color-card-bg);
    color: var(--color-text);
    font-size: 0.8125rem;
    font-weight: var(--font-weight-button);
    cursor: pointer;
    white-space: nowrap;
    /* The trigger has to shrink with the box it is in. Only the picker around */
    /* it was shrinkable, so the trigger kept its content width, spilled out   */
    /* of its own parent and — carrying z-index 1 — painted over the New       */
    /* availability button: 49px past the picker at 576 with a 46-character    */
    /* name, 33px of it across the button, taking the `+` with it. The label's */
    /* 120/240px caps do not help, being a ceiling on the text rather than a   */
    /* floor under the row.                                                    */
    max-width: 100%;
    min-width: 0;
    transition: background var(--transition-fast), border-color var(--transition-fast),
                opacity var(--transition-fast);
}
.calendar-avail-header-bucket-btn:hover {
    background: #f1f5f9;
    border-color: #cbd5e1;
}
/* ── Strip with no tabs on it ──                                           */
/* An org without the meetings add-on gets `scheduling_tabs = []`, so the   */
/* card holds this cluster and nothing else. The shell carries no padding   */
/* of its own — a tab's own 0.6rem/0.9rem is what insets the strip — so     */
/* with the tabs gone the controls sat flat against all four card edges.    */
/* Borrow the tab's padding so the lone cluster sits where the first tab    */
/* label would have. Every width: the cluster is the whole card here, so    */
/* there is no wide-screen case where the tabs put it back.                 */
.global-tab-card--row:not(:has(.global-tabs)) .calendar-avail-toolbar {
    padding: 0.6rem 0.9rem;
}
.calendar-avail-header-bucket-chevron {
    width: 0.5rem;
    height: 0.85rem;
    color: #94a3b8;
    transition: transform 0.2s ease;
    flex-shrink: 0;
}
.calendar-avail-header-bucket-chevron.is-open {
    transform: rotate(180deg);
}
.calendar-avail-header-bucket-dropdown {
    position: absolute;
    top: calc(100% + 4px);
    /* The pickers sit at the LEFT edge of the toolbar under the tabs, so
       menus anchor to the trigger's left edge and grow rightward. They
       anchored to the right only while the cluster lived in the header.  */
    left: 0;
    right: auto;
    min-width: 100%;
    /* Clamp width to viewport so a long-named bucket dropdown never bleeds   */
    /* off the screen. 320px ceiling matches Material list width; the calc()  */
    /* floor keeps a 0.75rem gutter on mobile.                                */
    max-width: min(320px, calc(100vw - 1.5rem));
    background: var(--color-card-bg);
    border: 1px solid var(--color-border);
    border-radius: 8px;
    box-shadow: var(--shadow-md);
    overflow: hidden;
    z-index: 100;
}
.calendar-avail-header-bucket-option {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    width: 100%;
    padding: 0.5rem 0.75rem;
    background: transparent;
    border: 0;
    font-size: 0.8125rem;
    font-weight: 500;
    color: #1e293b;
    text-align: left;
    text-decoration: none;
    cursor: pointer;
    transition: background 0.1s ease;
}
.calendar-avail-header-bucket-option:hover {
    background: #f8fafc;
}
.calendar-avail-header-bucket-option.is-selected {
    color: var(--color-action);
    font-weight: 600;
}
.calendar-avail-header-bucket-option i {
    font-size: 0.75rem;
}
/* The one thing on this page that MAKES something, so it is the one filled  */
/* control on the strip. It was a bare circular + until 2026-07-28: grey on  */
/* the page at 2.23:1, brand-colored only once you were already hovering it, */
/* and captioned nowhere — you had to click it to learn what it did.         */
/* Action tokens, never a literal: the same ink fill on every tenant.        */
.calendar-avail-header-add-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0 0.75rem;
    border: 0;
    border-radius: var(--radius-md);
    background: var(--color-action);
    color: var(--color-neutral-ink-fg);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    line-height: 1;
    white-space: nowrap;
    cursor: pointer;
    transition: background var(--transition-fast), opacity var(--transition-fast);
}
.calendar-avail-header-add-btn:hover:not(:disabled) {
    background: var(--color-action-hover);
}
.calendar-avail-header-add-btn:focus-visible {
    outline: 2px solid var(--color-focus-ring);
    outline-offset: 2px;
}
/* At the schedule limit the button stays put and stops working — see the   */
/* tooltip it carries in _availability_header_actions.html.                 */
.calendar-avail-header-add-btn:disabled {
    opacity: 0.55;
    cursor: not-allowed;
}
.calendar-avail-header-add-btn i {
    font-size: 0.875rem;
}
/* Ellipsize the header label on every viewport. A long bucket name like  */
/* "Outdoor Family / Maternity — Half-Day Premium" otherwise stretches    */
/* the trigger button across the whole header and pushes the rest of the */
/* utility bar (mode picker, profile chip) off-screen.                    */
.calendar-avail-header-bucket-label {
    display: inline-block;
    max-width: 240px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: middle;
    /* An ellipsis needs a floor as well as a ceiling. As a flex item of the   */
    /* trigger this span's automatic minimum is its own min-content — the      */
    /* whole name — so the cap above bounds it only while the row is roomy     */
    /* enough not to need one, and the trigger overflowed instead of cutting.  */
    min-width: 0;
}
@media (max-width: 767px) {
    .calendar-avail-header-bucket-label {
        max-width: 120px;
    }
}
/* Constrain option text inside the dropdown too. The dropdown panel is   */
/* clamped at 320px (see .calendar-avail-header-bucket-dropdown above), but the    */
/* option button is display:flex so the bare text node otherwise wraps    */
/* onto multiple lines. min-width:0 on the button lets a single-line      */
/* ellipsis form on the title span without forcing the badge to wrap.    */
.calendar-avail-header-bucket-option {
    min-width: 0;
}
.calendar-avail-header-bucket-option-title {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
    flex: 1 1 auto;
}
/* ── Contrast on the strip ──                                              */
/* Scoped to this page on purpose. The tab and segmented components are     */
/* shared and locked (ADR-125/ADR-131), and their muted grey is legible     */
/* enough on the surfaces they usually sit on; on this strip the two land   */
/* side by side and both read as disabled. Fixing them platform-wide is a   */
/* design review of every page that mounts them, not a line in this file.   */

/* The segmented half of that is no longer here: the Meetings tab had grown */
/* a hand-copy of it, so both moved to components/segmented.css under       */
/* `.global-tab-card__actions` — the actions cluster of a tab strip, which  */
/* is the surface the contrast argument is actually about. That widens the  */
/* rule to any segmented control seated in a strip, and to nothing else.    */
/* The tab half below stays page-scoped: `.global-tab` mounts on strips     */
/* this argument has not been made for.                                     */

/* 2.54:1 for the tab you are not on. The live tab has to be excluded by    */
/* hand, and the hover darkening restated, for the same reason: this block  */
/* is inline and comes after the stylesheet, so at equal specificity it     */
/* would otherwise take the colour off the tab you are standing on.         */
.global-tab-card--row:has(.calendar-avail-toolbar) .global-tab:not(.is-active) {
    color: var(--color-grey-700);
}
.global-tab-card--row:has(.calendar-avail-toolbar) .global-tab:not(.is-active):hover {
    color: var(--color-text);
}
/* ── Narrow desktop: the schedule PAIR takes a row of its own ──           */
/* One DOM location, wrapped — not a second copy of the controls for small  */
/* screens. Two copies means two ids, two Alpine scopes and two things to   */
/* keep in step, and the picker carries an id the rename endpoint swaps.    */
/*                                                                          */
/* What drops is the pair that acts on a schedule, not the switch. The      */
/* switch answers the same question the tabs do (mockup A), so it holds its */
/* place beside them, hairline included, for as long as it fits: tabs ask   */
/* 204px and the switch 246, 463 with the seam, against the 513px card a    */
/* 576px viewport draws. Sending the whole cluster down instead — which is  */
/* what this block did until 2026-07-29 — left the tabs alone on a row with */
/* 309px of nothing beside them and made the page three rows deep.          */
/*                                                                          */
/* Below 576 the phone block takes over and stacks all three; above 991 the */
/* strip has ~724px free and the whole cluster asks ~446, so it all sits on */
/* one line and this never fires.                                           */
@media (max-width: 991.98px) {
    /* Full basis, so the pair takes a line of its own and the switch is left */
    /* on the tabs'. That line is then the row's full width, so the pair also */
    /* needs telling to sit at the far end of it — its auto margin only       */
    /* reaches the free space on a line it shares with something, and here it */
    /* shares with nothing. Measured 2026-07-29: removing the alignment costs */
    /* 23px at 768 and 246px at 991, and is the one width-dependent thing on  */
    /* this rule — at 576 the pair fills its line and there is nothing to     */
    /* align.                                                                 */
    .calendar-avail-toolbar .calendar-avail-toolbar__right {
        flex: 1 1 100%;
        justify-content: flex-end;
    }
}
/* ── Above the phone stack, the cluster is not a box ──                     */
/* The card row centres its children against each other. A cluster that has  */
/* wrapped is an 80px box, so the 41px tab strip centred against the whole   */
/* of it and came out 22px BELOW the switch — straddling both of the         */
/* cluster's rows, 16px into each, with the hairline drawn beside the switch */
/* instead of beside the tab labels it divides. Nothing inside either box    */
/* was misaligned. The problem was that they were two boxes, and it showed   */
/* at every width where the cluster wrapped: 576 to 991, pushed 1200 and     */
/* 1440, and 992 itself once a schedule name is long enough to wrap it.      */
/*                                                                           */
/* So the cluster stops being a box. `display: contents` hands its children  */
/* to the card row, which makes the tabs, the hairline and the switch three  */
/* items of ONE flex line, centred by the same `align-items` the strip has   */
/* always had — measured at 0px stagger, the same as the single-row layout   */
/* it now matches at every width. The card row does the wrapping and takes   */
/* over the 0.9rem right inset that went with the cluster's own box.         */
/*                                                                           */
/* `justify-content` has to be restated: the row's shipped `space-between`   */
/* is inert while a full-width cluster is the only thing beside the tabs,    */
/* and would spread the tabs, hairline and switch across the line the moment */
/* they became separate items of it.                                         */
/*                                                                           */
/* Not on a phone: down there all three stack and the cluster's box is what  */
/* holds them, with its own inset and its own bottom padding.                */
/*                                                                           */
/* And not on a card with no tabs on it (the no-meetings-add-on org, above).  */
/* There is nothing for the cluster to align WITH there, and its box is the   */
/* only thing holding the padding that keeps those controls off the card's    */
/* edges — dissolving it would push them flat against all four.               */
@media (min-width: 576px) {
    .global-tab-card--row:has(.global-tabs) > .calendar-avail-toolbar {
        display: contents;
    }
    .global-tab-card--row:has(.global-tabs):has(.calendar-avail-toolbar) {
        flex-wrap: wrap;
        row-gap: var(--spacing-sm);
        justify-content: flex-start;
        padding-right: 0.9rem;
    }
    /* Both sides of the seam are the row's 0.75rem gap now. The hairline's own */
    /* right margin exists to make the toolbar's narrower 8px gap up to 12, and */
    /* on the row it lands on top of a gap that is already 12 — measured as a   */
    /* 12/16 seam, leaning right.                                               */
    .global-tab-card--row:has(.global-tabs) .calendar-avail-toolbar__divider {
        margin-right: 0;
    }
}
/* ── Phone toolbar: stack it into two rows ──                             */
/* These controls used to sit in the page header, and this block used to   */
/* stack them there. They live in the toolbar now, so every rule below     */
/* names the toolbar — pointed at the header they would either miss        */
/* entirely or move the wrong thing.                                       */
/* On one row they run past a 390px screen: the row does not wrap and a    */
/* bucket name is a nowrap span, so the picker keeps the full width of its */
/* text and pushes the mode switch off the right edge, where it cannot be  */
/* reached at all. Rows here:                                              */
/*   1. New availability and the schedule picker, which takes the rest     */
/*   2. the Personal | Organization switch, full width                     */
/* The label needs a cap of its own: an ellipsis only forms when something */
/* bounds the text, and every box between it and the row can still grow    */
/* unless each one is told it may shrink.                                  */
/* The tab strip needs no rule of its own: a cluster with a 100% basis      */
/* cannot share the tabs' line, so the tabs keep the first row by default.  */
@media (max-width: 575px) {
    /* The one width where the strip has to break: a 100%-basis cluster is    */
    /* the only thing that cannot share the tabs' line, and without this the  */
    /* row holds it there anyway — measured at 390 as the tabs crushed to     */
    /* 116px and the switch painting 28px past the card's right edge.         */
    .global-tab-card--row:has(.calendar-avail-toolbar) {
        flex-wrap: wrap;
    }
    /* The whole cluster comes down here, switch included — 204px of tabs    */
    /* plus a 246px switch does not fit a 342px card, and the switch is the  */
    /* one of the three that has somewhere else to be. Inset to the first    */
    /* tab label's own 0.9rem, and air below so the last row is not flush    */
    /* against the card's bottom edge.                                       */
    .global-tab-card--row .calendar-avail-toolbar {
        flex: 1 1 100%;
        padding-left: 0.9rem;
        padding-bottom: 0.75rem;
    }
    /* A hairline between the tabs and the switch says something only while  */
    /* they share a line. Down here the switch leads a row of its own with   */
    /* nothing to its left to be divided from.                              */
    .global-tab-card--row .calendar-avail-toolbar__divider {
        display: none;
    }
    .calendar-avail-toolbar .calendar-avail-header-bucket-picker {
        flex: 1 1 auto;
    }
    .calendar-avail-toolbar .calendar-avail-header-bucket-btn {
        width: 100%;
        min-width: 0;
        justify-content: space-between;
    }
    .calendar-avail-toolbar .calendar-avail-header-bucket-label {
        max-width: 100%;
        min-width: 0;
        flex: 1 1 auto;
    }
    /* The trigger is full width here, so the menu matches it edge to edge —   */
    /* right-anchored at a 320px cap it would start mid-button.                */
    .calendar-avail-toolbar .calendar-avail-header-bucket-dropdown {
        left: 0;
        right: 0;
        max-width: none;
    }
    /* Scoped to this toolbar on purpose: .global-segmented is a locked shared */
    /* component (ADR-125 singleton gate), so only the copy inside the         */
    /* availability toolbar moves to its own row.                             */
    .calendar-avail-toolbar .global-segmented {
        flex: 0 0 100%;
    }
    /* The two rows a phone has always had, in the order it has always had     */
    /* them: the schedule and the way to add one first, the mode switch under  */
    /* them. Mockup A puts the switch FIRST in source so it can sit beside the */
    /* tabs on a wide screen; `order` is what keeps that from reshuffling the  */
    /* phone, which never shares a line with the tabs at all.                  */
    .calendar-avail-toolbar .calendar-avail-toolbar__right {
        order: -1;
        flex: 1 1 100%;
        gap: var(--spacing-sm);
    }
}

.calendar-avail-preview-card.calendar-avail-personal-card {
    padding: 1rem 1.25rem 0.5rem;
}
.calendar-avail-personal-card .calendar-avail-personal-card-header,
.calendar-avail-personal-card .card-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    background: transparent;
    border: 0;
    border-bottom: 1px solid #f1f5f9;
    padding: 0.25rem 0 0.875rem 0;
    margin: 0 0 1rem 0;
}
.calendar-avail-personal-card .calendar-avail-personal-card-title,
.calendar-avail-personal-card .card-header h5 {
    font-size: 0.95rem;
    font-weight: 600;
    color: #111;
    margin: 0;
    letter-spacing: -0.01em;
}
/* The autosave status rides the right end of the working-hours header, beside */
/* the title. min-width keeps "Saving…" and "Saved" from resizing the row as   */
/* they swap; it is the only element in the header whose text changes.         */
.calendar-avail-personal-card .calendar-avail-hours-status {
    min-width: 90px;
    text-align: right;
}
.calendar-avail-personal-card .card-body {
    padding: 0;
}
.calendar-avail-personal-card .calendar-avail-disabled-banner {
    background: #fef3c7;
    border: 1px solid #fde68a;
    border-radius: 0.5rem;
    padding: 0.625rem 0.875rem;
    font-size: 0.8125rem;
    color: #78350f;
}
/* ── What each of the three cards is FOR (2026-08-19) ──────────────────────  */
/* The trio is an equation, not three peer settings: working hours ADD time,   */
/* connected calendars SUBTRACT it, exceptions OVERRIDE it. Equal thirds at    */
/* one height cannot say that on their own, so each card says it in one line   */
/* under its own title, and the page stops needing somebody to explain it.     */
.calendar-avail-settings-trio .calendar-avail-personal-card-header {
    /* The hint takes a row of its own, under the title and its buttons. */
    flex-wrap: wrap;
}
.calendar-avail-card-hint {
    flex: 0 0 100%;
    margin: 0;
    font-size: var(--font-size-sm);
    line-height: 1.35;
    color: var(--color-text-secondary);
}

/* ── Bucket panel + timing stepper + service-type chip chrome (both modes) ── */
/* ── Settings band — every control for the selected schedule, on the page ──  */
/*                                                                            */
/* Until 2026-08-18 this card was a summary of the settings and a gear that    */
/* opened them in a drawer. Now the settings show all the time. The            */
/* summary chrome that described them (the hours strip, the read-only chips,   */
/* the gear's focus ring) went with the drawer — everything it reported is on  */
/* screen.                                                                    */
/*                                                                            */
/* Round 10 (2026-08-19) split it in two: the name and location sit in the top */
/* section on the left, with a delete icon on the right. Below that, the       */
/* min/max notice and timezone take the left third of the row, and the service */
/* types take the right two-thirds.                                            */
/*                                                                            */
/* So a full-width top row, then a 1/3 : 2/3 row under it. The lower row still  */
/* has one fixed height set by its left column, and the service-type list takes */
/* that height and scrolls inside it. The band still cannot grow: add a field   */
/* to the left and the list gets shorter, which is the trade on purpose.       */
#bucket-settings-band {
    /* One height for every control in here. This card had four — a 28px name  */
    /* field, 31px comboboxes, 30px stepper parts and a 32px timezone select — */
    /* which read as four different kinds of control rather than one form.     */
    --settings-control-h: 34px;
    /* Two widths that used to be "whatever is left in the column", which is   */
    /* how a three-letter unit ended up in a 348px dropdown. Both are sized by */
    /* their longest content instead: "minutes" for the unit, an American time */
    /* zone name for the picker. Both may shrink in a narrow column; neither   */
    /* may grow.                                                               */
    --settings-unit-w: 4.75rem;
    --settings-tz-w: 17rem;
}
/* Name, location, delete. Capped, not fluid: the name and location fields do   */
/* not need to be excessively long — a name is a handful of words and an        */
/* address one line, so a field spanning half the band only advertises room     */
/* nobody needs. The third track is the slack that pushes delete right.         */
/* align-items: end so the icon sits on the field baseline, not on the labels.  */
.scheduling-bucket-settings-band__top {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1.125rem;
    align-items: end;
    padding-bottom: 1.125rem;
    margin-bottom: 1.125rem;
    border-bottom: 1px solid var(--color-grey-200);
}
@media (min-width: 768px) {
    .scheduling-bucket-settings-band__top {
        grid-template-columns: minmax(0, 18rem) minmax(0, 24rem) 1fr;
    }
}
/* The gap between the rows already separates these, so the per-group margin    */
/* that spaces a stacked column would double it.                               */
#bucket-settings-band .scheduling-bucket-settings-band__top .scheduling-bucket-settings-band__group {
    margin-bottom: 0;
    min-width: 0;
}
.scheduling-bucket-settings-band__group--name,
.scheduling-bucket-settings-band__group--location {
    min-width: 0;
}
.scheduling-bucket-settings-band__del {
    justify-self: end;
}
/* A Virtual schedule's top row carries the name and nothing else, so it takes */
/* the name track alone rather than reserving the location and delete tracks   */
/* beside it.                                                                  */
.scheduling-bucket-settings-band__top--name-only {
    grid-template-columns: minmax(0, 18rem);
}
/* Read-only name (Virtual). Grey fill and a no-entry cursor so it reads as a  */
/* value being reported, not a field waiting to be typed in — the meetings     */
/* add-on owns this name and nothing on this page may change it.               */
#bucket-settings-band .form-control[readonly] {
    background: var(--color-grey-50);
    color: var(--color-text-secondary);
    cursor: not-allowed;
}
.scheduling-bucket-settings-band__cols {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0 1.875rem;
}
/* A Virtual schedule has notice and time zone and nothing else — no service   */
/* types to put beside them. One 1fr track let the pair stretch the full band, */
/* and because the unit select takes a stepper's slack (see __unit below) that */
/* landed as two dropdowns the width of the page (2026-08-19). Capping the     */
/* track is the fix: the column is the same width it is in every other band,   */
/* with empty space beside it instead of stretched controls inside it.         */
.scheduling-bucket-settings-band__cols--single {
    grid-template-columns: minmax(0, 30rem);
}
@media (min-width: 992px) {
    .scheduling-bucket-settings-band__cols {
        /* ~1/3 notice + time zone, ~2/3 service types. minmax(0, …) on both   */
        /* because a grid item defaults to min-width: auto — one long time-zone */
        /* name would otherwise widen the left track past its share.           */
        grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
        /* The row is as tall as the left column, and the right column is       */
        /* stretched to match it. See __scrollhost for why the list itself      */
        /* contributes nothing to that measurement.                             */
        align-items: stretch;
    }
    .scheduling-bucket-settings-band__cols--single {
        grid-template-columns: minmax(0, 30rem);
    }
}
/* Section headers step back. At 12px/700 they were competing with the field   */
/* labels under them for the same job; quiet and small says "this is a         */
/* heading" without shouting it.                                              */
#bucket-settings-band .scheduling-bucket-settings-band__label {
    display: block;
    margin-bottom: 0.35rem;
    font-size: 11px;
    font-weight: var(--font-weight-medium);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--color-grey-600);
}
#bucket-settings-band .scheduling-bucket-settings-band__group {
    margin-bottom: 1.25rem;
}
/* The card's own bottom padding closes the band, so the last field does not   */
/* carry a margin of its own.                                                 */
#bucket-settings-band .scheduling-bucket-settings-band__group:last-child {
    margin-bottom: 0;
}

/* ── One control height ──────────────────────────────────────────────────── */
/* The name field, both comboboxes (location, time zone), and every piece of   */
/* both steppers.                                                             */
/*                                                                            */
/* A fixed height is right for a control that holds one line and wrong for one */
/* that holds several, and this band renders from two templates (personal and  */
/* org) — so the day a textarea lands in the org body, this would crush it to  */
/* a single line. Name the one element that must never take the height rather  */
/* than trusting whoever adds it to notice.                                    */
#bucket-settings-band .form-control:not(textarea),
#bucket-settings-band .global-cs-input,
#bucket-settings-band .scheduling-bucket-timing-stepper,
#bucket-settings-band .scheduling-bucket-timing-stepper__btn,
#bucket-settings-band .scheduling-bucket-timing-stepper__input,
#bucket-settings-band .scheduling-bucket-timing-stepper__unit {
    height: var(--settings-control-h);
}
#bucket-settings-band .scheduling-bucket-timing-stepper__btn {
    width: var(--settings-control-h);
}

/* Field labels — the two inside the Notice row and the time zone's. Ink, so   */
/* they read as the name of the thing you are about to set, not as chrome.     */
#bucket-settings-band .scheduling-bucket-timing-field__label,
#bucket-settings-band .scheduling-bucket-settings-band__field-label {
    font-size: 13px;
    font-weight: var(--font-weight-medium);
    color: var(--color-text);
}

/* The two steppers end on the same right edge and neither is wider than the   */
/* words in it (2026-08-19: the min/max and notice dropdowns were still much   */
/* too wide and looked out of place).                                          */
/*                                                                             */
/* They got that way honestly: each stepper is inline-flex at its own          */
/* intrinsic width, "min/hr/day/wk" and "day/wk/mo" are different widths, so   */
/* the two ended short of their columns by different amounts and the fix was   */
/* to fill the column and hand the slack to the unit select. That lands both   */
/* edges on one line, but the line is the column's — 348px of dropdown around  */
/* the word "day" at 1920. Fixing the select's width instead gets the same     */
/* two equal steppers out of the widest word either list holds, and the band   */
/* can be as wide as it likes without the controls following it.               */
#bucket-settings-band .scheduling-bucket-timing-stepper {
    display: flex;
    width: auto;
}
#bucket-settings-band .scheduling-bucket-timing-stepper__unit {
    flex: 0 1 var(--settings-unit-w);
    width: var(--settings-unit-w);
    min-width: 0;
}

/* "Add a location" is the only way forward when a worker has no addresses     */
/* yet, and it was dressed as a disabled input — grey fill, input border,      */
/* muted text. A dashed add button says the same thing the dashed             */
/* service-type chips already say on this page: nothing here yet, this is      */
/* where you add it.                                                          */
#bucket-settings-band .scheduling-bucket-settings-band__add {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.375rem;
    width: 100%;
    height: var(--settings-control-h);
    padding: 0 0.75rem;
    border: 1.5px dashed var(--color-grey-400);
    border-radius: var(--radius-md);
    background: transparent;
    color: var(--color-text);
    font-size: var(--font-size-sm);
    text-decoration: none;
}
#bucket-settings-band .scheduling-bucket-settings-band__add:hover {
    border-color: var(--color-action);
    color: var(--color-text);
}
#bucket-settings-band .scheduling-bucket-settings-band__add:focus-visible {
    outline: 2px solid var(--color-focus-ring);
    outline-offset: 2px;
}

/* A locked chip has to stay readable — it is the one chip carrying a tooltip  */
/* you are meant to go read. #94a3b8 on the muted fill was 2.34:1; the grey    */
/* token is 5.2:1 and still clearly the quiet chip. Muting stays on color,     */
/* never opacity: opacity here would composite the data-tooltip bubble along   */
/* with it (2026-07-02).                                                      */
#bucket-settings-band .scheduling-service-type-chip--used-elsewhere,
#bucket-settings-band .scheduling-service-type-chip.is-used-elsewhere {
    color: var(--color-grey-600);
}

/* ── The service-type column ─────────────────────────────────────────────── */
/* Label on top, list under it taking whatever is left.                       */
/* A grid item defaults to min-width: auto, which is "never shrink below your  */
/* content" — one long location label or time-zone name would push the column  */
/* past its 1fr and take the row with it.                                     */
.scheduling-bucket-settings-band__col {
    min-width: 0;
}
/* The notice/time-zone column measures itself so the time-zone row knows when */
/* it has run out of room for a label beside the control. The list column is   */
/* left out on purpose: `container-type` brings layout containment with it,    */
/* and that column's whole trick is an absolutely positioned list that reports */
/* no height (see __scrollhost).                                               */
.scheduling-bucket-settings-band__col:not(.scheduling-bucket-settings-band__col--fill) {
    container: settings-col / inline-size;
}
/* Under ~330px of column the label and a readable zone name no longer fit on  */
/* one line, and the name is the half that would lose — "Central Time (Chicag… */
/* So the label steps back above the control, which is the shape this row had  */
/* everywhere before. Side by side is the ask; unreadable is not.              */
@container settings-col (max-width: 330px) {
    .scheduling-bucket-settings-band__group--tz {
        flex-wrap: wrap;
        gap: 0.35rem 0.625rem;
    }
    .scheduling-bucket-settings-band__group--tz form {
        flex: 1 1 100%;
    }
}
.scheduling-bucket-settings-band__col--fill {
    display: grid;
    grid-template-rows: auto minmax(0, 1fr);
    min-height: 0;
}
/* The list is absolutely positioned inside here, which is the whole trick: an */
/* absolute child contributes nothing to its parent's height, so this column   */
/* never argues with the left one about how tall the row should be. The left   */
/* column wins by default and the list takes what that leaves. Position it     */
/* statically and a long list would make the band as tall as itself.          */
.scheduling-bucket-settings-band__scrollhost {
    position: relative;
    min-height: 0;
}
.scheduling-bucket-settings-band__scroll {
    position: absolute;
    inset: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    /* The chevrons and the fade are the affordance — hide the native bar. */
    scrollbar-width: none;
    -ms-overflow-style: none;
    /* Per-edge fade depth, raised by the --fade-* classes (bound to the same  */
    /* Alpine state as the chevrons). Kept at 0 here so a fully-scrolled edge  */
    /* renders crisp to the card boundary.                                     */
    --band-fade-top: 0rem;
    --band-fade-bottom: 0rem;
}
.scheduling-bucket-settings-band__scroll::-webkit-scrollbar {
    display: none;
}
/* Overflow fade — a mask on the scroll cell, not a wash painted over it. The  */
/* same treatment the signup role cards use, for the reason given there        */
/* (08-17, twice): a white scrim sits ON TOP of clipped text, so however eased */
/* its ramp is, its outer edge always meets full-strength letters in a visible */
/* line. Masking makes the chips themselves dissolve into the card: there is   */
/* no painted layer to end anywhere. The -webkit- copy is the same ramp        */
/* verbatim (Safari before 15.4 knows only the prefixed property) — edit the   */
/* two together or the mask layers drift.                                      */
.scheduling-bucket-settings-band__scroll--fade-top,
.scheduling-bucket-settings-band__scroll--fade-bottom,
.calendar-avail-card-scroll--fade-top,
.calendar-avail-card-scroll--fade-bottom {
    -webkit-mask-image: linear-gradient(
        to bottom,
        transparent,
        rgba(0, 0, 0, 0.3) calc(var(--band-fade-top) * 0.35),
        rgba(0, 0, 0, 0.75) calc(var(--band-fade-top) * 0.7),
        rgba(0, 0, 0, 0.95) calc(var(--band-fade-top) * 0.88),
        black var(--band-fade-top),
        black calc(100% - var(--band-fade-bottom)),
        rgba(0, 0, 0, 0.95) calc(100% - var(--band-fade-bottom) * 0.88),
        rgba(0, 0, 0, 0.75) calc(100% - var(--band-fade-bottom) * 0.7),
        rgba(0, 0, 0, 0.3) calc(100% - var(--band-fade-bottom) * 0.35),
        transparent
    );
    mask-image: linear-gradient(
        to bottom,
        transparent,
        rgba(0, 0, 0, 0.3) calc(var(--band-fade-top) * 0.35),
        rgba(0, 0, 0, 0.75) calc(var(--band-fade-top) * 0.7),
        rgba(0, 0, 0, 0.95) calc(var(--band-fade-top) * 0.88),
        black var(--band-fade-top),
        black calc(100% - var(--band-fade-bottom)),
        rgba(0, 0, 0, 0.95) calc(100% - var(--band-fade-bottom) * 0.88),
        rgba(0, 0, 0, 0.75) calc(100% - var(--band-fade-bottom) * 0.7),
        rgba(0, 0, 0, 0.3) calc(100% - var(--band-fade-bottom) * 0.35),
        transparent
    );
}
.scheduling-bucket-settings-band__scroll--fade-top,
.calendar-avail-card-scroll--fade-top {
    --band-fade-top: 0.75rem;
}
.scheduling-bucket-settings-band__scroll--fade-bottom,
.calendar-avail-card-scroll--fade-bottom {
    --band-fade-bottom: 0.75rem;
}
/* Hover-scroll chevrons — shown (via x-show) only when the chips overflow.    */
/* The "scroll for more" affordance is the mask fade; the chevron just names   */
/* the direction. A sliver, so the chips run almost to the cell's edges, and   */
/* no background: the mask already dissolves what sits under it, and any       */
/* painted wash here would put back the cutoff line the mask removed.          */
.scheduling-bucket-settings-band__scroll-arrow {
    position: absolute;
    left: 0;
    right: 0;
    height: 0.5rem;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 0;
    background: none;
    cursor: pointer;
    color: var(--color-action);
    /* Below the type scale on purpose — the chevron is an ornament, not text, */
    /* and must fit inside the 0.5rem sliver without spilling onto the chips.  */
    font-size: 0.5rem;
    opacity: 0.75;
    z-index: var(--z-raised);
    transition: opacity var(--transition-fast, 0.15s);
}
.scheduling-bucket-settings-band__scroll-arrow:hover {
    opacity: 1;
}
.scheduling-bucket-settings-band__scroll-arrow--up {
    top: 0;
}
.scheduling-bucket-settings-band__scroll-arrow--down {
    bottom: 0;
}
/* ── Connected calendars + exceptions scroll inside their own card ─────────  */
/* Same treatment as the band directly above them, deliberately: one scroll    */
/* idiom on the page, not two. Only the sizing differs, and only in where the  */
/* height comes from: the band's cell takes it from the left column beside it, */
/* a card's list takes it from the working-hours card across the row.          */
/*                                                                            */
/* Either way the point is that a list never sets a height. Left to grow, the  */
/* trio is as tall as whichever list is fullest, so a worker with thirty       */
/* exceptions pushes the live preview — the one thing that tells them the      */
/* change took — off the bottom of the screen. That fails worst for the most   */
/* complicated schedules, which is exactly backwards.                          */
/*                                                                            */
/* No chevron slivers here, unlike the band: those exist because the chips are */
/* a hover-scroll strip with no other way to move, while a list under the      */
/* pointer already scrolls on the wheel. hoverScroll is still what drives the  */
/* fade — its observers are what notice a list growing or emptying.            */
.calendar-avail-card-scrollhost {
    position: relative;
    min-height: 0;
}
.calendar-avail-card-scroll {
    overflow-y: auto;
    /* A capped list inside a scrolling page: stop at its own end rather than  */
    /* handing the rest of the gesture to the page behind it.                  */
    overscroll-behavior: contain;
    /* The mask fade is the affordance — hide the native bar, as the band does. */
    scrollbar-width: none;
    -ms-overflow-style: none;
    --band-fade-top: 0rem;
    --band-fade-bottom: 0rem;
}
.calendar-avail-card-scroll::-webkit-scrollbar {
    display: none;
}
/* Three across, one height. Each card is a flex column and each list is a     */
/* flex item with a ZERO basis, so a list contributes nothing to how tall its  */
/* card wants to be: the row is as tall as working hours (seven day rows,      */
/* never an eighth) and both lists take exactly what that leaves.              */
/*                                                                            */
/* This replaces a 20rem cap, which could not do the job from either side. Any */
/* cap is a guess at a height the row has not been asked for yet: 20rem was    */
/* TALLER than the row, so expanding a calendar account grew the card, the     */
/* trio, and the page under it — this was caught in review (2026-08-19: the    */
/* calendar container should not expand in size when the collapsables are      */
/* expanded, it should just scroll cleanly) — and a cap short enough to never  */
/* do that would end every card in dead space instead. Deriving the height     */
/* from the row is the only version with no wrong number in it.                */
/*                                                                            */
/* Stacked (below 992) the cards are full width with nothing beside them to    */
/* stay level with, so the lists go back to their natural height rather than   */
/* becoming scroll boxes inside a scrolling page.                              */
@media (min-width: 992px) {
    .calendar-avail-settings-trio > .calendar-avail-preview-card {
        display: flex;
        flex-direction: column;
    }
    /* The calendars card wraps its header and its list in an HTMX swap target */
    /* (#connected-calendars-card), so the flex chain has to pass THROUGH that */
    /* wrapper — otherwise the list inside measures against a box that never   */
    /* received the row's height.                                              */
    .calendar-avail-settings-trio .calendar-avail-preview-card #connected-calendars-card {
        display: flex;
        flex-direction: column;
        flex: 1 1 0;
        min-height: 0;
    }
    /* Three classes deep on purpose: the org exceptions host also wears       */
    /* `.settings-panel.is-active`, whose `display: block` matches at the same */
    /* weight from a stylesheet we do not control the order of.                */
    .calendar-avail-settings-trio .calendar-avail-preview-card .calendar-avail-card-scrollhost {
        display: flex;
        flex-direction: column;
        flex: 1 1 0;
        min-height: 0;
    }
    .calendar-avail-settings-trio .calendar-avail-preview-card .calendar-avail-card-scroll {
        flex: 1 1 0;
        min-height: 0;
    }
}
/* Stacked, the list has no left column to take its height from, so it goes    */
/* back to sizing itself and caps instead.                                     */
@media (max-width: 991.98px) {
    .scheduling-bucket-settings-band__col--fill {
        display: block;
        margin-top: 1.25rem;
    }
    .scheduling-bucket-settings-band__scroll {
        position: static;
        max-height: 16rem;
    }
}
/* Bootstrap Icons paint their ink high inside the em box (the library ships   */
/* ::before { vertical-align: -.125em } to compensate in text flow), so        */
/* em-box centering (display:block + line-height:1) still leaves the glyph     */
/* ~1px high. Flex-centering the ::before box centers the ink itself.          */
.calendar-bucket-panel__settings-btn i {
    display: flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
    font-size: 1rem;
}
/* ── Bucket panel ── */
/* Notice row: two timing steppers (min + max notice) side-by-side in the      */
/* settings band. Grid 1fr 1fr guarantees equal column widths so the steppers  */
/* visually align regardless of unit-label width (min/hr/day vs day/wk/mo).    */
/* Two rows, name on the left and the stepper beside it. Round 10 gave this     */
/* pair a third of the band instead of a half, which is too narrow to sit them  */
/* side by side; stacking them also drops the labels from their own line, so    */
/* the pair takes about the height it did across two columns.                   */
/*                                                                            */
/* The label track is fixed rather than auto so both steppers start at the same */
/* x — ragged left edges were the reason the drawer version read as two         */
/* unrelated controls. Nothing here lets a stepper stretch: the stepper is      */
/* inline-flex and sized by its parts (08-18: keep them from ballooning).       */
.scheduling-bucket-settings-band__notice-row {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}
.scheduling-bucket-settings-band__notice-row .scheduling-bucket-timing-field {
    flex-direction: row;
    align-items: center;
    gap: 0.625rem;
}
.scheduling-bucket-settings-band__notice-row .scheduling-bucket-timing-field__label {
    flex: 0 0 5.5rem;
    margin: 0;
    font-size: var(--font-size-sm);
}

/* Two-step delete, round 10: a trash icon at the end of the band's top row     */
/* that opens a small confirm anchored under it — still no browser popup. An    */
/* icon has no room to relabel itself the way the old full-width button did     */
/* ("Delete availability" → "Are you sure?"), and a bare icon that deletes on   */
/* two quick clicks is the one control here where a slip costs a whole          */
/* availability.                                                                */
/*                                                                            */
/* The popover is absolute so opening it cannot reflow the row it hangs off,    */
/* and right-anchored so it opens inward from the band's edge instead of off    */
/* the card.                                                                    */
.calendar-bucket-panel__delete-area {
    position: relative;
}
.calendar-bucket-panel__delete-confirm {
    position: absolute;
    top: calc(100% + 0.5rem);
    right: 0;
    z-index: var(--z-dropdown);
    width: 17rem;
    display: flex;
    flex-direction: column;
    gap: 0.625rem;
    padding: 0.75rem;
    background: var(--color-card-bg);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-menu);
    text-align: left;
}
.calendar-bucket-panel__delete-confirm-copy {
    font-size: 0.875rem;
    color: var(--color-error);
}
.calendar-bucket-panel__delete-confirm-actions {
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
}
/* Time zone is one more row of the same form: its label sits to the left of   */
/* the control, on the track the Min/Max Notice labels use, and the control is */
/* only as wide as a time-zone name (2026-08-19: the timezone label should sit */
/* to the left of the dropdown so the dropdown itself can be narrower). It was */
/* a stacked label over a dropdown as wide as the column —                     */
/* 576px at 1920 for a line of text a third of that.                           */
.scheduling-bucket-settings-band__group--tz {
    display: flex;
    align-items: center;
    gap: 0.625rem;
}
#bucket-settings-band .scheduling-bucket-settings-band__group--tz .scheduling-bucket-settings-band__field-label {
    flex: 0 0 5.5rem;
    margin: 0;
}
/* The form is the control's box here — the combobox fills it, so capping the  */
/* form is what makes the dropdown skinny. It shrinks with a narrow column and */
/* never grows past a zone name.                                               */
.scheduling-bucket-settings-band__group--tz form {
    flex: 0 1 var(--settings-tz-w);
    min-width: 0;
}
/* Save tell beside the settings band's time zone dropdown. */
.scheduling-bucket-settings-band__tz-inline-status {
    min-width: 18px;
}
/* Square, one control height, so it lines up with the name and location fields */
/* it shares the row with. Danger lives in the glyph, not in a filled button —  */
/* a solid red square at the top of the page would read as an alert.            */
.calendar-bucket-panel__delete-btn-cta {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--settings-control-h);
    height: var(--settings-control-h);
    padding: 0;
    background: var(--color-card-bg);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    color: var(--color-error);
    line-height: 1;
}
.calendar-bucket-panel__delete-btn-cta:hover,
.calendar-bucket-panel__delete-btn-cta[aria-expanded="true"] {
    background: var(--color-grey-100);
    border-color: var(--color-grey-300);
}
/* Small square icon button — the Exceptions "add" and the connected-calendars */
/* controls. Mirrors the brand-tab logos-panel "+" button: hover swaps to      */
/* brand-primary bg/fg; the open tell is that color holding (no rotation —     */
/* 2026-07-02: it must not spin). 140ms easing matches that component so       */
/* the muscle-memory across pages stays consistent.                            */
.calendar-bucket-panel__settings-btn {
    appearance: none;
    background: var(--color-card-bg);
    border: 1px solid var(--color-border-hairline);
    border-radius: var(--radius-md);
    color: var(--color-text-secondary);
    font-size: var(--font-size-sm);
    line-height: 1;
    width: 1.75rem;
    height: 1.75rem;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background 140ms ease, color 140ms ease, border-color 140ms ease;
}
/* A dead control (aria-disabled, the "+" at the account cap) keeps the      */
/* pointer for its tooltip but must not light up under it.                    */
.calendar-bucket-panel__settings-btn:not([aria-disabled="true"]):hover,
.calendar-bucket-panel__settings-btn:not([aria-disabled="true"]):focus-visible {
    background: var(--color-action);
    color: var(--color-neutral-ink-fg);
    border-color: var(--color-action);
}
/* Keyboard focus gets the house ring on top of the fill, like global-icon-btn. */
.calendar-bucket-panel__settings-btn:not([aria-disabled="true"]):focus-visible {
    outline: 2px solid var(--color-focus-ring);
    outline-offset: 2px;
}
.calendar-bucket-panel__settings-btn[aria-expanded="true"] {
    /* Open tell is color only — no rotation anywhere (2026-07-02: it        */
    /* must not spin), and no transform on the button (it would drag the      */
    /* ::before/::after tooltip pseudo-elements along and tilt the tooltip).  */
    background: var(--color-action);
    color: var(--color-neutral-ink-fg);
    border-color: var(--color-action);
}
.calendar-bucket-panel__settings-btn[data-tooltip=""]::before,
.calendar-bucket-panel__settings-btn[data-tooltip=""]::after {
    display: none !important;
}
/* Sync-in-progress: the refresh arrow rotates in place at a calm, steady    */
/* pace. linear keeps the loop seamless (no pulse at the cycle boundary).     */
.calendar-bucket-panel__settings-btn .calendar-sync-spin {
    animation: bucket-sync-spin 0.8s linear infinite;
}
@keyframes bucket-sync-spin {
    to { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
    .calendar-bucket-panel__settings-btn .calendar-sync-spin { animation: none; }
}

/* ── Bucket timing stepper (Session length / Buffer / Lead time / Bookable) ── */
.scheduling-bucket-timing-field {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-xsm);
    min-width: 0;
}
.scheduling-bucket-timing-field__label {
    font-size: var(--font-size-md);
    font-weight: var(--font-weight-medium);
    color: var(--color-text-secondary);
    margin: 0 0 var(--spacing-2xs) 0;
    letter-spacing: 0.005em;
}
.scheduling-bucket-timing-stepper {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    height: 2rem;
    width: auto;
    max-width: 100%;
}
.scheduling-bucket-timing-stepper__btn {
    appearance: none;
    background: #f8fafc;
    border: 1px solid #e2e8f0;
    border-radius: 50%;
    color: #475569;
    font-size: 0.875rem;
    line-height: 1;
    font-weight: var(--font-weight-button);
    width: 1.75rem;
    height: 1.75rem;
    flex-shrink: 0;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background-color 0.1s ease, color 0.1s ease, border-color 0.1s ease;
}
.scheduling-bucket-timing-stepper__btn:hover:not(:disabled) {
    background: color-mix(in srgb, var(--color-action) 8%, white);
    color: var(--color-action);
    border-color: color-mix(in srgb, var(--color-action) 30%, #e2e8f0);
}
.scheduling-bucket-timing-stepper__btn:active:not(:disabled) {
    background: color-mix(in srgb, var(--color-action) 16%, white);
}
.scheduling-bucket-timing-stepper__btn:disabled {
    color: #cbd5e1;
    cursor: not-allowed;
    background: #f8fafc;
}
.scheduling-bucket-timing-stepper__input {
    flex: 0 0 auto;
    width: 2.75rem;
    min-width: 0;
    border: 1px solid #e2e8f0;
    border-radius: 0.375rem;
    background: var(--color-card-bg);
    text-align: center;
    font-size: 0.875rem;
    font-weight: 600;
    color: #0f172a;
    font-variant-numeric: tabular-nums;
    padding: 0.2rem 0.15rem;
    height: 1.75rem;
    outline: none;
    transition: border-color 0.12s ease, box-shadow 0.12s ease;
    -moz-appearance: textfield;
}
.scheduling-bucket-timing-stepper__input:focus {
    border-color: var(--color-focus-ring);
    box-shadow: 0 0 0 2px var(--color-focus-ring-alpha);
}
.scheduling-bucket-timing-stepper__input::-webkit-outer-spin-button,
.scheduling-bucket-timing-stepper__input::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}
.scheduling-bucket-timing-stepper__unit {
    appearance: none;
    -webkit-appearance: none;
    border: 1px solid #e2e8f0;
    border-radius: 0.375rem;
    background: #f8fafc;
    color: #475569;
    font-size: 0.75rem;
    font-weight: 500;
    padding: 0 1rem 0 0.35rem;
    text-align: center;
    height: 1.75rem;
    cursor: pointer;
    outline: none;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%2364748b'><path d='M4.5 6.5L8 10l3.5-3.5z'/></svg>");
    background-repeat: no-repeat;
    background-position: right 0.15rem center;
    background-size: 0.6rem;
    transition: background-color 0.1s ease, color 0.1s ease, border-color 0.1s ease;
}
.scheduling-bucket-timing-stepper__unit:hover {
    background-color: color-mix(in srgb, var(--color-action) 8%, white);
    color: var(--color-action);
    border-color: color-mix(in srgb, var(--color-action) 30%, #e2e8f0);
}
.scheduling-bucket-timing-stepper__unit:focus {
    border-color: var(--color-focus-ring);
    box-shadow: 0 0 0 2px var(--color-focus-ring-alpha);
}

/*
 * Autosave feedback states. Driven by the global wireBucketTimingAutosave-
 * Feedback IIFE in _availability_panels.html. `.is-saving` is added by the
 * stepper's commit() and removed by htmx:afterRequest. `.is-save-failed`
 * persists until the next successful save or refresh — paired with the
 * global error toast so the user has both a glance signal (red border) and
 * a banner signal (toast).
 */
.scheduling-bucket-timing-field.is-saving .scheduling-bucket-timing-stepper__input {
    border-color: var(--color-action);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--color-action) 16%, transparent);
}
.scheduling-bucket-timing-field.is-save-failed .scheduling-bucket-timing-stepper__input {
    border-color: var(--color-error);
    box-shadow: 0 0 0 2px rgba(217, 0, 43, 0.18);
}
.scheduling-bucket-timing-field.is-save-failed .scheduling-bucket-timing-field__label {
    color: var(--color-error);
}

/* ── Service-type chip editor (PR-5) ── */
.scheduling-service-type-group {
    margin-bottom: 1rem;
}
.scheduling-service-type-group:last-child {
    margin-bottom: 0;
}
.scheduling-service-type-group__header {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    margin-bottom: 0.5rem;
}
.scheduling-service-type-group__title {
    font-size: 0.8125rem;
    font-weight: 600;
    color: #475569;
}
.scheduling-service-type-group__chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.375rem;
}
.scheduling-service-type-chip-wrap {
    display: inline-flex;
}
.scheduling-service-type-chip {
    display: inline-flex;
    align-items: center;
    padding: 0.3125rem 0.75rem;
    border-radius: 999px;
    font-size: 0.8125rem;
    font-weight: 500;
    border: 1px solid #e2e8f0;
    background: var(--color-card-bg);
    color: #475569;
    cursor: pointer;
    transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.scheduling-service-type-chip:hover {
    background: #f8fafc;
    border-color: #cbd5e1;
}
.scheduling-service-type-chip--assigned {
    background: var(--color-action);
    border-color: var(--color-action);
    color: #fff;
}
.scheduling-service-type-chip--assigned:hover {
    background: #4f46e5;
    border-color: #4f46e5;
    color: #fff;
}
.scheduling-service-type-chip--available {
    border-style: dashed;
    /* Inherits #475569 from .scheduling-service-type-chip — dashed border alone signals
       "click to add"; no accent needed. */
}
.scheduling-service-type-chip--used-elsewhere,
.scheduling-service-type-chip.is-used-elsewhere {
    /* Muted via explicit colors, NOT opacity — opacity on the chip composites  */
    /* its ::before/::after data-tooltip bubble at the same 55%, making the     */
    /* "Used by …" tooltip unreadably transparent (2026-07-02).                 */
    cursor: not-allowed;
    background: #f1f5f9;
    border-color: #e8edf3;
    color: #94a3b8;
}

/* ── Page layout under the band ──────────────────────────────────────────── */
/* The band's own header holds a name and, on an org schedule, the "All        */
/* workers" badge. They belong together on the left; the cards below are the   */
/* ones with a control on the far right.                                      */
.calendar-bucket-panel .calendar-avail-personal-card-header {
    justify-content: flex-start;
}
/* The name still gives way rather than pushing: a 46-character schedule name  */
/* ran past the card at 375px in round 6, and a header that is now a plain     */
/* flex row would do it again. min-width:0 is the link that lets the span      */
/* shrink below its own text so the ellipsis has something to fire against.    */
.calendar-bucket-panel .calendar-avail-personal-card-title {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* Working hours, calendars and exceptions: equal thirds at one height. They   */
/* were a stacked rail beside the band until 2026-08-18, which is why the      */
/* page needed 1500px before the preview stopped being a sliver.               */
.calendar-avail-settings-trio {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1.5rem;
    align-items: stretch;
}
/* A grid track sized `1fr` is `minmax(auto, 1fr)`, and a grid item's automatic */
/* minimum size is its MIN-CONTENT size — which one `white-space: nowrap`      */
/* descendant sets outright, no matter that the descendant itself clips with   */
/* `overflow: hidden`. A long connected-calendar address therefore froze the   */
/* middle track at 627px and left the other two thirds to split what was over: */
/* at 992 Working Hours got 132px of the row and each time combobox came out   */
/* 5px wide (2026-08-19: the dropdowns were cut off, so the numbers were not   */
/* visible). Stacked, the same min-content ran the single track wider          */
/* than the phone. `min-width: 0` opts the cards out of that automatic         */
/* minimum, so the tracks are equal thirds (or the screen) at every width and  */
/* the address ellipsizes inside its own card instead of sizing the page.      */
.calendar-avail-settings-trio > .calendar-avail-preview-card {
    min-width: 0;
}
@media (min-width: 992px) {
    .calendar-avail-settings-trio {
        grid-template-columns: repeat(3, 1fr);
    }
}
/* Card padding (2026-08-19: the working hours card padding was cleaned up as  */
/* much as possible). Two things were adding space nobody asked for. The grid  */
/* is wrapped in `.settings-section`, whose 2rem bottom margin is right in a   */
/* stacked settings form and is dead space at the foot of a card; and the      */
/* card's own bottom padding was half its top, set when that margin was making */
/* up the difference. The last row already ends flush                          */
/* (.calendar-uavail__row:last-child), so the card closes on its own padding and reads  */
/* the same top and bottom.                                                    */
#page-working-hours-card.calendar-avail-preview-card,
#page-personal-schedule-card.calendar-avail-preview-card {
    padding-bottom: 1rem;
}
#page-working-hours-card .settings-section,
#page-personal-schedule-card .settings-section {
    margin-bottom: 0;
}

.calendar-avail-preview-card {
    background: var(--color-card-bg);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-card);
    box-shadow: var(--shadow-sm);
    padding: 0.5rem 1.5rem 0.75rem;
}
/* ── Filter bar: one quiet row of filter pills (org team view, left       */
/* column, above the live preview). A pill is ink-tinted `is-active`       */
/* when its filter is applied — there are no enable switches; picking a    */
/* value activates a filter, clearing deactivates it.                      */
.calendar-avail-filter-section {
    padding: 0.625rem 1rem;
}
.calendar-avail-filter-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 0.625rem;
}
/* Row = dropdown anchor */
.calendar-avail-filter-row {
    position: relative;
    display: flex;
}

.calendar-avail-filter-trigger {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.4375rem 0.75rem;
    background: #f8fafc;
    border: 1px solid #e2e8f0;
    border-radius: 8px;
    font-size: 0.875rem;
    color: #1e293b;
    text-align: left;
    cursor: pointer;
    transition: background-color 0.15s ease, border-color 0.15s ease;
}
.calendar-avail-filter-trigger:hover {
    background: #f1f5f9;
    border-color: #cbd5e1;
}
.calendar-avail-filter-trigger:focus-visible {
    outline: 2px solid var(--color-focus-ring);
    outline-offset: 2px;
}
.calendar-avail-filter-trigger.is-active {
    background: color-mix(in srgb, var(--color-action) 7%, #fff);
    border-color: color-mix(in srgb, var(--color-action) 35%, #e2e8f0);
}

.calendar-avail-filter-trigger-icon {
    flex-shrink: 0;
    font-size: 0.95rem;
    color: #64748b;
}
.calendar-avail-filter-trigger-label {
    flex-shrink: 0;
    font-weight: 500;
}
.calendar-avail-filter-trigger-summary {
    max-width: 16ch;
    font-size: 0.8125rem;
    color: var(--color-action);
    font-weight: 500;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* The Service summary always renders ('Virtual' is the default view) —
   neutral until a real pick, so only active filters read brand-colored. */
.calendar-avail-filter-trigger-summary.is-default {
    color: #64748b;
    font-weight: 400;
}
.calendar-avail-filter-trigger-chevron {
    flex-shrink: 0;
    font-size: 0.75rem;
    color: #94a3b8;
    transition: transform 0.2s ease;
}
.calendar-avail-filter-trigger-chevron.is-open {
    transform: rotate(180deg);
}

/* ── Dropdown panel ── */
.calendar-avail-filter-dropdown {
    position: absolute;
    top: calc(100% + 0.25rem);
    /* Pills are narrow; the dropdown anchors left and takes its own width. */
    left: 0;
    min-width: 280px;
    max-width: 340px;
    z-index: 60;
    background: var(--color-card-bg);
    border: 1px solid #e2e8f0;
    border-radius: 10px;
    box-shadow:
        0 12px 28px -8px rgba(15, 23, 42, 0.18),
        0 4px 8px -4px rgba(15, 23, 42, 0.08);
    overflow: hidden;
}
.calendar-avail-filter-dropdown-search {
    position: relative;
    padding: 0.5rem 0.75rem;
    border-bottom: 1px solid #f1f5f9;
}
.calendar-avail-filter-dropdown-search i {
    position: absolute;
    top: 50%;
    left: 1.25rem;
    transform: translateY(-50%);
    color: #94a3b8;
    pointer-events: none;
    font-size: 0.875rem;
}
.calendar-avail-filter-dropdown-search input {
    width: 100%;
    padding: 0.375rem 0.5rem 0.375rem 2rem;
    border: 1px solid #e2e8f0;
    border-radius: 6px;
    font-size: 0.8125rem;
    color: #1e293b;
    background: #f8fafc;
    transition: border-color 0.15s ease, background-color 0.15s ease;
}
.calendar-avail-filter-dropdown-search input:focus {
    outline: none;
    border-color: var(--color-focus-ring);
    background: var(--color-card-bg);
}

.calendar-avail-filter-dropdown-list {
    max-height: 280px;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 0.25rem 0;
}
.calendar-avail-filter-option {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    padding: 0.5rem 0.875rem;
    cursor: pointer;
    transition: background-color 0.1s ease;
    margin: 0;
}
.calendar-avail-filter-option:hover {
    background: #f8fafc;
}
.calendar-avail-filter-option .form-check-input {
    margin: 0;
    flex-shrink: 0;
    cursor: pointer;
}
.calendar-avail-filter-option input[type="radio"]:checked,
.calendar-avail-filter-option input[type="checkbox"]:checked {
    background-color: var(--color-action);
    border-color: var(--color-action);
}
.calendar-avail-filter-option-label {
    flex: 1;
    font-size: 0.875rem;
    color: #1e293b;
    user-select: none;
}
/* The Virtual default block: set apart from the service list below it so  */
/* the no-service default can't read as a service type.                    */
.calendar-avail-filter-option--default {
    flex-wrap: wrap;
    padding-bottom: 0.625rem;
    border-bottom: 1px solid #f1f5f9;
}
.calendar-avail-filter-option-caption {
    flex-basis: 100%;
    padding-left: 1.625rem;
    font-size: 0.75rem;
    color: #94a3b8;
    user-select: none;
}
.calendar-avail-filter-group-label {
    padding: 0.5rem 0.875rem 0.125rem;
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: #94a3b8;
}
.calendar-avail-filter-dropdown-footer {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 0.875rem;
    border-top: 1px solid #f1f5f9;
    background: #fafbfc;
}
.calendar-avail-filter-clear-btn {
    background: none;
    border: none;
    padding: 0.125rem 0.375rem;
    margin-left: auto;
    font-size: 0.75rem;
    color: #64748b;
    cursor: pointer;
    border-radius: 4px;
    transition: background-color 0.1s ease, color 0.1s ease;
}
.calendar-avail-filter-clear-btn:hover {
    background: #f1f5f9;
    color: #1e293b;
}

.calendar-avail-level-select {
    flex: 1;
    font-size: 0.8125rem;
    border: 1px solid #e2e8f0;
    border-radius: 6px;
    padding: 0.25rem 0.5rem;
    background: var(--color-card-bg);
}

/* ── Alpine x-transition keyframes ── */
.global-dropdown-enter, .global-dropdown-leave {
    transition: opacity 0.15s ease, transform 0.15s ease;
}
.global-dropdown-enter-start, .global-dropdown-leave-end {
    opacity: 0;
    transform: translateY(-4px);
}
.global-dropdown-enter-end, .global-dropdown-leave-start {
    opacity: 1;
    transform: translateY(0);
}

/* ── Org-mode bucket switcher (PR 2) ── */
/* The personal-mode .scheduling-bucket-chip rules below are scoped to that branch only. */
/* We mirror the chip visual here so admins on the org tab get the same look. */
.scheduling-bucket-switcher {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
}
.scheduling-bucket-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.375rem 0.875rem;
    background: #f8fafc;
    border: 1px solid #e2e8f0;
    border-radius: 999px;
    font-size: 0.8125rem;
    font-weight: 500;
    color: #475569;
    cursor: pointer;
    transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.scheduling-bucket-chip:hover { background: #f1f5f9; border-color: #cbd5e1; color: #1e293b; }
.scheduling-bucket-chip--selected {
    background: var(--color-action);
    border-color: var(--color-action);
    color: #fff;
}
.scheduling-bucket-chip__badge {
    display: inline-flex;
    align-items: center;
    padding: 0.0625rem 0.4375rem;
    border-radius: 999px;
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    background: rgba(99, 102, 241, 0.12);
    color: #4338ca;
    text-transform: uppercase;
    line-height: 1.4;
}
.scheduling-bucket-chip--selected .scheduling-bucket-chip__badge {
    background: rgba(255, 255, 255, 0.22);
    color: #fff;
}
.scheduling-bucket-chip__badge--inline {
    background: rgba(99, 102, 241, 0.14);
    color: #4338ca;
}


/* ── Personal mode: white card chrome + header/body styling ── */
/* Base rule (matches org-mode side; without this the personal cards have */
/* no background/border-radius/shadow and the page reads as bare divs). */
.calendar-avail-preview-card {
    background: var(--color-card-bg);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-card);
    box-shadow: var(--shadow-sm);
    padding: 0.5rem 1.5rem 0.75rem;
}
/* `.calendar-avail-personal-card` cascade (padding, header divider, title typography,  */
/* disabled banner) was hoisted to a shared <style> block above the mode-if   */
/* near line 282 so org cards inherit the same chrome. Do not re-add those     */
/* rules here — keeping them in one place prevents drift. See test file        */
/* tests/interface/templates/app/test_availability_card_chrome_shared.py.      */
/* Personal-mode top-bar: tighter padding, single row, no header chrome. */
.calendar-avail-preview-card.calendar-avail-personal-topbar {
    padding: 0.875rem 1.25rem;
}
.calendar-avail-preview-card.calendar-avail-personal-topbar form {
    margin: 0;
}

/* ── Bucket switcher (chip strip) ── */
.scheduling-bucket-switcher {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
}
.scheduling-bucket-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.375rem 0.875rem;
    background: #f8fafc;
    border: 1px solid #e2e8f0;
    border-radius: 999px;
    font-size: 0.8125rem;
    font-weight: 500;
    color: #475569;
    cursor: pointer;
    transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.scheduling-bucket-chip:hover:not(.scheduling-bucket-chip--disabled) {
    background: #f1f5f9;
    border-color: #cbd5e1;
    color: #1e293b;
}
.scheduling-bucket-chip--selected {
    background: var(--color-action);
    border-color: var(--color-action);
    color: #fff;
}
.scheduling-bucket-chip--selected:hover {
    background: color-mix(in srgb, var(--color-action) 85%, #000);
    border-color: color-mix(in srgb, var(--color-action) 85%, #000);
}
.scheduling-bucket-chip:focus-visible {
    outline: 2px solid var(--color-focus-ring);
    outline-offset: 2px;
}
.scheduling-bucket-chip--add {
    background: var(--color-card-bg);
    border-style: dashed;
    color: var(--color-action);
}
.scheduling-bucket-chip--disabled {
    opacity: 0.55;
    cursor: not-allowed;
}

/* The .calendar-bucket-panel__*, .scheduling-bucket-timing-* and
   .scheduling-service-type-* cascade lives in the shared part of this sheet,
   above the org/personal split. Do not re-add it here.
   See test_availability_org_bucket_css_shared.py. */

/* ── Timezone row inside Working Hours card ── */
.calendar-wh-tz-divider {
    margin: 1rem 0 0.75rem;
    border-color: #f1f5f9;
    opacity: 1;
}
.calendar-wh-tz-row {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding-bottom: 0.25rem;
}
.calendar-wh-tz-label {
    font-size: 0.8125rem;
    font-weight: 600;
    color: #64748b;
    white-space: nowrap;
    flex-shrink: 0;
}

/* Calendar card: header wraps so the reveal drops below title + buttons */
#page-personal-calendars-card .calendar-avail-personal-card-header {
    flex-wrap: wrap;
}

/* ── First-bucket setup ── */
.scheduling-bucket-setup {
    padding: 2rem 1rem;
    text-align: center;
}
.scheduling-bucket-setup__form {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    max-width: 320px;
    margin: 0 auto;
}

/* Exception list styles moved to features/exceptions-list.css so they're in
   scope on both this page AND the standalone settings page that includes
   _org_exceptions.html. */
