/* core/css/forms/fields.css — Shared field styles
   Classes: phx- + BEM — .phx-<field>__<part>--<modifier>
   Used by: core/templates/phoxtail_core/forms/fields/ */

/* ── Field Wrapper ── */

.phx-field {
    display: block;
}

/* ── Required Marker ── */

.phx-field__required {
    color: rgb(var(--color-destructive-500));
}

/* ── Choice Input (MD3 checkbox / radio) ──
   Checkbox: 18dp container, 2dp corner radius, 2dp outline border; checked
   fills with primary and shows an on-primary checkmark. Radio: 20dp ring;
   selected shows a primary ring with a primary inner dot (radial gradient —
   ::before/::after are reserved/reset for third-party interop below). */

.phx-choice__input {
    appearance: none !important;
    -webkit-appearance: none !important;
    flex-shrink: 0;
    border: 2px solid rgb(var(--md-sys-color-on-surface-variant)) !important;
    background-color: transparent !important;
    cursor: pointer;
    outline: none;
    transition: background-color 150ms var(--md-sys-motion-easing-standard),
                border-color 150ms var(--md-sys-motion-easing-standard);
}

.phx-choice__input::before,
.phx-choice__input::after {
    display: none !important;
    content: none !important;
}

.phx-choice__input--checkbox {
    width: 1.125rem !important;
    height: 1.125rem !important;
    border-radius: 2px !important;
}

.phx-choice__input--radio {
    width: 1.25rem !important;
    height: 1.25rem !important;
    border-radius: 50% !important;
}

.phx-choice__input--checkbox:checked {
    background-color: rgb(var(--md-sys-color-primary)) !important;
    border-color: rgb(var(--md-sys-color-primary)) !important;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke-width='3' stroke='white'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='m4.5 12.75 6 6 9-13.5'/%3E%3C/svg%3E") !important;
    background-repeat: no-repeat !important;
    background-position: center !important;
    background-size: 0.75rem !important;
}

/* Selected radio: primary ring + centered primary dot (10dp of the 20dp). */
.phx-choice__input--radio:checked {
    border-color: rgb(var(--md-sys-color-primary)) !important;
    background: radial-gradient(circle,
        rgb(var(--md-sys-color-primary)) 0 31%,
        transparent 34%) !important;
}

.phx-choice__input:focus-visible {
    outline: 2px solid rgb(var(--md-sys-color-primary));
    outline-offset: 2px;
}

.phx-choice__input:disabled {
    border-color: rgb(var(--md-sys-color-on-surface) / 0.38) !important;
    cursor: default;
}

/* ── Choice Option Label (shared by single checkbox, multi-checkbox, radio) ──
   Plain MD3 list rows — the control and a body-large label, state layer on
   hover, no pill/glass container. The row is the 48dp touch target. */

.phx-choice {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    min-height: 3rem;
    padding: 0.5rem 0.75rem;
    border-radius: var(--md-sys-shape-corner-extra-small, 4px);
    cursor: pointer;
    min-width: 0;
    transition: background-color 150ms var(--md-sys-motion-easing-standard);
}

.phx-choice:hover {
    background-color: rgb(var(--md-sys-color-on-surface) / 0.08);
}

/* Larger padding for standalone single-checkbox */
.phx-checkbox {
    padding: 0.75rem;
}

/* In single-checkbox context, the text container fills remaining space */
.phx-checkbox .phx-choice__text {
    flex: 1;
}

.phx-choice__text {
    font-size: 1rem;
    color: rgb(var(--md-sys-color-on-surface));
}

/* Tighter rows in the weekday picker so its narrow cells don't clip their
   labels. */
.phx-choices--7col .phx-choice {
    padding: 0.375rem 0.375rem;
    gap: 0.5rem;
}

/* Truncate text when inside a grid (multi-choice context) */
.phx-choices .phx-choice__text {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.phx-choice__name {
    display: block;
    font-size: 1rem;
    color: rgb(var(--md-sys-color-on-surface));
}

.phx-choice__help {
    display: block;
    margin-top: 0.125rem;
    font-size: 0.75rem;
    line-height: 1rem;
    color: rgb(var(--md-sys-color-on-surface-variant));
}

/* ── Choice Grid ── */

/* Column count adapts to the grid's own rendered width, not the viewport —
   this widget gets mounted in containers of wildly different widths (a full
   page, a narrow modal drawer, a sidebar panel) that have no relation to the
   viewport size a fixed media-query breakpoint would key off of. Falls back
   to viewport-based breakpoints for browsers without container query
   support (behavior identical to the previous implementation).
   Containment lives on the .phx-field wrapper, not the grid itself — a
   container query can't size an element against a containment context the
   element itself establishes, it only sees ancestor containers. */
.phx-field:has(.phx-choices) {
    container-type: inline-size;
}

.phx-choices {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0.25rem;
}

@container (min-width: 400px) {
    .phx-choices {
        grid-template-columns: repeat(2, 1fr);
    }
}

@container (min-width: 640px) {
    .phx-choices {
        grid-template-columns: repeat(3, 1fr);
    }
}

@supports not (container-type: inline-size) {
    @media (min-width: 640px) {
        .phx-choices {
            grid-template-columns: repeat(2, 1fr);
        }
    }

    @media (min-width: 1024px) {
        .phx-choices {
            grid-template-columns: repeat(3, 1fr);
        }
    }
}

/* A grouped choice's heading spans the whole row above its options. */
.phx-choices > .phx-field__group-label {
    grid-column: 1 / -1;
}

/* 7-column layout for weekday selection (Mon–Sun). Four columns until the
   grid itself — not the screen — is wide enough for seven short day names
   (a wide screen with a narrow drawer used to force seven cells too small
   for their labels); seven need ~27rem at the spacing below. */
.phx-choices--7col {
    grid-template-columns: repeat(4, 1fr);
    gap: 1rem;
}

@container (min-width: 28rem) {
    .phx-choices--7col {
        grid-template-columns: repeat(7, 1fr);
        gap: 0.25rem;
    }
}

@supports not (container-type: inline-size) {
    @media (min-width: 1024px) {
        .phx-choices--7col {
            grid-template-columns: repeat(7, 1fr);
        }
    }
}

/* One option per row whatever the width: options whose names are long or
   whose number grows (a member's groups), which side by side get cut off. */
.phx-choices--1col {
    grid-template-columns: 1fr;
}

/* ── Password ──
   The password box is the shared phx-field outlined field (input.html); its
   show/hide button is a .phx-field__trailing-button driven by js/fields.js. */

.phx-input__password-eye {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 1.25rem;
    height: 1.25rem;
}

.phx-input__password-eye svg {
    width: 1.25rem;
    height: 1.25rem;
}

/* ── Hidden Utility ── */

.phx-hidden {
    display: none;
}

/* Visually hidden but still focusable/participates in layout flow enough for
   native constraint validation — unlike display:none, this lets a `required`
   select still be validated and (if invalid) focused by the browser on
   submit instead of throwing "not focusable" and silently blocking it. */
.phx-sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* ── Widget Container (complex HTMX widgets) ── */

.phx-single-select-search__container {
    position: relative;
}

/* Inactive (is_active=False, or a disabled form field): the filled look of a
   disabled field (below), and nothing to click. */
.phx-single-select-search__container--inactive {
    pointer-events: none;
    user-select: none;
}

.phx-field__box:has(> .phx-single-select-search__container--inactive) {
    isolation: isolate;
}

.phx-single-select-search__container--inactive ~ .phx-field__outline {
    z-index: -1;
    border-color: transparent;
    background: rgb(var(--md-sys-color-surface-container-highest) / 0.6) !important;
}

/* ── Toggle (MD3 switch) ──
   52x32dp track. Unselected: surface-container-highest fill, 2dp outline
   border, 16dp on-surface-variant handle. Selected: primary fill, handle
   grows to 24dp in on-primary and slides right. A list row like the
   checkbox's: padded, highlighted on hover, no pill. */

.phx-toggle {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.75rem;
    border-radius: var(--md-sys-shape-corner-extra-small, 4px);
    cursor: pointer;
    transition: background-color 150ms var(--md-sys-motion-easing-standard);
}

/* The whole row answers the pointer, as the checkbox row does. */
.phx-toggle:hover {
    background-color: rgb(var(--md-sys-color-on-surface) / 0.08);
}

.phx-toggle__name {
    font-size: 1rem;
    color: rgb(var(--md-sys-color-on-surface));
}

.phx-toggle__wrapper {
    position: relative;
    display: inline-flex;
    align-items: center;
    flex-shrink: 0;
}

.phx-toggle__input {
    position: absolute;
    width: 0 !important;
    height: 0 !important;
    opacity: 0 !important;
    appearance: none !important;
}

.phx-toggle__track {
    position: relative;
    width: 3.25rem;
    height: 2rem;
    box-sizing: border-box;
    border-radius: 9999px;
    border: 2px solid rgb(var(--md-sys-color-outline));
    background-color: rgb(var(--md-sys-color-surface-container-highest));
    transition: background-color 200ms var(--md-sys-motion-easing-standard),
                border-color 200ms var(--md-sys-motion-easing-standard);
}

.phx-toggle__track::before {
    content: '';
    position: absolute;
    top: 50%;
    left: 0.375rem;
    width: 1rem;
    height: 1rem;
    background-color: rgb(var(--md-sys-color-on-surface-variant));
    border-radius: 9999px;
    transform: translateY(-50%);
    transition: transform 200ms var(--md-sys-motion-easing-standard),
                width 200ms var(--md-sys-motion-easing-standard),
                height 200ms var(--md-sys-motion-easing-standard),
                background-color 200ms var(--md-sys-motion-easing-standard);
}

.phx-toggle__input:checked + .phx-toggle__track {
    background-color: rgb(var(--md-sys-color-primary));
    border-color: rgb(var(--md-sys-color-primary));
}

/* 24dp handle, 4dp from the track's right inner edge. */
.phx-toggle__input:checked + .phx-toggle__track::before {
    width: 1.5rem;
    height: 1.5rem;
    background-color: rgb(var(--md-sys-color-on-primary));
    transform: translate(0.875rem, -50%);
}

.phx-toggle__input:focus-visible + .phx-toggle__track {
    outline: 2px solid rgb(var(--md-sys-color-primary));
    outline-offset: 2px;
}

/* ── Search ──
   filled + small: one pill for a list's toolbar — the magnifier (or the
   clear button once there is text), the box and the result count sit inside
   it. The small size, as the buttons beside it. */

.phx-search {
    position: relative;
    display: flex;
    align-items: center;
    gap: 0.625rem;
    width: 100%;
    box-sizing: border-box;
}

.phx-search--small {
    height: var(--phx-size-small);
    padding: 0 1rem;
}

.phx-search--filled {
    background: var(--phx-control-background);
    box-shadow: var(--phx-control-shadow);
    border-radius: 999px;
    transition: background-color 150ms ease, box-shadow 200ms ease;
}

.phx-search--filled:hover {
    background: var(--phx-control-background-hover);
    box-shadow: var(--phx-control-shadow-hover);
}

/* The box drops its own outline, so focus draws the fields' ring. */
.phx-search--filled:focus-within {
    outline: 2px solid rgb(var(--color-primary-600));
    outline-offset: 2px;
}

/* !important: Wagtail's admin styles every input. */
.phx-search__input {
    flex: 1 !important;
    min-width: 0 !important;
    width: auto !important;
    height: 100% !important;
    /* Right padding reserves room for the absolutely positioned count. */
    padding: 0 3.25rem 0 0 !important;
    border: none !important;
    border-radius: 0 !important;
    background: transparent !important;
    color: rgb(var(--color-surface-900)) !important;
    font-size: 0.875rem !important;
    font-weight: 400 !important;
    outline: none !important;
    box-shadow: none !important;
}

/* The placeholder and the count are labels, weighted as the buttons beside
   the bar; what is typed stays regular. */
.phx-search__input::placeholder {
    color: rgb(var(--color-surface-600));
    font-weight: 600;
}

/* The magnifier and the clear button share one slot — one is visible. */
.phx-search__icon,
.phx-search__clear {
    display: flex;
    flex-shrink: 0;
}

.phx-search__icon.phx-hidden,
.phx-search__clear.phx-hidden {
    display: none;
}

.phx-search__icon {
    pointer-events: none;
}

.phx-search__clear {
    border: none;
    background: none;
    padding: 0;
    cursor: pointer;
}

.phx-search__icon svg,
.phx-search__clear svg {
    width: var(--phx-size-small-icon);
    height: var(--phx-size-small-icon);
    display: block;
    color: rgb(var(--color-surface-600));
}

.phx-search__count {
    position: absolute;
    right: 1rem;
    color: rgb(var(--color-surface-600));
    font-size: 0.75rem;
    font-weight: 600;
    white-space: nowrap;
    pointer-events: none;
}

@media (prefers-color-scheme: dark) {
    .phx-search--filled:focus-within {
        outline-color: rgb(var(--color-primary-400));
    }

    .phx-search__input {
        color: rgb(var(--color-surface-50)) !important;
    }

    .phx-search__input::placeholder {
        color: rgb(var(--color-surface-300));
    }

    .phx-search__icon svg,
    .phx-search__clear svg,
    .phx-search__count {
        color: rgb(var(--color-surface-300));
    }
}

/* ── Date Stepper ──
   filled + small: ‹ date › for a toolbar — one pill in three segments, a
   faint line between them. The outer radius is half the height, not 999px:
   an oversized radius makes the browser shrink every corner of the box. */

.phx-date-stepper {
    display: inline-flex;
}

.phx-date-stepper > * {
    display: flex;
    align-items: center;
    box-sizing: border-box;
}

.phx-date-stepper--small > * {
    height: var(--phx-size-small);
}

.phx-date-stepper > :first-child {
    border-start-start-radius: calc(var(--phx-size-small) / 2);
    border-end-start-radius: calc(var(--phx-size-small) / 2);
}

.phx-date-stepper > :last-child {
    border-start-end-radius: calc(var(--phx-size-small) / 2);
    border-end-end-radius: calc(var(--phx-size-small) / 2);
}

/* What the box it sits in hands its controls (main.css): the shadow on the
   whole pill, the fill on each segment. */
.phx-date-stepper--filled {
    border-radius: calc(var(--phx-size-small) / 2);
    box-shadow: var(--phx-control-shadow);
    transition: box-shadow 200ms ease;
}

.phx-date-stepper--filled:hover {
    box-shadow: var(--phx-control-shadow-hover);
}

.phx-date-stepper--filled > * {
    background: var(--phx-control-background);
    color: rgb(var(--color-surface-600));
    cursor: pointer;
    transition: background-color 150ms ease;
}

.phx-date-stepper--filled > :hover {
    background: var(--phx-control-background-hover);
}

/* The focused segment is lifted, or its neighbour paints over its ring. */
.phx-date-stepper > :focus-visible {
    position: relative;
    z-index: 1;
}

.phx-date-stepper__step {
    justify-content: center;
    width: var(--phx-size-small);
    padding: 0;
    border: none;
}

/* The line between segments darkens (lightens, in dark) whatever fill it
   crosses, so it shows on every ground. */
.phx-date-stepper--filled > :first-child {
    border-inline-end: 1px solid rgb(0 0 0 / 0.08);
}

.phx-date-stepper--filled > :last-child {
    border-inline-start: 1px solid rgb(0 0 0 / 0.08);
}

/* As the icons in the buttons beside it. */
.phx-date-stepper__step svg {
    width: var(--phx-size-small-icon);
    height: var(--phx-size-small-icon);
}

/* The browser's calendar icon, as the icons beside it (Chrome and Safari;
   Firefox draws its own at its own size). */
.phx-date-stepper__input::-webkit-calendar-picker-indicator {
    width: var(--phx-size-small-icon);
    height: var(--phx-size-small-icon);
    padding: 0;
}

.phx-date-stepper__date {
    flex: 1;
}

/* Sheds Wagtail's input[type=date] styling (!important: Wagtail's admin
   styles every input). The box takes every click and tap itself, so the
   browser opens its own picker: iOS opens none from script. It spans the date
   from its start edge, where the picker anchors, and pads its text back in. */
.phx-date-stepper__input {
    appearance: none;
    align-self: stretch;
    width: 100% !important;
    min-height: 0 !important;
    padding: 0 1rem !important;
    border: none !important;
    border-radius: 0 !important;
    background: none !important;
    color: inherit !important;
    font-size: 0.875rem !important;
    font-weight: 600 !important;
    color-scheme: light dark;
    /* Outranks Wagtail's global :focus-visible ring: the ring moves to the
       whole date. */
    outline: none !important;
    box-shadow: none !important;
}

.phx-date-stepper__date:focus-within {
    position: relative;
    z-index: 1;
    outline: 3px solid var(--w-color-focus, currentColor);
    outline-offset: 2px;
}

/* iOS zooms the page into a focused box whose text is under 16px. */
@media (any-pointer: coarse) {
    .phx-date-stepper__input {
        font-size: 1rem !important;
    }
}

@media (prefers-color-scheme: dark) {
    .phx-date-stepper--filled > * {
        color: rgb(var(--color-surface-300));
    }

    .phx-date-stepper--filled > :first-child,
    .phx-date-stepper--filled > :last-child {
        border-color: rgb(255 255 255 / 0.08);
    }
}

/* ── Week Stepper ──
   The days sit on the card itself, the day on show on a circle in the
   brand colour that slides to the next one, today's number in the brand
   colour too. Each day stacks weekday,
   number and month, the two small words muted capitals so the number reads
   first. Each day is a square
   as large as its circle, so the track is as tall as the circles plus its
   padding: 58px circles, never squeezed. The calendar and the arrows
   line up with the days below them. One card, a control's fill and
   shadow, holds three groups: the calendar, which opens the browser's own
   date picker, and Today (plain text); the arrows around the week's dates;
   and the track. The controls are plain icons and text, each as large to
   the pointer as a day's circle (Today wider where its word needs it), which
   shows only under the pointer, as a faint fill. They share a row where they fit, and each takes a row of its own
   where it does not (js/fields.js lays them out: all three on one row, the
   track between; or the two others above the track, side by side or one
   under the other). The days always keep one row: where the seven circles
   do not fit, the track scrolls sideways. */

.phx-week-stepper {
    /* A day's circle, which a day never shrinks below, the gap between the
       circles and the track (which the thumb's place counts from), the
       card's padding, the
       faint fill of a control's circle under the pointer, the faint line
       between the calendar and Today, and the width of a fade where the
       days scroll. */
    --phx-week-stepper-circle: calc(4rem - 6px);
    --phx-week-stepper-inset: 3px;
    --phx-week-stepper-padding: 0.25rem;
    --phx-week-stepper-fill: rgb(0 0 0 / 0.05);
    --phx-week-stepper-line: rgb(0 0 0 / 0.12);
    --phx-week-stepper-fade: 2.5rem;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0 var(--phx-week-stepper-padding);
    min-width: 0;
    max-width: 100%;
    padding: var(--phx-week-stepper-padding);
    /* The track's own radius, the card's padding further out. */
    border-radius: calc(2rem + var(--phx-week-stepper-padding));
    background: var(--phx-control-background);
    box-shadow: var(--phx-control-shadow);
    box-sizing: border-box;
}

/* All three on one row (js/fields.js): the track between the others, as
   wide as its seven circles and in the middle; on a wider card the room
   left over goes to its sides, the calendar and Today at the start, the
   arrows at the end. Short of room, the track gives way first: the sides
   never go below their own width (minmax(max-content, 1fr)), the track can
   (minmax(0, auto)), so the script sees it no longer fits and the three
   leave the one row; nothing overlaps. */
/* On two rows or more, softer corners: a full pill's ends would bulge on a
   box that tall. */
.phx-week-stepper:not(.phx-week-stepper--wide) {
    border-radius: calc(1.25rem + var(--phx-week-stepper-padding));
}

.phx-week-stepper:not(.phx-week-stepper--wide) .phx-week-stepper__days {
    border-radius: 1.25rem;
}

.phx-week-stepper--wide {
    display: grid;
    grid-template-columns: minmax(max-content, 1fr) minmax(0, auto) minmax(max-content, 1fr);
    grid-template-areas: "jump days nav";
}

.phx-week-stepper--wide .phx-week-stepper__nav {
    justify-self: end;
}

/* The calendar and the arrows sit as far in as the days' circles (the
   track's inset), so a control above a day lines up with it. */
.phx-week-stepper__jump {
    display: flex;
    grid-area: jump;
    align-items: center;
    padding-inline: var(--phx-week-stepper-inset);
}

/* Alone on its row (--stacked), the calendar and Today go to its ends, over
   the first day and the last, the faint line between them at its middle. */
.phx-week-stepper--stacked .phx-week-stepper__jump {
    position: relative;
    flex: 1 1 100%;
    justify-content: space-between;
}

.phx-week-stepper--stacked .phx-week-stepper__calendar + .phx-week-stepper__today {
    position: static;
}

.phx-week-stepper--stacked .phx-week-stepper__calendar + .phx-week-stepper__today::before {
    inset-inline-start: calc(50% - 0.5px);
}

/* Beside the calendar and Today, the arrows sit at the card's end; alone on
   their row (--stacked), they go to its ends, the dates between them. */
.phx-week-stepper__nav {
    display: flex;
    flex: 0 1 auto;
    align-items: center;
    min-width: 0;
    grid-area: nav;
    justify-content: space-between;
    padding-inline: var(--phx-week-stepper-inset);
}

.phx-week-stepper--stacked .phx-week-stepper__nav {
    flex: 1 1 100%;
}

.phx-week-stepper__today,
.phx-week-stepper__calendar,
.phx-week-stepper__step {
    display: flex;
    flex-shrink: 0;
    align-items: center;
    justify-content: center;
    height: var(--phx-week-stepper-circle);
    padding: 0;
    border: none;
    border-radius: calc(var(--phx-week-stepper-circle) / 2);
    background: transparent;
    color: rgb(var(--color-surface-600));
    font: inherit;
    cursor: pointer;
    transition: color 0.15s ease, background-color 150ms ease;
}

/* Plain text, never underlined; as wide as a circle, or its word. */
.phx-week-stepper__today {
    min-width: var(--phx-week-stepper-circle);
    padding-inline: 0.5rem;
    font-size: 0.875rem;
    font-weight: 600;
    text-decoration: none;
}

/* The faint line between the calendar and Today, in the gap between them,
   so neither loses its width to it. */
.phx-week-stepper__calendar + .phx-week-stepper__today {
    position: relative;
    margin-inline-start: 0.75rem;
}

.phx-week-stepper__calendar + .phx-week-stepper__today::before {
    content: "";
    position: absolute;
    top: 50%;
    inset-inline-start: calc(-0.375rem - 0.5px);
    width: 1px;
    height: 2rem;
    background: var(--phx-week-stepper-line);
    transform: translateY(-50%);
}

/* A day's circle, faintly filled under the pointer. */
.phx-week-stepper__calendar,
.phx-week-stepper__step {
    width: var(--phx-week-stepper-circle);
}

.phx-week-stepper__today:hover,
.phx-week-stepper__calendar:hover,
.phx-week-stepper__step:hover {
    background: var(--phx-week-stepper-fill);
}

.phx-week-stepper__today:hover,
.phx-week-stepper__calendar:hover,
.phx-week-stepper__step:hover {
    color: rgb(var(--color-surface-900));
}

.phx-week-stepper__step svg,
.phx-week-stepper__calendar svg {
    flex-shrink: 0;
    width: var(--phx-size-small-icon);
    height: var(--phx-size-small-icon);
}

.phx-week-stepper__calendar {
    position: relative;
}

/* The date box, unseen over the calendar, takes the tap: the browser opens
   its own picker. Sheds Wagtail's input styling (!important: Wagtail's admin
   styles every input); 16px, or iOS zooms the page into it. */
.phx-week-stepper__box {
    position: absolute;
    inset: 0;
    width: 100% !important;
    height: 100% !important;
    min-height: 0 !important;
    margin: 0;
    padding: 0 !important;
    border: none !important;
    opacity: 0;
    font-size: 1rem !important;
    cursor: pointer;
}

.phx-week-stepper__calendar:focus-within {
    outline: 3px solid var(--w-color-focus, currentColor);
    outline-offset: 2px;
}

/* The week's dates, two lines in a day's circle (wider where a language's
   dates need it), set as a day is, a month in small muted capitals and a day
   in bold: its month over its days, or both months, side by side, for a
   week into the next. */
.phx-week-stepper__label {
    display: flex;
    flex-direction: column;
    flex-shrink: 0;
    align-items: center;
    justify-content: center;
    gap: 0.1875rem;
    min-width: var(--phx-week-stepper-circle);
    height: var(--phx-week-stepper-circle);
    color: rgb(var(--color-surface-600));
    line-height: 1;
    text-align: center;
    white-space: nowrap;
}

.phx-week-stepper__label-month {
    font-size: 0.625rem;
    font-weight: 500;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    opacity: 0.75;
}

.phx-week-stepper__label-day {
    font-size: 1rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

.phx-week-stepper__label-months {
    display: flex;
    gap: 0.5rem;
}

/* The track: a row of its own (flex-basis 100%), or the middle of one.
   Seven columns, never narrower than a circle; short of that room the
   track scrolls sideways, and never pushes the box it sits in wider. */
.phx-week-stepper__days {
    position: relative;
    display: grid;
    flex: 1 1 100%;
    grid-area: days;
    grid-template-columns: repeat(7, minmax(var(--phx-week-stepper-circle), 1fr));
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
    padding: var(--phx-week-stepper-inset);
    border-radius: 2rem;
    box-sizing: border-box;
}

/* Where the track scrolls, the days fade out at a side with more beyond it
   (js/fields.js marks which), and the fade eases in and out as the scroll
   reaches an end. The fades are lengths registered as such, so they can
   ease, and so is the width of a full one, which js/fields.js reads in
   pixels to keep the chosen day clear of it. */
@property --phx-week-stepper-fade {
    syntax: "<length>";
    inherits: true;
    initial-value: 0px;
}

@property --phx-week-stepper-fade-start {
    syntax: "<length>";
    inherits: false;
    initial-value: 0px;
}

@property --phx-week-stepper-fade-end {
    syntax: "<length>";
    inherits: false;
    initial-value: 0px;
}

.phx-week-stepper--fade-start .phx-week-stepper__days {
    --phx-week-stepper-fade-start: var(--phx-week-stepper-fade);
}

.phx-week-stepper--fade-end .phx-week-stepper__days {
    --phx-week-stepper-fade-end: var(--phx-week-stepper-fade);
}

.phx-week-stepper--fade-start .phx-week-stepper__days,
.phx-week-stepper--fade-end .phx-week-stepper__days {
    mask-image: linear-gradient(to right, transparent, #000 var(--phx-week-stepper-fade-start), #000 calc(100% - var(--phx-week-stepper-fade-end)), transparent);
}

.phx-week-stepper__days {
    transition: --phx-week-stepper-fade-start 0.2s ease, --phx-week-stepper-fade-end 0.2s ease;
}

/* On a row of its own the track asks for no width at all (width 0), yet
   fills its row (min-width 100%), so its days can never make a box it sits
   in wider (a wrapping box sizes its rows by what they ask): it takes the
   row it is given and scrolls inside it. */
.phx-week-stepper:not(.phx-week-stepper--wide) .phx-week-stepper__days {
    width: 0;
    min-width: 100%;
}

/* What the track asks for: seven circles side by side, so it takes a row
   of its own before it scrolls. */
.phx-week-stepper__days::after {
    content: "";
    grid-row: 1;
    grid-column: 1 / -1;
    align-self: start;
    width: calc(7 * var(--phx-week-stepper-circle));
    max-width: 100%;
    height: 0;
}

/* Centred on the chosen day, it slides by its left edge. A column is a
   seventh of the track, or a circle where the track scrolls. A circle in
   the brand colour, a shade deeper under the pointer. */
.phx-week-stepper__thumb {
    --phx-week-stepper-cell: max(var(--phx-week-stepper-circle), (100% - 2 * var(--phx-week-stepper-inset)) / 7);
    position: absolute;
    top: 50%;
    left: calc(var(--phx-week-stepper-inset) + var(--phx-week-stepper-cell) * (var(--phx-week-stepper-chosen, 0) + 0.5));
    width: min(var(--phx-week-stepper-cell), var(--phx-week-stepper-circle));
    aspect-ratio: 1;
    border-radius: 50%;
    background: rgb(var(--color-primary-700));
    box-shadow: 0 1px 2px rgb(var(--color-primary-700) / 0.2);
    transform: translate(-50%, -50%);
    transition-property: left, background-color;
    transition-duration: 0.2s;
    transition-timing-function: var(--md-sys-motion-easing-standard, cubic-bezier(0.4, 0, 0.2, 1));
}

.phx-week-stepper__days::-webkit-scrollbar {
    display: none;
}

.phx-week-stepper__days:has(.phx-week-stepper__day[aria-current]:hover) .phx-week-stepper__thumb {
    background: color-mix(in srgb, rgb(var(--color-primary-700)), black 12%);
}

.phx-week-stepper__day {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.1875rem;
    justify-self: stretch;
    aspect-ratio: 1;
    min-width: var(--phx-week-stepper-circle);
    max-height: var(--phx-week-stepper-circle);
    padding: 0;
    border: none;
    border-radius: 50%;
    background: transparent;
    color: rgb(var(--color-surface-600));
    font: inherit;
    line-height: 1;
    cursor: pointer;
    transition: color 0.15s ease;
}

.phx-week-stepper__day:hover {
    color: rgb(var(--color-surface-900));
}

/* The chosen day in white on its circle, today's number too. */
.phx-week-stepper__day[aria-current],
.phx-week-stepper__day--today[aria-current] .phx-week-stepper__number {
    color: #fff;
}

/* Today's number in the brand colour, hovered or not (white once chosen):
   a colour, not a circle, so it never reads as the chosen day. */
.phx-week-stepper__day--today .phx-week-stepper__number {
    color: rgb(var(--color-primary-700));
}

.phx-week-stepper__weekday,
.phx-week-stepper__month {
    font-size: 0.625rem;
    font-weight: 500;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    opacity: 0.85;
}

.phx-week-stepper__number {
    font-size: 1rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

@media (prefers-color-scheme: dark) {
    /* A fill and a line light enough to show on the ground. */
    .phx-week-stepper {
        --phx-week-stepper-fill: rgb(255 255 255 / 0.08);
        --phx-week-stepper-line: rgb(255 255 255 / 0.16);
    }

    .phx-week-stepper__day--today .phx-week-stepper__number {
        color: rgb(var(--color-primary-400));
    }

    .phx-week-stepper__today,
    .phx-week-stepper__calendar,
    .phx-week-stepper__step,
    .phx-week-stepper__label {
        color: rgb(var(--color-surface-300));
    }

    .phx-week-stepper__day {
        color: rgb(var(--color-surface-400));
    }

    .phx-week-stepper__today:hover,
    .phx-week-stepper__calendar:hover,
    .phx-week-stepper__step:hover,
    .phx-week-stepper__day:hover {
        color: rgb(var(--color-surface-50));
    }
}

/* ── Search Results (single select search) ── */

.phx-single-select-search__divider {
    margin: 0;
    border-top: 1px solid rgb(var(--md-sys-color-outline-variant));
}

.phx-single-select-search__item {
    display: flex;
    align-items: center;
    width: 100%;
    padding: 0.5rem 1rem;
    text-align: left;
    font-size: 0.9375rem;
    color: rgb(var(--md-sys-color-on-surface));
    background: none;
    border: none;
    cursor: pointer;
    transition: background 0.1s;
    white-space: nowrap;
}

.phx-single-select-search__item:hover {
    background: rgb(var(--md-sys-color-on-surface) / 0.06);
}

.phx-single-select-search__item-text {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.phx-single-select-search__empty {
    padding: 0.75rem 1rem;
    font-size: 0.9375rem;
    color: rgb(var(--md-sys-color-on-surface-variant));
    font-style: italic;
    text-align: center;
}

/* ── Single Select Search ── */

.phx-single-select-search__input {
    position: relative;
    /* token definitions — light; cascade to trigger, panel, results */
    --md-sys-color-surface-container-low: var(--color-surface-100);
    --md-sys-color-outline-variant: var(--color-surface-200);
    --md-sys-color-on-surface: var(--color-surface-900);
    --md-sys-color-on-surface-variant: var(--color-surface-600);
    --md-sys-color-primary: var(--color-primary-600);
}

@media (prefers-color-scheme: dark) {
    .phx-single-select-search__input {
        --md-sys-color-surface-container-low: var(--color-surface-800);
        --md-sys-color-outline-variant: var(--color-surface-700);
        --md-sys-color-on-surface: var(--color-surface-100);
        --md-sys-color-on-surface-variant: var(--color-surface-400);
        --md-sys-color-primary: var(--color-primary-400);
    }
}

/* Trigger — a bare flex row; all field chrome (background, outline, focus
   and open states) comes from the shared .phx-field__control / .phx-field__outline
   anatomy, never from the trigger itself. */
.phx-single-select-search__trigger {
    white-space: nowrap;
    outline: none !important;
}

.phx-single-select-search__trigger:disabled {
    opacity: 0.38;
    cursor: not-allowed;
}

.phx-single-select-search__trigger-label {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    text-align: left;
}

/* Chevron icon — rotates when panel is open */
.phx-single-select-search__chevron {
    width: 1rem !important;
    height: 1rem !important;
    color: rgb(var(--md-sys-color-on-surface-variant));
    flex-shrink: 0 !important;
    transition: transform 0.2s ease;
    display: block !important;
    background: none !important;
    border: none !important;
    padding: 0 !important;
    box-shadow: none !important;
    border-radius: 0 !important;
}

.phx-single-select-search__trigger[aria-expanded="true"] .phx-single-select-search__chevron {
    transform: rotate(180deg);
}

/* Clear button (replaces chevron when an item is selected) */
.phx-single-select-search__trigger-clear {
    display: inline-flex !important;
    align-items: center;
    justify-content: center;
    background: none !important;
    border: none !important;
    padding: 0 !important;
    margin: 0 !important;
    cursor: pointer;
    color: inherit;
    transition: color 0.15s;
    border-radius: 0 !important;
    box-shadow: none !important;
    line-height: 0;
}

.phx-single-select-search__trigger-clear svg {
    width: 1rem;
    height: 1rem;
    display: block;
}

.phx-single-select-search__trigger-clear:hover {
    color: rgb(var(--md-sys-color-on-surface)) !important;
    background: none !important;
}

/* Panel (the dropdown) */
.phx-single-select-search__panel {
    position: absolute;
    top: calc(100% + 0.5rem);
    left: 0;
    z-index: 100;
    min-width: 14rem;
    max-width: 22rem;
    border-radius: 12px;
    overflow: hidden;
}

/* Search bar inside panel */
.phx-single-select-search__panel-search {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    padding: 0 0.875rem;
    border-bottom: 1px solid rgb(var(--md-sys-color-outline-variant));
}

.phx-single-select-search__panel-search-icon {
    width: 1rem !important;
    height: 1rem !important;
    flex-shrink: 0;
    color: rgb(var(--md-sys-color-on-surface-variant));
    display: block !important;
    background: none !important;
    border: none !important;
    padding: 0 !important;
    box-shadow: none !important;
    border-radius: 0 !important;
}

.phx-single-select-search__panel-input {
    flex: 1 !important;
    border: none !important;
    outline: none !important;
    background: transparent !important;
    font-size: 0.875rem !important;
    font-family: inherit !important;
    color: rgb(var(--md-sys-color-on-surface)) !important;
    padding: 0 !important;
    box-shadow: none !important;
    border-radius: 0 !important;
    height: auto !important;
    width: auto !important;
}

.phx-single-select-search__panel-input::placeholder {
    color: rgb(var(--md-sys-color-on-surface-variant));
}

.phx-single-select-search__panel-input:hover,
.phx-single-select-search__panel-input:focus {
    border-color: transparent !important;
    box-shadow: none !important;
}

/* Items list */
.phx-single-select-search__results {
    padding: 0.375rem 0;
    max-height: 14rem;
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: rgb(var(--md-sys-color-outline-variant)) transparent;
}

/* ── Segmented Control ──
   Keeps the original sliding-thumb design (a deliberate departure from MD3
   segmented buttons, by design decision) but dressed as an outlined field:
   same 56px height, same outline token/hover/error border treatment and 4px
   corners as .phx-field__outline, transparent track. The thumb is glassy — a
   low-alpha primary tint over a backdrop blur with a primary hairline —
   and the selected label carries the primary accent. That is the outlined
   + large look, for forms; --filled --small is a pill (below). */

.phx-segmented-control {
    position: relative !important;
    display: inline-flex !important;
    height: 3.5rem !important;
    width: auto !important;
    flex-shrink: 0 !important;
    border-radius: var(--md-sys-shape-corner-extra-small, 4px) !important;
    border: 1px solid rgb(var(--md-sys-color-outline)) !important;
    background: transparent !important;
    padding: 4px !important;
    box-sizing: border-box !important;
    user-select: none !important;
    transition: border-color 200ms var(--md-sys-motion-easing-standard);
}

/* Hover/error borders mirror .phx-field__outline so the control never stands out
   from the outlined fields sharing its row. */
.phx-segmented-control:hover {
    border-color: rgb(var(--md-sys-color-on-surface)) !important;
}

.phx-field--error .phx-segmented-control,
.phx-field--error .phx-segmented-control:hover {
    border-color: rgb(var(--md-sys-color-error)) !important;
}

.phx-segmented-control__radio {
    position: absolute !important;
    width: 0 !important;
    height: 0 !important;
    opacity: 0 !important;
    margin: 0 !important;
    padding: 0 !important;
    pointer-events: none !important;
}

.phx-segmented-control__track {
    position: relative !important;
    width: 100% !important;
    height: 100% !important;
    display: flex !important;
    align-items: center !important;
    justify-content: space-between !important;
    margin: 0 !important;
    padding: 0 !important;
    border: none !important;
    background: transparent !important;
}

.phx-segmented-control__slider {
    position: absolute !important;
    top: 0 !important;
    left: 0 !important;
    width: 50% !important;
    height: 100% !important;
    /* Container radius minus its 4px padding would be negative; a hair of
       rounding keeps the thumb from looking sharper than the outline. */
    border-radius: calc(var(--md-sys-shape-corner-extra-small, 4px) - 2px) !important;
    /* Glass thumb: a whisper of primary over a backdrop blur, edged with a
       primary hairline. Safe over any surface — including glass panels —
       because nothing here is opaque. */
    background: rgb(var(--md-sys-color-primary) / 0.08) !important;
    border: 1px solid rgb(var(--md-sys-color-primary) / 0.25) !important;
    -webkit-backdrop-filter: blur(8px) saturate(1.3) !important;
    backdrop-filter: blur(8px) saturate(1.3) !important;
    box-shadow: none !important;
    transition: transform 0.2s var(--md-sys-motion-easing-standard, cubic-bezier(0.4, 0, 0.2, 1)) !important;
    z-index: 1 !important;
    box-sizing: border-box !important;
}

.phx-segmented-control__label {
    flex: 1 1 0% !important;
    width: auto !important;
    min-width: 0 !important;
    max-width: none !important;
    height: 100% !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    font-size: 0.875rem !important;
    font-weight: 600 !important;
    color: rgb(var(--md-sys-color-on-surface-variant)) !important;
    cursor: pointer !important;
    z-index: 2 !important;
    transition: color 0.15s ease !important;
    text-align: center !important;
    margin: 0 !important;
    padding: 0 !important;
    float: none !important;
    background: transparent !important;
    border: none !important;
    box-shadow: none !important;
    line-height: normal !important;
}

/* One segment per choice: labels share the width, the thumb is one share
   wide and slides to the checked radio (up to five segments). */
.phx-segmented-control .phx-segmented-control__label {
    padding: 0 16px !important;
    white-space: nowrap !important;
}

.phx-segmented-control__slider {
    width: calc(100% / var(--phx-segmented-control-count, 2)) !important;
}

/* Neutral thumb; the selection is voiced by the primary label. */
.phx-segmented-control__radio:checked + .phx-segmented-control__label {
    color: rgb(var(--md-sys-color-primary)) !important;
}

.phx-segmented-control__track:has(.phx-segmented-control__radio:nth-of-type(1):checked) .phx-segmented-control__slider {
    transform: translateX(0) !important;
}

.phx-segmented-control__track:has(.phx-segmented-control__radio:nth-of-type(2):checked) .phx-segmented-control__slider {
    transform: translateX(100%) !important;
}

.phx-segmented-control__track:has(.phx-segmented-control__radio:nth-of-type(3):checked) .phx-segmented-control__slider {
    transform: translateX(200%) !important;
}

.phx-segmented-control__track:has(.phx-segmented-control__radio:nth-of-type(4):checked) .phx-segmented-control__slider {
    transform: translateX(300%) !important;
}

.phx-segmented-control__track:has(.phx-segmented-control__radio:nth-of-type(5):checked) .phx-segmented-control__slider {
    transform: translateX(400%) !important;
}

/* filled + small: a pill for toolbars and page headers — a grey track with
   a raised white thumb (the outlined + large default is for forms). */
.phx-segmented-control--filled {
    border-radius: 9999px !important;
    border-color: rgb(var(--color-surface-300)) !important;
    background: rgb(var(--color-surface-200)) !important;
    padding: 3px !important;
}

.phx-segmented-control--filled:hover {
    border-color: rgb(var(--color-surface-300)) !important;
}

.phx-segmented-control--small {
    height: var(--phx-size-small) !important;
}

.phx-segmented-control--filled .phx-segmented-control__slider {
    border-radius: 9999px !important;
    background: rgb(var(--color-surface-50)) !important;
    border: 1px solid rgb(0 0 0 / 0.05) !important;
    -webkit-backdrop-filter: none !important;
    backdrop-filter: none !important;
    box-shadow: 0 1px 3px rgb(0 0 0 / 0.08), 0 1px 2px rgb(0 0 0 / 0.04) !important;
}

.phx-segmented-control--filled .phx-segmented-control__label {
    font-size: 0.8125rem !important;
    color: rgb(var(--color-surface-500)) !important;
}

.phx-segmented-control--filled .phx-segmented-control__radio:checked + .phx-segmented-control__label {
    color: rgb(var(--color-surface-900)) !important;
}

@media (prefers-color-scheme: dark) {
    .phx-segmented-control--filled,
    .phx-segmented-control--filled:hover {
        border-color: rgb(var(--color-surface-800)) !important;
        background: rgb(var(--color-surface-900)) !important;
    }

    .phx-segmented-control--filled .phx-segmented-control__slider {
        background: rgb(var(--color-surface-800)) !important;
        border-color: rgb(255 255 255 / 0.08) !important;
        box-shadow: 0 1px 3px rgb(0 0 0 / 0.2), 0 1px 2px rgb(0 0 0 / 0.1) !important;
    }

    .phx-segmented-control--filled .phx-segmented-control__label {
        color: rgb(var(--color-surface-400)) !important;
    }

    .phx-segmented-control--filled .phx-segmented-control__radio:checked + .phx-segmented-control__label {
        color: rgb(var(--color-surface-50)) !important;
    }
}

/* A disabled field disables every segment, so it takes the MD3 disabled
   look: faded labels and outline. */
.phx-segmented-control--locked .phx-segmented-control__label {
    opacity: 0.38 !important;
    cursor: default !important;
}

.phx-segmented-control--locked,
.phx-segmented-control--locked:hover {
    border-color: rgb(var(--md-sys-color-on-surface) / 0.12) !important;
}

/* ── MD3 Outlined Field (pilot: select widget) ──
   Tokens are scoped to .phx-field for now, mirroring the
   .phx-single-select-search__input pattern; hoist to :root once the remaining widgets migrate.
   The outline is a fieldset/legend so the label notch is a real border gap —
   no background patch behind the label, safe over glass surfaces. */

.phx-field {
    --md-sys-color-primary: var(--color-primary-600);
    --md-sys-color-on-primary: 255 255 255;
    --md-sys-color-error: var(--color-destructive-600);
    --md-sys-color-on-surface: var(--color-surface-900);
    --md-sys-color-on-surface-variant: var(--color-surface-600);
    --md-sys-color-outline: var(--color-surface-400);
    /* Approximations of the secondary-container pair from the phoxtail
       palette (no dedicated secondary hue exists yet). */
    --md-sys-color-secondary-container: var(--color-primary-100);
    --md-sys-color-on-secondary-container: var(--color-primary-900);
    --md-sys-color-surface-container-highest: var(--color-surface-200);
    --md-sys-color-surface-container-low: var(--color-surface-100);
    --md-sys-color-outline-variant: var(--color-surface-200);
    --md-sys-motion-easing-standard: cubic-bezier(0.2, 0, 0, 1);
    --md-sys-shape-corner-extra-small: 4px;
}

@media (prefers-color-scheme: dark) {
    .phx-field {
        --md-sys-color-primary: var(--color-primary-400);
        --md-sys-color-on-primary: var(--color-primary-950, 0 0 0);
        --md-sys-color-error: var(--color-destructive-400);
        --md-sys-color-on-surface: var(--color-surface-100);
        --md-sys-color-on-surface-variant: var(--color-surface-400);
        --md-sys-color-outline: var(--color-surface-600);
        --md-sys-color-secondary-container: var(--color-primary-900);
        --md-sys-color-on-secondary-container: var(--color-primary-100);
        --md-sys-color-surface-container-highest: var(--color-surface-700);
        --md-sys-color-surface-container-low: var(--color-surface-800);
        --md-sys-color-outline-variant: var(--color-surface-700);
    }
}

.phx-field__box {
    position: relative;
    display: flex;
    align-items: center;
    /* MD3 default field height is 56dp; drop to 40px if a -2 density is
       preferred for dense forms. */
    height: 56px;
}

/* Structural props carry !important as armor against host-app admin CSS
   (Wagtail restyles input/select/textarea/label/legend/fieldset globally,
   sometimes with attribute selectors that out-rank a single class). State
   rules (focus, error, disabled) target the sibling outline/label, so they
   are unaffected by these. */
.phx-field__control {
    appearance: none !important;
    -webkit-appearance: none !important;
    width: 100% !important;
    height: 100%;
    margin: 0 !important;
    padding: 0 1rem !important;
    border: none !important;
    outline: none !important;
    box-shadow: none !important;
    background: transparent !important;
    font-size: 1rem !important;
    font-family: inherit !important;
    font-weight: 400 !important;
    line-height: normal;
    color: rgb(var(--md-sys-color-on-surface)) !important;
    border-radius: var(--md-sys-shape-corner-extra-small) !important;
    box-sizing: border-box !important;
}

select.phx-field__control {
    cursor: pointer;
}

/* MD3 fields don't show native number spinners; the trailing area stays clean. */
input.phx-field__control[type="number"] {
    -moz-appearance: textfield;
}

input.phx-field__control[type="number"]::-webkit-outer-spin-button,
input.phx-field__control[type="number"]::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

/* Reserve room for the trailing icon (24dp icon + 12dp inset per spec). */
.phx-field__box:has(.phx-field__trailing, .phx-field__trailing-button) .phx-field__control {
    padding-right: 3rem !important;
}

/* Two trailing buttons (a secret's show/hide beside its copy): the eye moves
   one button inwards, and the box keeps room for both. */
.phx-field__box:has([data-copy]) [data-password-toggle] {
    right: 2.75rem;
}

.phx-field__box:has([data-copy]):has([data-password-toggle]) .phx-field__control {
    padding-right: 5.5rem !important;
}

/* A caller-supplied placeholder must not fight the resting label for the
   same spot: per MD3 it only shows once the label has floated (focus). The
   single-space float-driver placeholder is unaffected — it has no glyphs. */
.phx-field__control:not(:focus)::placeholder {
    color: transparent;
}

.phx-field__control:focus::placeholder {
    color: rgb(var(--md-sys-color-on-surface-variant));
}

/* Split phone field: the country prefix and the national number are separate
   controls, each in its own outline, sharing the row evenly. Below the
   breakpoint an even half would clip the country name, so the pair stacks
   instead. Containment sits on .phx-field, not the row: a container query
   cannot size an element against a context that element establishes. */
/* A fieldset (the two parts are one answer); its default border, padding
   and min-content width go. One row at every width, as a phone number is
   written: a narrow country box — its choices lead with the code, so the
   code stays in view when the name is cut off — and the number. The gap is
   the form's own gap between fields (--phx-field-gap), so the pair keeps the
   form's rhythm. */
.phx-phone {
    min-width: 0;
    margin: 0;
    padding: 0;
    border: 0;
    display: grid;
    grid-template-columns: 8rem minmax(0, 1fr);
    gap: var(--phx-field-gap, 1.5rem);
}

/* A native select cuts its text off without an ellipsis; a country name too
   long for the box fades out before the arrow instead of stopping mid-letter.
   The text ends 3rem from the right, where the arrow's space begins. */
.phx-phone__prefix .phx-field__control {
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 4.25rem), transparent calc(100% - 3rem));
    mask-image: linear-gradient(to right, #000 calc(100% - 4.25rem), transparent calc(100% - 3rem));
}

/* Multiline variant: the container grows with the textarea and the resting
   label pins to the first text line instead of the vertical center. */
.phx-field__box--textarea {
    height: auto;
    min-height: 56px;
}

textarea.phx-field__control {
    padding: 1rem !important;
    resize: vertical;
    line-height: 1.5rem;
    min-height: 56px;
}

.phx-field__box--textarea .phx-field__label {
    top: 1.75rem;
}

.phx-field__control:focus ~ .phx-field__label,
.phx-field__control:not(:placeholder-shown) ~ .phx-field__label {
    /* Repeated after the --textarea override so floating wins there too. */
    top: 0;
}

/* Interactive trailing slot (password visibility, date/time pickers):
   24dp icon centered in a 40dp round target, 4dp from the field edge so the
   icon itself sits at the spec's 12dp inset. */
.phx-field__trailing-button {
    position: absolute;
    right: 0.25rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: transparent;
    color: rgb(var(--md-sys-color-on-surface-variant));
    cursor: pointer;
    transition: background-color 150ms var(--md-sys-motion-easing-standard);
}

.phx-field__trailing-button:hover {
    background-color: rgb(var(--md-sys-color-on-surface) / 0.08);
}

.phx-field__trailing-button:focus-visible {
    outline: 2px solid rgb(var(--md-sys-color-primary));
    outline-offset: 1px;
}

/* On a touch screen the picker buttons let the tap through to the box under
   them, which opens the browser's own picker: iOS opens none from script. */
@media (any-pointer: coarse) {
    .phx-field__trailing-button[data-picker-open] {
        pointer-events: none;
    }
}

.phx-field__trailing-button svg {
    width: 1.5rem;
    height: 1.5rem;
    display: block;
}

/* Native pickers get our trailing button instead of the browser's inline
   indicator. Unscoped from :has() and !important-ed: Wagtail admin ships its
   own date-input chrome, which otherwise leaves two calendar icons side by
   side. background-image is re-asserted for the same reason — some admin
   skins paint an icon onto the input itself. */
.phx-field input.phx-field__control::-webkit-calendar-picker-indicator {
    display: none !important;
    -webkit-appearance: none !important;
    opacity: 0 !important;
    width: 0 !important;
    margin: 0 !important;
    padding: 0 !important;
}

.phx-field input.phx-field__control,
.phx-field select.phx-field__control {
    background-image: none !important;
}

/* Firefox exposes no pseudo-element for its native date-picker icon, which
   it paints just inside the input's right padding edge. Shrink the right
   padding so the icon lands entirely within the trailing-button strip, then
   clip that strip away — our trailing button is a sibling, so it is not
   clipped and remains the single visible calendar icon. Scoped to Firefox
   via @supports; in Chromium the indicator is hidden by the rule above. */
@supports (-moz-appearance: none) {
    .phx-field__box:has(.phx-field__trailing-button) input.phx-field__control {
        padding-right: 0.5rem !important;
        clip-path: inset(0 2.75rem 0 0);
    }

    .phx-field__box:has([data-copy]):has([data-password-toggle]) input.phx-field__control {
        clip-path: inset(0 5.25rem 0 0);
    }
}

/* Group label for checkbox/radio groups: styled like a floated field label,
   since these controls have no container to notch it into. */
.phx-field__group-label {
    display: block;
    margin-bottom: 0.5rem;
    font-size: 0.75rem;
    line-height: 1rem;
    color: rgb(var(--md-sys-color-on-surface-variant));
}

.phx-field--error .phx-field__group-label {
    color: rgb(var(--md-sys-color-error));
}

/* ── MD3 anatomy for the search-family widgets ──
   (single_select_search). The pill trigger becomes the
   outlined field's control; label/outline live outside the HTMX swap target,
   so float state is driven by :has() — a hidden input exists only while
   something is selected, and aria-expanded flags an open panel. */

/* The outlined wrapper is a flex row; without explicit sizes the swap
   container shrinks to its content (an empty trigger label), leaving only a
   small clickable square — force the control chain to fill the field. */
.phx-single-select-search__box .phx-single-select-search__container,
.phx-single-select-search__box .phx-single-select-search__input {
    height: 100%;
    width: 100%;
    min-width: 0;
}

.phx-single-select-search__trigger.phx-field__control {
    display: flex !important;
    align-items: center;
    gap: 0.5rem;
    cursor: pointer;
    text-align: left;
    /* Rich item templates can render multi-line content taller than the
       56px field — clip instead of spilling over the outline. */
    overflow: hidden;
}

/* Optional trigger placeholder: hidden while closed (the resting label
   occupies that spot), revealed while the panel is open — MD3 placeholder
   semantics. */
.phx-single-select-search__placeholder {
    opacity: 0;
    color: rgb(var(--md-sys-color-on-surface-variant));
    transition: opacity 150ms var(--md-sys-motion-easing-standard);
}

.phx-single-select-search__box:has(.phx-single-select-search__trigger[aria-expanded="true"]) .phx-single-select-search__placeholder {
    opacity: 1;
}

/* Float the label / open the notch when something is selected (hidden input
   present) or the panel is open. */
.phx-single-select-search__box:has(input[type="hidden"]) .phx-field__label,
.phx-single-select-search__box:has(.phx-single-select-search__trigger[aria-expanded="true"]) .phx-field__label {
    top: 0;
    font-size: 0.75rem;
}

.phx-single-select-search__box:has(input[type="hidden"]) .phx-field__notch,
.phx-single-select-search__box:has(.phx-single-select-search__trigger[aria-expanded="true"]) .phx-field__notch {
    padding: 0 0.25rem;
    max-width: 100%;
}

/* Open/keyboard-focused trigger mirrors the control focus state. */
.phx-single-select-search__box:has(.phx-single-select-search__trigger[aria-expanded="true"]) .phx-field__outline,
.phx-single-select-search__box:has(.phx-single-select-search__trigger:focus-visible) .phx-field__outline {
    border-width: 2px;
    border-color: rgb(var(--md-sys-color-primary));
}

.phx-single-select-search__box:has(.phx-single-select-search__trigger[aria-expanded="true"]) .phx-field__label {
    color: rgb(var(--md-sys-color-primary));
}

/* Error keeps the whole field in error color, beating the open-state primary
   (same specificity, later in the cascade). */
.phx-field--error .phx-single-select-search__box .phx-field__outline {
    border-color: rgb(var(--md-sys-color-error));
}

.phx-field--error .phx-single-select-search__box .phx-field__label {
    color: rgb(var(--md-sys-color-error));
}

/* filled + small: a pill for a toolbar, as the search field's. No outline;
   the label stays for assistive technology, the placeholder names the field. */
.phx-single-select-search--small .phx-single-select-search__box {
    height: var(--phx-size-small);
}

.phx-single-select-search--filled .phx-single-select-search__box {
    background: var(--phx-control-background);
    box-shadow: var(--phx-control-shadow);
    border-radius: 999px;
    transition: background-color 150ms ease, box-shadow 200ms ease;
}

.phx-single-select-search--filled .phx-single-select-search__box:hover {
    background: var(--phx-control-background-hover);
    box-shadow: var(--phx-control-shadow-hover);
}

.phx-single-select-search--filled .phx-single-select-search__box:has(.phx-single-select-search__trigger[aria-expanded="true"]),
.phx-single-select-search--filled .phx-single-select-search__box:has(.phx-single-select-search__trigger:focus-visible) {
    outline: 2px solid rgb(var(--color-primary-600));
    outline-offset: 2px;
}

.phx-single-select-search--filled .phx-field__outline {
    display: none !important;
}

.phx-single-select-search--filled .phx-field__label {
    position: absolute !important;
    width: 1px !important;
    height: 1px !important;
    overflow: hidden !important;
    clip: rect(0 0 0 0) !important;
    white-space: nowrap !important;
}

.phx-single-select-search--filled .phx-single-select-search__trigger.phx-field__control {
    border-radius: 999px !important;
    font-size: 0.875rem !important;
}

.phx-single-select-search--filled .phx-single-select-search__placeholder {
    opacity: 1;
    color: rgb(var(--color-surface-600));
    font-weight: 600;
}

@media (prefers-color-scheme: dark) {
    .phx-single-select-search--filled .phx-single-select-search__box:has(.phx-single-select-search__trigger[aria-expanded="true"]),
    .phx-single-select-search--filled .phx-single-select-search__box:has(.phx-single-select-search__trigger:focus-visible) {
        outline-color: rgb(var(--color-primary-400));
    }

    .phx-single-select-search--filled .phx-single-select-search__placeholder {
        color: rgb(var(--color-surface-300));
    }
}

.phx-field__control option {
    background-color: rgb(var(--color-surface-50));
    color: rgb(var(--color-surface-900));
}

@media (prefers-color-scheme: dark) {
    .phx-field__control option {
        background-color: rgb(var(--color-surface-800));
        color: rgb(var(--color-surface-100));
    }
}

/* Label rests inside the field (body-large, vertically centered) and floats
   into the outline notch (body-small) on focus or when populated. "Populated"
   is :not(:placeholder-shown): text/number controls carry a single-space
   placeholder for exactly this, and a <select> can never match
   :placeholder-shown, so its label is permanently floated — correct, since a
   native select always renders a selection. */
.phx-field__label {
    position: absolute !important;
    top: 50%;
    left: 1rem !important;
    transform: translateY(-50%);
    display: block !important;
    margin: 0 !important;
    padding: 0 !important;
    font-size: 1rem;
    font-weight: 400 !important;
    line-height: 1 !important;
    color: rgb(var(--md-sys-color-on-surface-variant));
    pointer-events: none;
    cursor: default;
    transition: top 150ms var(--md-sys-motion-easing-standard),
                font-size 150ms var(--md-sys-motion-easing-standard),
                color 150ms var(--md-sys-motion-easing-standard);
}

.phx-field__control:focus ~ .phx-field__label,
.phx-field__control:not(:placeholder-shown) ~ .phx-field__label {
    top: 0;
    font-size: 0.75rem;
}

/* The outline itself. Top inset compensates for the legend's line box so the
   border-top aligns with the visual top of the field. */
.phx-field__outline {
    position: absolute !important;
    inset: -0.375rem 0 0 0 !important;
    display: block !important;
    width: auto !important;
    min-width: 0 !important;
    margin: 0 !important;
    /* 12px + the notch's 4px side padding = legend text starts at 16px,
       exactly under the floated label. */
    padding: 0 0.75rem !important;
    border: 1px solid rgb(var(--md-sys-color-outline));
    border-radius: var(--md-sys-shape-corner-extra-small) !important;
    background: transparent !important;
    box-shadow: none !important;
    pointer-events: none;
    transition: border-color 200ms var(--md-sys-motion-easing-standard);
}

/* The border itself stays un-!important-ed (focus/error swap width/color),
   but everything that lets the legend cut its notch gap is armored:
   Wagtail's admin CSS floats legends inline at 16.67% width, which silently
   disables the fieldset notch. */
.phx-field__notch,
fieldset.phx-field__outline > legend.phx-field__notch {
    float: none !important;
    display: block !important;
    position: static !important;
    width: auto !important;
    margin: 0 !important;
    border: 0 !important;
    height: auto !important;
    visibility: visible !important;
}

/* The notch is collapsed while the label rests inside the field and opens
   (4dp padding each side, per spec) when the label floats. */
.phx-field__notch {
    padding: 0;
    max-width: 0;
    white-space: nowrap;
    font-size: 0.75rem;
    line-height: 0.75rem;
    max-height: 0.75rem;
    transition: max-width 150ms var(--md-sys-motion-easing-standard),
                padding 150ms var(--md-sys-motion-easing-standard);
}

.phx-field__control:focus ~ .phx-field__outline .phx-field__notch,
.phx-field__control:not(:placeholder-shown) ~ .phx-field__outline .phx-field__notch {
    padding: 0 0.25rem;
    max-width: 100%;
}

/* Invisible twin of the label text — only there to size the border gap. */
.phx-field__notch > span {
    visibility: hidden;
}

/* Explicitly label-less fields must never open a gap in the top border —
   !important so the focus/populated notch-opening states can't override. */
.phx-field__notch--empty {
    padding: 0 !important;
    max-width: 0 !important;
    width: 0 !important;
}

/* An empty legend has no line box, so the fieldset would draw its top border
   at the fieldset's own top edge — 6px above the field — instead of pushing
   it down through the legend's middle like labeled fields do. A zero-width
   space restores the line box without opening a notch. */
.phx-field__notch--empty::before {
    content: "\200B";
}

.phx-field__trailing {
    position: absolute;
    right: 0.75rem;
    width: 1.5rem;
    height: 1.5rem;
    color: rgb(var(--md-sys-color-on-surface-variant));
    pointer-events: none;
    transition: color 200ms var(--md-sys-motion-easing-standard);
}

/* States: hover darkens the outline, focus thickens it to 2px in primary —
   no glow/box-shadow halo, per MD3. */
.phx-field__box:hover .phx-field__outline {
    border-color: rgb(var(--md-sys-color-on-surface));
}

.phx-field__control:focus ~ .phx-field__outline {
    border-width: 2px;
    border-color: rgb(var(--md-sys-color-primary));
}

.phx-field__control:focus ~ .phx-field__label {
    color: rgb(var(--md-sys-color-primary));
}

/* Error state colors the whole field, not just the message. */
.phx-field--error .phx-field__outline,
.phx-field--error .phx-field__box:hover .phx-field__outline,
.phx-field--error .phx-field__control:focus ~ .phx-field__outline {
    border-color: rgb(var(--md-sys-color-error));
}

.phx-field--error .phx-field__label,
.phx-field--error .phx-field__control:focus ~ .phx-field__label,
.phx-field--error .phx-field__supporting {
    color: rgb(var(--md-sys-color-error));
}

/* Disabled: a value to read, not to type. MD3 fades it (38% content, 12%
   outline), which reads poorly; here the box fills with a surface shade
   instead and keeps its text at full contrast. */
.phx-field__control:disabled {
    color: rgb(var(--md-sys-color-on-surface));
    -webkit-text-fill-color: rgb(var(--md-sys-color-on-surface));
    opacity: 1;
    cursor: default;
}

/* The fill lies under the text: the outline is drawn after the control, so
   it goes behind it, inside the box's own stacking context. */
.phx-field__box:has(> .phx-field__control:disabled) {
    isolation: isolate;
}

.phx-field__control:disabled ~ .phx-field__outline {
    z-index: -1;
    border-color: transparent;
    background: rgb(var(--md-sys-color-surface-container-highest) / 0.6) !important;
}

.phx-field__control:disabled ~ .phx-field__label,
.phx-field__control:disabled ~ .phx-field__trailing {
    color: rgb(var(--md-sys-color-on-surface-variant));
}

/* The copied check, in the brand colour. */
.phx-field__copy-icon--done {
    color: rgb(var(--md-sys-color-primary));
}

/* Supporting text replaces the hover help tooltip; also hosts errors. */
.phx-field__supporting {
    margin: 0.25rem 0 0 !important;
    padding: 0 1rem !important;
    font-size: 0.75rem !important;
    font-weight: 400 !important;
    line-height: 1rem !important;
    color: rgb(var(--md-sys-color-on-surface-variant));
}

.phx-field__supporting span {
    display: block;
}

/* ── Dark Mode ── */

@media (prefers-color-scheme: dark) {
    /* Choice, toggle, and outlined segmented widgets are dark-mode-aware
       through the .phx-field token block; the filled segmented pill has its own
       dark rules beside it. */

    /* Search — dark mode tokens are handled by .phx-single-select-search__input media query above */

    /* Multi Select Chips — dark mode handled by the .phx-field token block. */
}
