:where(date-calendar, date-picker) {
  --dp-bg: #ffffff;
  --dp-fg: #1f2328;
  --dp-muted: color-mix(in srgb, var(--dp-fg) 58%, var(--dp-bg));
  --dp-border: color-mix(in srgb, var(--dp-fg) 16%, var(--dp-bg));
  --dp-hover: color-mix(in srgb, var(--dp-fg) 5%, var(--dp-bg));
  --dp-accent: #2563eb;
  --dp-accent-fg: #fff;
  --dp-focus: var(--dp-accent);
  --dp-focus-width: 2px;
  --dp-radius: 0.5rem;
  --dp-day-size: 2.75rem;
  --dp-gap: 0.375rem;
  --dp-header-control-size: 2.25rem;
  --dp-header-block-gap: 0.75rem;
  --dp-row-gap: 0.375rem;
  --dp-picker-button-size: 2.5rem;
  --dp-year-inline-size: 5.5rem;
  --dp-day-radius: calc(var(--dp-radius) * 0.75);
  color: var(--dp-fg);
  font: inherit;
}

.dp-visually-hidden {
  position: absolute !important;
  inline-size: 1px !important;
  block-size: 1px !important;
  padding: 0 !important;
  margin: -1px !important;
  overflow: hidden !important;
  clip: rect(0 0 0 0) !important;
  white-space: nowrap !important;
  border: 0 !important;
}

date-calendar {
  display: block;
  inline-size: max-content;
  max-inline-size: 100%;
}

.dp-calendar-shell {
  inline-size: max-content;
  max-inline-size: 100%;
}

.dp-calendar-header {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto auto;
  /* Stretch (not center): once a UA natural height exceeds
     --dp-header-control-size, the row grows to the tallest control and the
     others stretch to match, so month/year/nav stay equal. */
  align-items: stretch;
  /* Uniform horizontal rhythm: the four header controls are self-evident from
     their kind and position, so no group gets an extra semantic gap. The air
     belongs to the vertical zones (header -> weekdays -> dates). */
  gap: var(--dp-gap);
  margin-block-end: var(--dp-header-block-gap);
}

/* Locale year-first order (Intl-derived, direction-independent): the flexible
   track stays under the month select so the fixed-width year input never
   stretches. Visual mirroring itself is left to the inherited `dir`. */
date-calendar[data-year-first] .dp-calendar-header {
  grid-template-columns: auto minmax(0, 1fr) auto auto;
}

.dp-calendar-header :where(button, select, input) {
  min-block-size: var(--dp-header-control-size);
  box-sizing: border-box;
  /* Shared vertical metrics: UA default padding/line-height differ per control
     (up to ~13px apart), which only shows once --dp-header-control-size drops
     below content size. */
  padding-block: 0.15rem;
  border: 1px solid var(--dp-border);
  border-radius: calc(var(--dp-radius) * 0.75);
  background: var(--dp-bg);
  color: var(--dp-fg);
  font: inherit;
  line-height: 1.2;
}

.dp-calendar-header input {
  min-inline-size: 0;
  padding-inline: 0.45rem;
}

/* Author-drawn caret so the month select matches the nav controls without a
   hardcoded SVG color (currentColor keeps theming). Equal outer heights come
   from the header grid's stretch alignment: the row sizes to the tallest
   control and the others stretch to match. */
.dp-month-select {
  inline-size: 100%;
  min-inline-size: 0;
  /* Long month names in a narrow track (compact consumers, long locales)
     would paint under the caret: truncate with an ellipsis instead. */
  overflow: hidden;
  text-overflow: ellipsis;
  appearance: none;
  padding-inline: 0.45rem 2rem;
  background-image:
    linear-gradient(45deg, transparent 50%, currentColor 50%),
    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position:
    calc(100% - 0.9rem) 50%,
    calc(100% - 0.65rem) 50%;
  background-size: 0.3rem 0.3rem;
  background-repeat: no-repeat;
}

/* Inherited RTL mirrors the header layout via the grid. The logical
   `padding-inline` already flips, so only the physically-positioned caret has
   to follow it to the other side. */
[dir="rtl"] .dp-month-select,
html[dir="rtl"] .dp-month-select {
  background-position:
    0.9rem 50%,
    0.65rem 50%;
}

.dp-year-input {
  inline-size: var(--dp-year-inline-size);
}

.dp-nav {
  display: grid;
  place-items: center;
  inline-size: var(--dp-header-control-size);
  padding: 0;
  font-size: 1.35rem;
  line-height: 1;
  cursor: pointer;
}

.dp-nav svg {
  display: block;
  inline-size: 1rem;
  block-size: 1rem;
  pointer-events: none;
}

.dp-calendar-header :where(button, select, input):disabled,
.dp-picker-button:disabled {
  cursor: not-allowed;
  opacity: 0.45;
}

.dp-nav:hover:not(:disabled) {
  background: var(--dp-hover);
}

/* Inner outlines survive forced colors and keep focus inside each control.
   The picker trigger uses a tighter inset around its icon below. */
.dp-calendar-header :where(button, select, input):focus-visible,
date-picker > input:not([type="hidden"]):focus-visible,
.dp-day:focus-visible {
  outline: var(--dp-focus-width) solid var(--dp-focus);
  outline-offset: calc(var(--dp-focus-width) * -1);
}

.dp-day:hover:not([data-disabled="true"]):not([data-selected="true"]):not([data-range-start="true"]):not(
  [data-range-end="true"]
) {
  background: var(--dp-hover);
}

/* .dp-calendar-heading is always visually hidden: it names the grid via
   aria-labelledby and stays the aria-live announcement channel while the
   month/year selects render the same info visually. */

.dp-grid {
  border-collapse: separate;
  /* --dp-gap scopes to the header grid; vertical week rhythm is --dp-row-gap. */
  border-spacing: 0 var(--dp-row-gap);
  table-layout: fixed;
}

.dp-grid :where(th, td) {
  box-sizing: border-box;
  inline-size: var(--dp-day-size);
  block-size: var(--dp-day-size);
  padding: 0;
  text-align: center;
}

.dp-grid thead th {
  block-size: 1.5rem;
  color: var(--dp-muted);
  font-size: 0.72rem;
  font-weight: 500;
}

.dp-day {
  position: relative;
  border: 1px solid transparent;
  border-radius: var(--dp-day-radius);
  cursor: pointer;
  outline: none;
  vertical-align: middle;
  font-size: 0.875rem;
}

/* On an accent-filled cell the ring inverts so it stays readable. */
.dp-day:is([data-selected="true"], [data-range-start="true"], [data-range-end="true"]):focus-visible {
  outline-color: var(--dp-accent-fg);
}

/* Base tint for days outside the displayed month. It stays before the
   selection states so selected/range endpoints keep their accent-contrast
   text on the accent fill (equal specificity, source order decides). */
.dp-day[data-outside-month="true"] {
  color: var(--dp-muted);
}

.dp-day[data-selected="true"] {
  background: var(--dp-accent);
  color: var(--dp-accent-fg);
}

/* Today never competes with a stronger state: a selected day or a range
   endpoint keeps its own treatment, in normal rendering and in
   forced-colors alike. */
.dp-day[data-today="true"]:not([data-selected="true"], [data-range-start="true"], [data-range-end="true"]) {
  border-color: var(--dp-accent);
}

.dp-day[data-disabled="true"] {
  cursor: not-allowed;
  opacity: 0.42;
}

.dp-day[data-range-start="true"],
.dp-day[data-range-end="true"] {
  background: var(--dp-accent);
  color: var(--dp-accent-fg);
}

.dp-day[data-in-range="true"] {
  border-radius: 0;
  background: color-mix(in srgb, var(--dp-accent) 18%, var(--dp-bg));
}

/* Join the band without gaps, including the corners beside each endpoint. */
.dp-day[data-range-start="true"]:has(+ [data-in-range="true"], + [data-range-end="true"]) {
  border-start-end-radius: 0;
  border-end-end-radius: 0;
}

.dp-day:is([data-in-range="true"], [data-range-start="true"]) + .dp-day[data-range-end="true"] {
  border-start-start-radius: 0;
  border-end-start-radius: 0;
}

.dp-day[data-in-range="true"]:first-of-type {
  border-start-start-radius: var(--dp-day-radius);
  border-end-start-radius: var(--dp-day-radius);
}

.dp-day[data-in-range="true"]:last-of-type {
  border-start-end-radius: var(--dp-day-radius);
  border-end-end-radius: var(--dp-day-radius);
}

/* Projected band: the range the next commit would produce. It reads as one
   step short of the committed band, so a hovered, keyboard or dragged preview
   is never mistaken for the selection itself. */
[data-range-preview] .dp-day:is([data-range-start="true"], [data-range-end="true"]) {
  background: color-mix(in srgb, var(--dp-accent) 58%, var(--dp-bg));
}

[data-range-preview] .dp-day[data-in-range="true"] {
  background: color-mix(in srgb, var(--dp-accent) 11%, var(--dp-bg));
}

/* Endpoint handles are draggable only while the committed range is complete
   and its two ends sit on different days. */
[data-range-drag] .dp-day:is([data-range-start="true"], [data-range-end="true"]) {
  cursor: grab;
}

[data-range-drag="active"],
[data-range-drag="active"] .dp-day {
  cursor: grabbing;
}

.dp-day-number {
  display: block;
  font-variant-numeric: tabular-nums;
}

/* A focused disabled day stays discoverable by keyboard: restore full opacity
   so the focus outline renders at full strength, and mark the number with the
   muted tone (same language as outside-month days) instead of the wash-out. */
.dp-day[data-disabled="true"]:focus-visible {
  opacity: 1;
}

.dp-day[data-disabled="true"]:focus-visible .dp-day-number {
  color: var(--dp-muted);
}

.dp-day-extra {
  position: absolute;
  inset-inline: 2px;
  inset-block-end: 1px;
  display: flex;
  justify-content: center;
  gap: 2px;
  min-block-size: 0.35rem;
  font-size: 0.55rem;
  line-height: 1;
  pointer-events: none;
}

.dp-week-number,
.dp-week-heading {
  inline-size: 1.6rem !important;
  color: var(--dp-muted);
  font-size: 0.65rem;
  font-weight: 500;
}

date-picker {
  position: relative;
  display: inline-grid;
  grid-template-columns: minmax(0, 1fr);
  align-items: stretch;
  max-inline-size: 100%;
}

/* Every authored control is a grid item. */
date-picker > input:not([type="hidden"]) {
  min-inline-size: 0;
}

/* Date fields reserve room for the trigger, which is painted inside the
   field's own box: the field is the real outer box, so its focus ring wraps
   the affordance too. `grid-row` must stay explicit, otherwise the trigger
   (placed with a definite row) claims the row and pushes the field down. */
date-picker > input:not([type="hidden"]):not([type="time"]) {
  grid-column: 1;
  grid-row: 1;
  box-sizing: border-box;
  inline-size: 100%;
  padding-inline-end: calc(var(--dp-picker-button-size) + 0.5rem);
}

/* The trigger is a real button overlaid on the field's inline-end, like the
   native `input[type=time]` indicator: no chrome of its own, transparent, so
   the authored field background and border stay visible underneath. */
.dp-picker-button {
  display: grid;
  place-items: center;
  grid-column: 1;
  grid-row: 1;
  justify-self: end;
  align-self: stretch;
  inline-size: var(--dp-picker-button-size);
  min-inline-size: 0;
  border: 0;
  background: transparent;
  color: var(--dp-fg);
  font: inherit;
  cursor: pointer;
}

/* Like the native time indicator: the ring wraps the icon, not the field (the
   field already shows its own ring through :focus-visible). Same radius as
   everywhere else: no bespoke shape. */
.dp-picker-button:focus-visible {
  outline: var(--dp-focus-width) solid var(--dp-focus);
  outline-offset: -5px;
  border-radius: var(--dp-radius);
}

/* Optional native time companions share the date row; authored inputs stay
   consumer-styled, the picker only reserves their grid cells. Time tracks are
   flexible (never `auto`) so a wide UA time control cannot squeeze the date.
   Each companion keeps its own box and its own gap: nothing is joined, so
   focus rings never merge and no neighbour swallows another's focus. */
date-picker:has(> [data-time-start], > [data-time-end]) {
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  column-gap: var(--dp-gap);
}

date-picker:has(> [data-time-start]):has(> [data-time-end]) {
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr);
}

date-picker > input[data-time-start] {
  grid-column: 2;
  grid-row: 1;
  min-inline-size: 0;
}

date-picker > input[data-time-end] {
  grid-column: 3;
  grid-row: 1;
  min-inline-size: 0;
}

/* Range: two stacked fields, each owning its trigger, sharing one popup and
   one calendar. No trigger spans both bounds, so each bound keeps a local
   affordance and a local focus target. */
date-picker[range] {
  row-gap: var(--dp-gap);
}

date-picker[range] > input[data-range-start] {
  grid-row: 1;
}

date-picker[range] > input[data-range-end] {
  grid-row: 2;
}

date-picker[range] > .dp-picker-button[data-endpoint="start"] {
  grid-row: 1;
}

date-picker[range] > .dp-picker-button[data-endpoint="end"] {
  grid-row: 2;
}

.dp-picker-panel[popover] {
  /* Safe baseline. show() switches to absolute only when the consumer
   * explicitly selects document coordinate space. */
  position: fixed;
  inset: auto;
  margin: 0;
  padding: 0.875rem 1rem;
  border: 1px solid var(--dp-border);
  border-radius: var(--dp-radius);
  background: var(--dp-bg);
  color: var(--dp-fg);
  box-shadow: 0 0.5rem 1.5rem rgb(15 23 42 / 0.12);
  max-block-size: var(--available-height, 90svh);
  max-inline-size: calc(100vi - 1rem);
  overflow: auto;
}

.dp-picker-panel:not(:popover-open) {
  display: none;
}

@media (forced-colors: active) {
  /* The author-drawn caret is a gradient and disappears here: hand the
     control back to the browser instead of trying to rebuild it. */
  .dp-month-select,
  [dir="rtl"] .dp-month-select {
    appearance: auto;
    background-image: none;
    padding-inline: 0.45rem;
  }

  /* Fills vanish here, so selection and endpoints fall back to a 2px
     Highlight border. The in-range underline is the only band marker left:
     the range fill is lost and the browser does not know the semantics. */
  .dp-day:is([data-selected="true"], [data-range-start="true"], [data-range-end="true"]) {
    border: 2px solid Highlight;
    background-color: Canvas;
    color: CanvasText;
  }

  .dp-day[data-in-range="true"] {
    color: CanvasText;
  }

  .dp-day[data-in-range="true"]::after {
    content: "";
    position: absolute;
    inset-inline: 3px;
    inset-block-end: 4px;
    block-size: 1px;
    background-color: Highlight;
  }

  /* Pin the today marker: the deterministic accent is a non-system color
     and would otherwise remap unpredictably here. */
  .dp-day[data-today="true"] {
    border-color: Highlight;
  }

  .dp-day-extra {
    color: CanvasText;
    forced-color-adjust: none;
  }
}
