/* ==========================================================================
   الكشاف — the control layer
   Loaded after app.css. Owns two things and nothing else:

     1. the container width scale, and the header/main/footer alignment
        that hangs off it;
     2. every form control, under the `f-` namespace.

   The `f-` classes are a contract shared with the admin implementation, so
   nothing here may be renamed without renaming it there too.

   Everything is written with logical properties. No physical left/right.
   ========================================================================== */

:root {
  /* ---- the one container scale --------------------------------------- */
  /* The page container. Header inner, main inner and footer inner are all
     clamped to this, so their edges coincide at every width. */
  --container-max: 64rem;

  /* The narrow reading measure: forms, the test runner, prose. Centred
     inside the page container, never a second alignment origin. */
  --container-narrow: 30rem;

  /* The side gutter, identical for all three bands. Header, content and
     footer take it from the same property, which is the whole point. */
  --container-gutter: clamp(1.25rem, 0.75rem + 1.25vw, 2rem);

  /* The floating header pill's outer box: the container plus its gutters,
     so the pill's *inner* content lines up with the page content exactly. */
  --header-outer: calc(var(--container-max) + 2 * var(--container-gutter));
  --header-block-size: 4.25rem;

  /* ---- control tokens ------------------------------------------------ */
  --f-radius: 0.875rem;
  --f-radius-lg: 1.125rem;
  --f-border: var(--border);
  --f-border-strong: #d9d5e8;
  --f-ring: 0 0 0 4px var(--primary-soft);
  --f-control-size: 3rem;
  --f-pad-inline: 0.9375rem;
  --f-menu-shadow: 0 24px 56px -16px rgba(24, 21, 42, 0.32);
  --f-z-popup: 120;
}

/* ==========================================================================
   1. Shell alignment
   ==========================================================================
   The complaint this answers: the header, the content and the footer did not
   share an edge. They do now, and the proof is that all three inner elements
   resolve to the same box — `min(container-max, viewport - 2*gutter)`,
   centred — by the same two declarations.
*/

.site-header {
  /* The fixed band. It carries no chrome of its own; the pill inside does. */
  position: fixed;
  inset-block-start: 0;
  inset-inline: 0;
  z-index: 50;
  display: block;
  max-inline-size: none;
  padding: 0;
  border: 0;
  background: none;
  box-shadow: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

/* The pill: the reference project's floating bar, widened to the page
   container so its content can share the container's edges. Its 1px inline
   border is subtracted from the inner padding below, which is why the inner
   element lands exactly on the gutter and not one pixel inside it. */
.site-header__bar {
  max-inline-size: var(--header-outer);
  margin-inline: auto;
  padding-inline: calc(var(--container-gutter) - 1px);
  border: 1px solid var(--border);
  border-block-start: 0;
  border-end-start-radius: var(--radius-2xl);
  border-end-end-radius: var(--radius-2xl);
  background: rgba(255, 255, 255, 0.75);
  box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-block-size: var(--header-block-size);
  padding-block: 0.625rem;
}

.site-main {
  padding-inline: var(--container-gutter);
  padding-block-start: calc(var(--header-block-size) + clamp(1rem, 0.5rem + 2vw, 2.5rem));
  padding-block-end: clamp(1.5rem, 1rem + 3vw, 3.5rem);
}

.site-main__inner {
  inline-size: 100%;
  max-inline-size: var(--container-max);
  margin-inline: auto;
}

/* The footer is the header bar inverted: same outer width, same inner
   padding, same 1px border subtracted from it, so `.site-footer__inner`
   lands on the identical edges. Only the rounded corners and the missing
   edge move to the other side. The band itself adds nothing — no full-width
   background, no full-width rule — because a hairline running the whole
   viewport is exactly what made the footer read as full width. */
.site-footer {
  padding: 0;
  border-block-start: 0;
  background: none;
}

.site-footer__bar {
  max-inline-size: var(--header-outer);
  margin-inline: auto;
  padding-inline: calc(var(--container-gutter) - 1px);
  border: 1px solid var(--border);
  border-block-end: 0;
  border-start-start-radius: var(--radius-2xl);
  border-start-end-radius: var(--radius-2xl);
  background: rgba(255, 255, 255, 0.7);
  box-shadow: 0 -1px 2px 0 rgba(0, 0, 0, 0.04);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}

/* Phone first: everything centred and stacked, with room to breathe. The
   two lines only sit side by side once the bar is wide enough to hold them
   without either one wrapping. */
.site-footer__inner {
  inline-size: 100%;
  max-inline-size: none;
  margin-inline: 0;
  padding-block: 1.25rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 0.625rem;
}

@media (min-width: 48rem) {
  .site-footer__inner {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    text-align: start;
    gap: 0.5rem 1.5rem;
    padding-block: 1.125rem;
  }
}

.site-footer__line--brand {
  font-weight: 600;
  color: var(--text);
}

/* The two names app.css already used are re-pointed at the scale above rather
   than left as a second, parallel set of numbers. There is one scale. */
:root {
  --reading-column: var(--container-narrow);
  --wide-column: var(--container-max);
}

.site-footer__line {
  margin-block-end: 0;
}

/* A page heading centred over a form. Only the title and the line under it;
   the fields below keep their own alignment. */
.page-head--center {
  text-align: center;
}

.page-head--center p {
  margin-inline: auto;
  max-inline-size: 26rem;
}

/* ==========================================================================
   2. Field scaffolding
   ========================================================================== */

.f-field {
  margin-block-end: 1.125rem;
}

.f-field:last-child {
  margin-block-end: 0;
}

.f-label {
  display: block;
  font-family: var(--font-display);
  font-size: 0.9375rem;
  font-weight: 600;
  margin-block-end: 0.4375rem;
}

.f-hint {
  display: block;
  font-size: 0.8125rem;
  line-height: 1.6;
  color: var(--text-muted);
  margin-block-start: 0.375rem;
}

.f-error {
  display: block;
  font-size: 0.8125rem;
  line-height: 1.6;
  color: var(--danger);
  margin-block-start: 0.375rem;
}

/* ==========================================================================
   3. Text inputs and textarea
   ========================================================================== */

.f-input,
.f-textarea,
.f-date,
.f-select {
  inline-size: 100%;
  min-block-size: var(--f-control-size);
  padding-block: 0.6875rem;
  padding-inline: var(--f-pad-inline);
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.6;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--f-border);
  border-radius: var(--f-radius);
  text-align: start;
  transition: border-color 0.15s ease, box-shadow 0.15s ease, background-color 0.15s ease;
}

.f-input:hover:not(:disabled):not([readonly]),
.f-textarea:hover:not(:disabled):not([readonly]),
.f-date:hover:not(:disabled):not([readonly]) {
  border-color: var(--f-border-strong);
}

.f-input:focus,
.f-textarea:focus,
.f-date:focus,
.f-select:focus {
  border-color: var(--primary);
  box-shadow: var(--f-ring);
  outline: none;
}

.f-input::placeholder,
.f-textarea::placeholder,
.f-date::placeholder {
  color: var(--text-muted);
  opacity: 0.75;
}

.f-input[aria-invalid='true'],
.f-textarea[aria-invalid='true'],
.f-date[aria-invalid='true'],
.f-select[aria-invalid='true'] {
  border-color: var(--danger);
  background: var(--danger-soft);
}

.f-input[aria-invalid='true']:focus,
.f-textarea[aria-invalid='true']:focus,
.f-date[aria-invalid='true']:focus {
  box-shadow: 0 0 0 4px rgba(180, 35, 24, 0.12);
}

.f-input:disabled,
.f-textarea:disabled,
.f-date:disabled,
.f-input[readonly],
.f-textarea[readonly] {
  background: var(--surface-soft);
  color: var(--text-muted);
  cursor: not-allowed;
}

/* An email or a password reads left-to-right whatever the page direction. */
.f-input--ltr {
  direction: ltr;
  text-align: start;
}

/* ---- textarea ---------------------------------------------------------- */
/* The browser default is a monospace-ish, cramped box. This is the project's
   Arabic UI font at a reading size, with room to breathe, and no resize grip:
   the auto-grow in components.js does that job instead. */
.f-textarea {
  display: block;
  resize: none;
  min-block-size: 7.5rem;
  max-block-size: 24rem;
  padding-block: 0.875rem;
  font-size: 1.0625rem;
  line-height: 1.9;
  overflow-y: auto;
}

.f-textarea.is-autogrow {
  overflow-y: hidden;
}

.f-textarea.is-autogrow.is-at-max {
  overflow-y: auto;
}

/* ==========================================================================
   4. Select
   ==========================================================================
   The native control carries the value and the validation. Without
   JavaScript it is what the user operates, so it has to look deliberate on
   its own: same box as a text input, with a chevron drawn in the background
   rather than the platform's arrow.
*/

.f-select {
  appearance: none;
  -webkit-appearance: none;
  cursor: pointer;
  padding-inline-end: 2.75rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16' fill='none' stroke='%236b6880' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 6l5 5 5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: left var(--f-pad-inline) center;
  background-size: 1rem 1rem;
}

.f-select:disabled {
  background-color: var(--surface-soft);
  color: var(--text-muted);
  cursor: not-allowed;
}

/* Once enhanced, the native select stays in the DOM and in the form — it is
   still the value that gets posted — but it is taken out of the visual flow.
   Not `display:none`: a hidden-by-display control is skipped by constraint
   validation reporting in some browsers, and the label association would be
   lost. Clipped instead. */
.f-select-shell .f-select {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  padding: 0;
  margin: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
}

.f-select-shell {
  position: relative;
  display: block;
  inline-size: 100%;
}

/* ---- trigger ----------------------------------------------------------- */

.f-select-trigger {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  inline-size: 100%;
  min-block-size: var(--f-control-size);
  padding-block: 0.6875rem;
  padding-inline: var(--f-pad-inline);
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.6;
  text-align: start;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--f-border);
  border-radius: var(--f-radius);
  cursor: pointer;
  transition: border-color 0.15s ease, box-shadow 0.15s ease, background-color 0.15s ease;
}

.f-select-trigger:hover:not([aria-disabled='true']) {
  border-color: var(--f-border-strong);
}

.f-select-trigger:focus-visible {
  border-color: var(--primary);
  box-shadow: var(--f-ring);
  outline: none;
}

.f-select-trigger[aria-expanded='true'] {
  border-color: var(--primary);
  box-shadow: var(--f-ring);
}

.f-select-trigger__value {
  flex: 1 1 auto;
  min-inline-size: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The empty state is a prompt, not a failure: muted text, ordinary border. */
.f-select-trigger.is-empty .f-select-trigger__value {
  color: var(--text-muted);
}

.f-select-trigger__chevron {
  flex: none;
  inline-size: 1rem;
  block-size: 1rem;
  color: var(--text-muted);
  transition: transform 0.18s ease;
}

.f-select-trigger[aria-expanded='true'] .f-select-trigger__chevron {
  transform: rotate(180deg);
}

/* The waiting state — the city list before a country is chosen. Deliberately
   not the error palette: a dashed border and a soft ground read as "not yet",
   where a red border would read as "you did something wrong". */
.f-select-trigger[aria-disabled='true'] {
  cursor: not-allowed;
  color: var(--text-muted);
  background: var(--surface-soft);
  border-style: dashed;
  border-color: var(--f-border-strong);
}

.f-select-trigger[aria-disabled='true'] .f-select-trigger__chevron {
  opacity: 0.45;
}

.f-select-trigger.is-invalid {
  border-color: var(--danger);
  background: var(--danger-soft);
}

/* ---- menu -------------------------------------------------------------- */
/* Appended to <body> and positioned with `position: fixed`, so no ancestor
   with `overflow: hidden` or a transform can clip it, and so it can flip
   above the trigger when the viewport runs out below. */

.f-select-menu {
  position: fixed;
  z-index: var(--f-z-popup);
  display: flex;
  flex-direction: column;
  max-block-size: 20rem;
  padding: 0.375rem;
  background: var(--surface);
  border: 1px solid var(--f-border);
  border-radius: var(--f-radius-lg);
  box-shadow: var(--f-menu-shadow);
  overflow: hidden;
}

.f-select-menu[hidden] {
  display: none;
}

.f-select-search {
  flex: none;
  inline-size: 100%;
  min-block-size: 2.5rem;
  margin-block-end: 0.375rem;
  padding-block: 0.5rem;
  padding-inline: 0.75rem;
  font-family: var(--font-body);
  font-size: 0.9375rem;
  color: var(--text);
  background: var(--surface-soft);
  border: 1px solid transparent;
  border-radius: 0.625rem;
  text-align: start;
}

.f-select-search:focus {
  border-color: var(--primary);
  background: var(--surface);
  outline: none;
}

.f-select-list {
  flex: 1 1 auto;
  margin: 0;
  padding: 0;
  list-style: none;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.f-select-option {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-block-size: var(--touch-target);
  padding-block: 0.5rem;
  padding-inline: 0.75rem;
  border-radius: 0.625rem;
  font-size: 0.9375rem;
  line-height: 1.6;
  color: var(--text);
  cursor: pointer;
  user-select: none;
}

.f-select-option.is-active {
  background: var(--primary-soft);
  color: var(--primary);
}

.f-select-option[aria-selected='true'] {
  font-weight: 700;
  color: var(--primary);
}

.f-select-option[aria-selected='true']::after {
  content: '✓';
  margin-inline-start: auto;
  font-size: 0.875rem;
}

.f-select-option[aria-disabled='true'] {
  color: var(--text-muted);
  cursor: not-allowed;
  opacity: 0.6;
}

.f-select-option--placeholder {
  color: var(--text-muted);
}

/* Nothing matched the filter, or the list is genuinely empty. Calm, centred,
   unmistakably "no results" rather than a blank hole. */
.f-select-empty {
  padding-block: 1.25rem;
  padding-inline: 0.75rem;
  text-align: center;
  font-size: 0.875rem;
  color: var(--text-muted);
}

/* ---- compact modifier --------------------------------------------------- */
/* `.f-select--sm`: a select that has to sit beside small inline controls
   (pagination's page-size picker today; anywhere else a short, fixed-width
   list of options needs to read as part of a toolbar row rather than as its
   own field) instead of standing full-height in a stacked form. Sized off
   the same recipe `.admin-btn-sm` uses: padding-block 0.3rem, font-size
   0.78rem, 1px border — measured in the browser against a rendered
   `.admin-btn-sm` rather than assumed. `line-height: normal` was the first
   attempt and does NOT converge on the same height: `normal` is a
   font-metric-derived value, and it resolves differently per font WEIGHT
   even at the same font-size (measured: Tajawal 700 → 21.84px, Tajawal 400
   → 17.99px, both at this font-size) — .admin-btn-sm is bold, this select
   text is not. So the line-height is pinned to the explicit ratio
   `.admin-btn-sm` actually measured at (21.84 / 12.48 = 1.75) instead,
   which reproduces its height exactly regardless of weight. */
.f-select--sm {
  inline-size: auto;
  min-block-size: auto;
  padding-block: 0.3rem;
  padding-inline: 0.75rem 2rem;
  font-size: 0.78rem;
  line-height: 1.75;
  background-position: left 0.6rem center;
  background-size: 0.8rem 0.8rem;
}

/* `enhanceSelect()` (components.js) builds the visible trigger fresh and
   does not copy the source <select>'s classes onto it, so a plain modifier
   class on the select alone would only ever reach the no-JS fallback. The
   `:has()` rule below is how the modifier still reaches the enhanced
   trigger — one class to add, not two, and no JS change needed. */
.f-select-shell:has(.f-select--sm) .f-select-trigger {
  inline-size: auto;
  min-block-size: auto;
  padding-block: 0.3rem;
  padding-inline: 0.75rem;
  gap: 0.375rem;
  font-size: 0.78rem;
  line-height: 1.75;
}

.f-select-shell:has(.f-select--sm) .f-select-trigger__chevron {
  inline-size: 0.8rem;
  block-size: 0.8rem;
}

/* ==========================================================================
   5. Checkbox and radio
   ==========================================================================
   The real input stays in the layout and stays focusable — it is made
   transparent and stretched over the drawn box, so the platform focus ring
   lands on the right rectangle and screen readers see an ordinary control.
   `display:none` would take it out of the tab order entirely.
*/

.f-check {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  /* 44px minimum touch target, label included. */
  min-block-size: var(--touch-target);
  padding-block: 0.5rem;
  font-weight: 400;
  line-height: 1.7;
  cursor: pointer;
}

.f-check input[type='checkbox'],
.f-check input[type='radio'] {
  position: absolute;
  inset-block-start: 0.6875rem;
  inset-inline-start: 0;
  inline-size: 1.375rem;
  block-size: 1.375rem;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.f-check input:disabled {
  cursor: not-allowed;
}

.f-check__box {
  flex: none;
  position: relative;
  /* The drawn box sits over the real input. It must not swallow the click:
     with pointer events off, the input itself is the hit target on its own
     rectangle and the surrounding label handles everything else. */
  pointer-events: none;
  inline-size: 1.375rem;
  block-size: 1.375rem;
  margin-block-start: 0.1875rem;
  border: 1.5px solid var(--f-border-strong);
  border-radius: 0.4375rem;
  background: var(--surface);
  transition: background-color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}

.f-check--radio .f-check__box {
  border-radius: 999px;
}

/* The tick. Drawn, not a glyph, so it scales with the box. */
.f-check__box::after {
  content: '';
  position: absolute;
  inset: 0;
  background-repeat: no-repeat;
  background-position: center;
  background-size: 0.875rem 0.875rem;
  opacity: 0;
  transform: scale(0.7);
  transition: opacity 0.12s ease, transform 0.12s ease;
}

.f-check input:checked ~ .f-check__box::after {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16' fill='none' stroke='%23ffffff' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 8.5l3.5 3.5L13 4.5'/%3E%3C/svg%3E");
  opacity: 1;
  transform: scale(1);
}

/* A radio gets a filled dot, not a tick. */
.f-check--radio input:checked ~ .f-check__box::after {
  background-image: none;
  inset: 0.3125rem;
  border-radius: 999px;
  background: #fff;
}

.f-check input:indeterminate ~ .f-check__box::after {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16' fill='none' stroke='%23ffffff' stroke-width='2.5' stroke-linecap='round'%3E%3Cpath d='M4 8h8'/%3E%3C/svg%3E");
  opacity: 1;
  transform: scale(1);
}

.f-check input:checked ~ .f-check__box,
.f-check input:indeterminate ~ .f-check__box {
  background: var(--primary);
  border-color: var(--primary);
}

.f-check:hover input:not(:disabled) ~ .f-check__box {
  border-color: var(--primary);
}

.f-check input:focus-visible ~ .f-check__box {
  border-color: var(--primary);
  box-shadow: var(--f-ring);
}

.f-check input[aria-invalid='true'] ~ .f-check__box {
  border-color: var(--danger);
}

.f-check input:disabled ~ .f-check__box {
  background: var(--surface-soft);
  border-color: var(--f-border);
}

.f-check input:disabled:checked ~ .f-check__box {
  background: var(--f-border-strong);
  border-color: var(--f-border-strong);
}

.f-check input:disabled ~ .f-check__text {
  color: var(--text-muted);
  cursor: not-allowed;
}

.f-check__text {
  flex: 1 1 auto;
  min-inline-size: 0;
}

/* A stack of radios reading as one group. */
.f-check-group {
  display: grid;
  gap: 0.25rem;
}

/* ==========================================================================
   6. Date field
   ==========================================================================
   A text input the user types into, plus a calendar button sitting inside
   the field. The ISO value the server reads lives in a hidden sibling that
   components.js keeps in step.
*/

.f-date-shell {
  position: relative;
  display: block;
  inline-size: 100%;
}

/* The shell keeps the page direction, so the calendar button sits at the
   field's inline end — the left, in Arabic. The text itself runs
   left-to-right, because a date is digits and dots and the caret has to
   behave, but it is aligned to the field's own end so it still reads flush
   against the RTL label above it. The room for the button is reserved on the
   physical left, which under `direction: ltr` is `padding-inline-start`. */
.f-date-shell .f-date {
  direction: ltr;
  text-align: end;
  padding-inline-start: 3.25rem;
  padding-inline-end: var(--f-pad-inline);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
}

.f-date-toggle {
  position: absolute;
  inset-block-start: 50%;
  inset-inline-end: 0.4375rem;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 2.25rem;
  block-size: 2.25rem;
  padding: 0;
  color: var(--text-muted);
  background: none;
  border: 0;
  border-radius: 0.625rem;
  cursor: pointer;
  transition: color 0.15s ease, background-color 0.15s ease;
}

.f-date-toggle:hover {
  color: var(--primary);
  background: var(--primary-soft);
}

.f-date-toggle:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 1px;
}

.f-date-toggle svg {
  inline-size: 1.25rem;
  block-size: 1.25rem;
}

.f-date.is-invalid,
.f-date[aria-invalid='true'] {
  border-color: var(--danger);
  background: var(--danger-soft);
}

/* The client-side complaint. It never clears what was typed — the text stays
   so it can be corrected. */
.f-date-feedback {
  display: none;
  font-size: 0.8125rem;
  line-height: 1.6;
  color: var(--danger);
  margin-block-start: 0.375rem;
}

.f-date-feedback.is-visible {
  display: block;
}

/* ---- calendar ---------------------------------------------------------- */

.f-cal {
  position: fixed;
  z-index: var(--f-z-popup);
  inline-size: 20rem;
  max-inline-size: calc(100vw - 1.5rem);
  padding: 0.875rem;
  background: var(--surface);
  border: 1px solid var(--f-border);
  border-radius: var(--f-radius-lg);
  box-shadow: var(--f-menu-shadow);
}

.f-cal[hidden] {
  display: none;
}

.f-cal__head {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  margin-block-end: 0.75rem;
}

.f-cal__nav {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 2.25rem;
  block-size: 2.25rem;
  color: var(--text-muted);
  background: none;
  border: 1px solid var(--f-border);
  border-radius: 0.625rem;
  cursor: pointer;
  font-size: 1rem;
  line-height: 1;
}

.f-cal__nav svg {
  inline-size: 1rem;
  block-size: 1rem;
}

/* The next-month arrow is the previous-month one mirrored. */
.f-cal__nav--next svg {
  transform: scaleX(-1);
}

.f-cal__nav:hover:not(:disabled) {
  color: var(--primary);
  border-color: var(--primary);
  background: var(--primary-soft);
}

.f-cal__nav:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

/* Month and year as dropdowns, so a birthdate reaches 1960 in two gestures
   rather than by paging back 780 months. */
.f-cal__selects {
  flex: 1 1 auto;
  display: flex;
  gap: 0.375rem;
  min-inline-size: 0;
}

.f-cal__select {
  flex: 1 1 0;
  min-inline-size: 0;
  min-block-size: 2.25rem;
  padding-block: 0.25rem;
  padding-inline: 0.5rem 1.75rem;
  font-family: var(--font-body);
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--text);
  background-color: var(--surface);
  border: 1px solid var(--f-border);
  border-radius: 0.625rem;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16' fill='none' stroke='%236b6880' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 6l5 5 5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: left 0.5rem center;
  background-size: 0.875rem 0.875rem;
}

.f-cal__select:focus-visible {
  border-color: var(--primary);
  outline: none;
  box-shadow: var(--f-ring);
}

.f-cal__weekdays,
.f-cal__grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 0.125rem;
}

.f-cal__weekdays {
  margin-block-end: 0.25rem;
}

.f-cal__weekday {
  text-align: center;
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--text-muted);
  padding-block: 0.25rem;
}

.f-cal__day {
  display: flex;
  align-items: center;
  justify-content: center;
  min-block-size: 2.25rem;
  font-family: var(--font-body);
  font-size: 0.875rem;
  font-variant-numeric: tabular-nums;
  color: var(--text);
  background: none;
  border: 1px solid transparent;
  border-radius: 0.625rem;
  cursor: pointer;
}

.f-cal__day:hover:not(:disabled) {
  background: var(--primary-soft);
  color: var(--primary);
}

.f-cal__day.is-outside {
  color: var(--text-muted);
  opacity: 0.45;
}

.f-cal__day.is-today {
  border-color: var(--f-border-strong);
  font-weight: 700;
}

.f-cal__day.is-focused {
  border-color: var(--primary);
}

.f-cal__day.is-selected {
  background: var(--primary);
  border-color: var(--primary);
  color: #fff;
  font-weight: 700;
}

.f-cal__day:disabled {
  color: var(--text-muted);
  opacity: 0.3;
  cursor: not-allowed;
}

.f-cal__foot {
  display: flex;
  justify-content: space-between;
  gap: 0.5rem;
  margin-block-start: 0.75rem;
  padding-block-start: 0.625rem;
  border-block-start: 1px solid var(--f-border);
}

.f-cal__action {
  min-block-size: 2.25rem;
  padding-inline: 0.75rem;
  font-family: var(--font-body);
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--primary);
  background: none;
  border: 0;
  border-radius: 0.625rem;
  cursor: pointer;
}

.f-cal__action:hover {
  background: var(--primary-soft);
}

/* ==========================================================================
   7. Bridge from the pre-existing classes
   ==========================================================================
   `.input`, `.select`, `.textarea` and `.field` still appear in views that are
   not part of this pass (and in the admin area until its own conversion
   lands). They keep working; these rules only pull them onto the new metrics
   so a converted and an unconverted field do not sit at different heights.
*/

.input,
.select,
.textarea {
  min-block-size: var(--f-control-size);
  padding-inline: var(--f-pad-inline);
  border-radius: var(--f-radius);
}

@media (prefers-reduced-motion: reduce) {
  .f-check__box::after,
  .f-select-trigger__chevron {
    transition: none;
  }
}
