/* ==========================================================================
   GaragIO — custom stylesheet
   Design system v3 «Solar White» (docs/ux/sistema-diseno.md) on top of
   Bootstrap 5.3. Mobile-first 360px. WCAG 2.2 AA.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Design-system tokens (v3 «Solar White» — approved by the user,
      docs/arquitectura.md). Elevated light mode, coral accent, generous radii.
   -------------------------------------------------------------------------- */
:root {
  /* Backgrounds */
  --bg-page:        #F4F6F9;   /* very light cool gray */
  --bg-surface:     #FFFFFF;
  --bg-surface-alt: #F8F9FB;

  /* Accent: dark coral */
  --color-primary:      #C13209;  /* 5.5:1 on white, AA verified */
  --color-primary-dark: #A12807;  /* hover */
  --color-primary-text: #FFFFFF;

  /* Text */
  --text-main:    #111827;
  --text-muted:   #6B7280;       /* 4.6:1 on white — only >=14px; NEVER on --bg-page */
  --border-color: #E5E7EB;

  /* Depth */
  --shadow-card:  0 2px 16px rgba(17, 24, 39, 0.08), 0 1px 0 rgba(0,0,0,0.04);
  --shadow-card-hover: 0 6px 24px rgba(17, 24, 39, 0.12), 0 2px 4px rgba(0, 0, 0, 0.06);
  --shadow-float: 0 8px 24px rgba(193,50,9,0.20), 0 2px 8px rgba(0,0,0,0.10);
  /* Tokenized one-off shadows (HU-50 dark mode): the bottom bar, the inner
     frame around photos and the badge shadow over the photo. Previously these
     were fixed rgba(17,24,39,X) (light tone) that washed out over dark backgrounds. */
  --shadow-bottom-bar: 0 -2px 8px rgba(17, 24, 39, 0.08);
  --shadow-photo-inset: inset 0 0 0 1px rgba(17, 24, 39, 0.06);
  --shadow-photo-badge: 0 1px 4px rgba(17, 24, 39, 0.25);
  --radius-card: 1.25rem;   /* 20px */
  --radius-btn:  0.75rem;   /* 12px */

  /* Plan states */
  --state-ok:      #065F46;  --state-ok-bg:      #D1FAE5;
  --state-warning: #92400E;  --state-warning-bg: #FEF3C7;
  --state-danger:  #B91C1C;  --state-danger-bg:  #FEE2E2;
  /* Informational state (HU-33: Telegram «Pending» badge).
     #1E40AF on #DBEAFE = 7.2:1 — passes AA (P-19b §8). */
  --state-info:    #1E40AF;  --state-info-bg:    #DBEAFE;
  /* «Silenced» state (HU-45, UX §0): an active plan with a date whose reminders
     are paused (notification_enabled=False). #374151 on #F3F4F6 = 9.2:1
     — comfortably passes AA. Neutral gray, deliberately subdued. */
  --state-muted:   #374151;  --state-muted-bg:   #F3F4F6;

  /* Errors and success */
  --color-error:   #B91C1C;  --color-error-bg:   #FEE2E2;
  --color-success: #065F46;  --color-success-bg: #D1FAE5;

  /* Numeric alerts badge (HU-25): solid red pill with white text.
     Its own token because --state-danger is also used as a TEXT COLOR over
     tinted backgrounds; in dark mode that token lightens (text on a tint) and
     the solid badge must stay a strong red with light text. */
  --nav-badge-bg:   var(--state-danger);
  --nav-badge-text: #FFFFFF;

  /* OCR flow surfaces (ADR-011): method cards and AI consent panel.
     Tokenized (previously #DEE2E6/#FFF5F3/#F8F9FA/#FFF8F7/#495057) so they have
     a dark equivalent and don't end up «broken». */
  --ocr-card-border:        #DEE2E6;
  --ocr-card-selected-bg:   #FFF5F3;
  --ocr-card-disabled-bg:   #F8F9FA;
  --ai-consent-bg:          #FFF8F7;
  --ai-consent-text:        #495057;  /* 8.6:1 on #FFF8F7 (AAA, ux-ui) */
  /* Veil for the affordance gradient of the tab rail (seg-control--five).
     Assumes the background surface color; in dark mode it is replaced by slate. */
  --scroll-fade-rgb: 255, 255, 255;

  /* Bootstrap overrides (btn-primary, focus rings...) */
  --bs-primary:     #C13209;
  --bs-primary-rgb: 193, 50, 9;

  --bottom-bar-height: 64px;

  /* Desktop Premium v4 (>=lg): fixed sidebar + per-screen section topbar. */
  --sidebar-width: 240px;
  --section-topbar-height: 60px;
  --content-padding-desktop: 2rem;

  /* License plate (it. 4, spec A.2). Contrast verified:
     number #111827 on #FFFFFF = 17.9:1; country letter #FFFFFF on EU blue
     #003399 = 10.8:1. Both pass AA. */
  --plate-bg:#FFFFFF; --plate-text:#111827; --plate-border:#9CA3AF;
  --plate-band-bg:#003399; --plate-band-text:#FFFFFF; --plate-radius:4px;
}

/* Token derived from the system's AA rule: --text-muted (#6B7280) on
   --bg-page (#F4F6F9) gives ~4.0:1 and does NOT pass AA. Secondary text placed
   directly on the page background uses this darker gray: #565F6E on #F4F6F9
   gives 4.8:1 (AA verified for normal text). */
:root {
  --text-secundario-en-pagina: #565F6E;
}

/* --------------------------------------------------------------------------
   1-OSCURO. «Midnight Garage» palette (dark mode, HU-50)
   --------------------------------------------------------------------------
   Dark theme documented in docs/ux/sistema-diseno.md («slate + amber» as a
   possible future theme). It is resolved ENTIRELY through tokens: these rules
   REDEFINE the same custom properties as :root, so EVERY component that uses the
   tokens (backgrounds, surfaces, text, borders, coral accent, up-to-date/
   upcoming/overdue/silenced/info states, badges, shadows, predictive estimate…)
   changes without touching its CSS. The coral accent is LIGHTENED (#FF6B3D)
   because dark coral v3 (#C13209) does not contrast against slate; the primary
   button text becomes a very dark brown to keep AA over the light coral.

   Activation (base.html, server-side, anti-FOUC):
     · [data-theme="dark"]                         → always dark.
     · [data-theme="auto"] + prefers-color-scheme:dark → dark following the system.
   Light lives in :root (default) and covers data-theme="light" and "auto" when
   the system is in light mode.

   WCAG 2.2 AA contrasts verified (check script, all ≥ 4.5:1):
     main text       #F1F5F9 / surface #1A222C ...... 14.6:1
     main text       #F1F5F9 / page #0F141A .......... 16.9:1
     muted text      #9CA8B6 / surface #1A222C ...... 6.6:1
     muted text      #9CA8B6 / surf. alt #222C38 ........ 5.9:1
     secondary       #AEB9C6 / page #0F141A .......... 9.3:1
     coral accent    #FF6B3D / surface #1A222C ...... 5.7:1
     coral accent    #FF6B3D / page #0F141A .......... 6.5:1
     button text     #1A120D / coral #FF6B3D ............ 6.5:1
     up-to-date #6EE7B7 / tint #0E2A22 / surface ..... 10.0 / 10.5:1
     upcoming   #FCD34D / tint #2E2206 / surface ..... 10.8 / 11.1:1
     overdue    #FCA5A5 / tint #2E1416 / surface ...... 9.0 / 8.5:1
     info       #93C5FD / tint #11233F / surface ...... 8.7 / 8.9:1
     silenced   #CBD5E1 / tint #232C38 ................. 9.5:1
     alerts badge text #FFFFFF / red #B91C1C ......... 6.5:1
   -------------------------------------------------------------------------- */
/* Dark variables: they ALWAYS apply to data-theme="dark"; the @media block
   below replicates them for data-theme="auto" when the system requests dark.
   :root[data-theme="dark"] (0,2,0) is used so these tokens BEAT those of
   :root (0,1,0); defining variables here does not compete with the component
   rules (which only consume the variables already resolved at the root). */
:root[data-theme="dark"] {
  /* Backgrounds */
  --bg-page:        #0F141A;   /* deep slate */
  --bg-surface:     #1A222C;
  --bg-surface-alt: #222C38;

  /* Accent: coral lightened for slate */
  --color-primary:      #FF6B3D;
  --color-primary-dark: #FF8052;  /* hover: a touch lighter on dark */
  --color-primary-text: #1A120D;  /* text on the light coral (6.5:1 AA) */

  /* Text */
  --text-main:    #F1F5F9;
  --text-muted:   #9CA8B6;       /* 6.6:1 on surface, 5.9:1 on surf-alt */
  --border-color: #33414F;
  --text-secundario-en-pagina: #AEB9C6;  /* 9.3:1 on the page */

  /* Depth: stronger shadows (the dim light of dark mode needs more opacity to
     separate surfaces from the background). */
  --shadow-card:  0 2px 16px rgba(0, 0, 0, 0.45), 0 1px 0 rgba(0, 0, 0, 0.3);
  --shadow-card-hover: 0 8px 28px rgba(0, 0, 0, 0.6), 0 2px 4px rgba(0, 0, 0, 0.4);
  --shadow-float: 0 8px 24px rgba(0, 0, 0, 0.55), 0 2px 8px rgba(0, 0, 0, 0.4);
  /* One-off shadows in dark mode: more opaque black to separate surfaces and,
     on the inner photo frames, a LIGHT hairline (not dark) that does show over
     slate and separates dark photos from the card border. */
  --shadow-bottom-bar:  0 -2px 12px rgba(0, 0, 0, 0.6);
  --shadow-photo-inset: inset 0 0 0 1px rgba(255, 255, 255, 0.12);
  --shadow-photo-badge: 0 1px 6px rgba(0, 0, 0, 0.7);

  /* Plan states: light text over a dark tint of the same hue. */
  --state-ok:      #6EE7B7;  --state-ok-bg:      #0E2A22;
  --state-warning: #FCD34D;  --state-warning-bg: #2E2206;
  --state-danger:  #FCA5A5;  --state-danger-bg:  #2E1416;
  --state-info:    #93C5FD;  --state-info-bg:    #11233F;
  --state-muted:   #CBD5E1;  --state-muted-bg:   #232C38;

  /* Errors and success (semantic aliases of danger/ok). */
  --color-error:   #FCA5A5;  --color-error-bg:   #2E1416;
  --color-success: #6EE7B7;  --color-success-bg: #0E2A22;

  /* Alerts badge: the pill stays a strong SOLID red with white text (6.5:1),
     NOT the light pink of --state-danger (which is text here). */
  --nav-badge-bg:   #B91C1C;
  --nav-badge-text: #FFFFFF;

  /* OCR flow / AI consent surfaces in dark mode. */
  --ocr-card-border:        #33414F;
  --ocr-card-selected-bg:   #2A1C16;  /* dark coral wash */
  --ocr-card-disabled-bg:   #161D26;
  --ai-consent-bg:          #241A16;  /* dark coral wash */
  --ai-consent-text:        #D5DDE6;  /* ~10:1 on #241A16 */
  --scroll-fade-rgb: 26, 34, 44;      /* = --bg-surface (#1A222C) */

  /* License plate: the European plate is physically white; it stays legible
     (dark number on white) but its border adapts to the theme. */
  --plate-border: #5A6B7D;

  /* Bootstrap overrides: the light coral and its rgb for focus rings / links. */
  --bs-primary:     #FF6B3D;
  --bs-primary-rgb: 255, 107, 61;
  --bs-link-color-rgb: 255, 107, 61;
  --bs-link-hover-color-rgb: 255, 128, 82;
}

/* "auto": follows the system. The palette is applied only when the OS requests
   dark; in light mode, :root wins. The SAME map is reused (copied) so it doesn't
   depend on inheritance between different selectors. */
@media (prefers-color-scheme: dark) {
  :root[data-theme="auto"] {
    --bg-page:        #0F141A;
    --bg-surface:     #1A222C;
    --bg-surface-alt: #222C38;

    --color-primary:      #FF6B3D;
    --color-primary-dark: #FF8052;
    --color-primary-text: #1A120D;

    --text-main:    #F1F5F9;
    --text-muted:   #9CA8B6;
    --border-color: #33414F;
    --text-secundario-en-pagina: #AEB9C6;

    --shadow-card:  0 2px 16px rgba(0, 0, 0, 0.45), 0 1px 0 rgba(0, 0, 0, 0.3);
    --shadow-card-hover: 0 8px 28px rgba(0, 0, 0, 0.6), 0 2px 4px rgba(0, 0, 0, 0.4);
    --shadow-float: 0 8px 24px rgba(0, 0, 0, 0.55), 0 2px 8px rgba(0, 0, 0, 0.4);
    --shadow-bottom-bar:  0 -2px 12px rgba(0, 0, 0, 0.6);
    --shadow-photo-inset: inset 0 0 0 1px rgba(255, 255, 255, 0.12);
    --shadow-photo-badge: 0 1px 6px rgba(0, 0, 0, 0.7);

    --state-ok:      #6EE7B7;  --state-ok-bg:      #0E2A22;
    --state-warning: #FCD34D;  --state-warning-bg: #2E2206;
    --state-danger:  #FCA5A5;  --state-danger-bg:  #2E1416;
    --state-info:    #93C5FD;  --state-info-bg:    #11233F;
    --state-muted:   #CBD5E1;  --state-muted-bg:   #232C38;

    --color-error:   #FCA5A5;  --color-error-bg:   #2E1416;
    --color-success: #6EE7B7;  --color-success-bg: #0E2A22;

    --nav-badge-bg:   #B91C1C;
    --nav-badge-text: #FFFFFF;

    --ocr-card-border:        #33414F;
    --ocr-card-selected-bg:   #2A1C16;
    --ocr-card-disabled-bg:   #161D26;
    --ai-consent-bg:          #241A16;
    --ai-consent-text:        #D5DDE6;
    --scroll-fade-rgb: 26, 34, 44;

    --plate-border: #5A6B7D;

    --bs-primary:     #FF6B3D;
    --bs-primary-rgb: 255, 107, 61;
    --bs-link-color-rgb: 255, 107, 61;
    --bs-link-hover-color-rgb: 255, 128, 82;
  }
}

/* Native color scheme: so the browser controls (scrollbars, date/number inputs,
   autofill) adopt the correct mode in each theme. */
[data-theme="dark"] { color-scheme: dark; }
[data-theme="light"] { color-scheme: light; }
:root[data-theme="auto"] { color-scheme: light dark; }

/* --------------------------------------------------------------------------
   1b. Bridge to Bootstrap 5.3: Bootstrap's compiled CSS carries its blue in
   every component, so the coral is injected via its local variables.
   -------------------------------------------------------------------------- */
:root {
  --bs-body-bg: var(--bg-page);
  --bs-body-color: var(--text-main);
  --bs-border-color: var(--border-color);
  --bs-secondary-color: var(--text-muted); /* .text-muted with the v3 token */
  --bs-link-color: var(--color-primary);
  --bs-link-color-rgb: 193, 50, 9;
  --bs-link-hover-color: var(--color-primary-dark);
  --bs-link-hover-color-rgb: 161, 40, 7;
  --bs-border-radius: var(--radius-btn);
}

body {
  background-color: var(--bg-page);
  color: var(--text-main);
}

.btn {
  --bs-btn-border-radius: var(--radius-btn);
}

.btn-primary {
  --bs-btn-bg: var(--color-primary);
  --bs-btn-border-color: var(--color-primary);
  --bs-btn-color: var(--color-primary-text);
  --bs-btn-hover-bg: var(--color-primary-dark);
  --bs-btn-hover-border-color: var(--color-primary-dark);
  --bs-btn-hover-color: var(--color-primary-text);
  --bs-btn-active-bg: var(--color-primary-dark);
  --bs-btn-active-border-color: var(--color-primary-dark);
  --bs-btn-active-color: var(--color-primary-text);
  --bs-btn-disabled-bg: var(--color-primary);
  --bs-btn-disabled-border-color: var(--color-primary);
  --bs-btn-disabled-color: var(--color-primary-text);
  --bs-btn-focus-shadow-rgb: var(--bs-primary-rgb);
}

.btn-outline-primary {
  --bs-btn-color: var(--color-primary);
  --bs-btn-border-color: var(--color-primary);
  --bs-btn-hover-bg: var(--color-primary);
  --bs-btn-hover-border-color: var(--color-primary);
  --bs-btn-hover-color: var(--color-primary-text);
  --bs-btn-active-bg: var(--color-primary-dark);
  --bs-btn-active-border-color: var(--color-primary-dark);
  --bs-btn-active-color: var(--color-primary-text);
  --bs-btn-focus-shadow-rgb: var(--bs-primary-rgb);
}

/* Generic Bootstrap card (login, profile): system radius and shadow */
.card {
  --bs-card-border-radius: var(--radius-card);
  --bs-card-inner-border-radius: calc(var(--radius-card) - 1px);
  --bs-card-border-color: var(--border-color);
  box-shadow: var(--shadow-card);
}

/* Confirmation modal: same depth as the cards */
.modal-content {
  border-radius: var(--radius-card);
}

/* Flash messages with the v2 state tokens (Bootstrap ships its own palette) */
.alert-success {
  --bs-alert-color: var(--color-success);
  --bs-alert-bg: var(--color-success-bg);
  --bs-alert-border-color: var(--color-success-bg);
}

.alert-danger {
  --bs-alert-color: var(--color-error);
  --bs-alert-bg: var(--color-error-bg);
  --bs-alert-border-color: var(--color-error-bg);
}

.alert-warning {
  --bs-alert-color: var(--state-warning);
  --bs-alert-bg: var(--state-warning-bg);
  --bs-alert-border-color: var(--state-warning-bg);
}

/* --------------------------------------------------------------------------
   2. Layout: space for the bottom bar on authenticated pages
   -------------------------------------------------------------------------- */
main.with-bottom-bar {
  /* The bar (64px) must not cover the last content element */
  padding-bottom: 72px;
}

/* --------------------------------------------------------------------------
   3. Buttons (minimum 48px touch height) and visible focus
   -------------------------------------------------------------------------- */
.btn-primary,
.btn-outline-primary,
.btn-outline-danger {
  min-height: 48px;
  font-weight: 600;
  /* True vertical centering of the text: with min-height larger than the
     content's natural height, without flex the text of an <a class="btn"> sits
     stuck to the top. This centers ALL system buttons (action bar, empty
     state, forms). */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.375rem;
}

/* Clearly visible keyboard focus across the whole interface (WCAG 2.4.7) */
.btn:focus-visible,
.bottom-bar__item:focus-visible,
.back-link:focus-visible,
.subtle-link:focus-visible,
.action-row:focus-visible {
  outline: 3px solid var(--color-primary);
  outline-offset: 2px;
  box-shadow: none;
}

/* --------------------------------------------------------------------------
   4. Forms
   -------------------------------------------------------------------------- */
.form-control {
  min-height: 48px;
  border-color: var(--border-color);
}

.form-control:focus {
  border-color: var(--color-primary);
  box-shadow: 0 0 0 0.25rem rgba(var(--bs-primary-rgb), 0.25);
}

.form-label {
  font-size: 0.875rem;
  font-weight: 500;
}

.form-control.is-invalid {
  border-color: var(--color-error);
}

.invalid-feedback {
  color: var(--color-error);
  font-size: 0.875rem;
}

/* The error containers carry d-block (needed inside input-group) and are hidden
   with the hidden attribute; without this rule, the !important of .d-block would
   beat hidden and the empty gap would stay visible. */
.invalid-feedback.d-block[hidden] {
  display: none !important;
}

/* Show/hide password «eye» button: minimum 44×44px touch area */
.eye-button {
  min-width: 44px;
  min-height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-color: var(--border-color);
  color: var(--text-muted);
}

.eye-button:hover {
  color: var(--text-main);
  background-color: var(--bg-surface-alt);
}

/* Fields visually disabled during submission (readonly so their values DO
   travel in the POST, unlike disabled) */
.field-submitting {
  background-color: var(--bg-surface-alt);
  pointer-events: none;
}

/* Fixed requirement note (P-02 and P-05): sits directly on --bg-page, which is
   why it uses the AA blue-gray and not --text-muted (v2 contrast rule) */
.requirement-note {
  color: var(--text-secundario-en-pagina);
  font-size: 0.875rem;
}

/* --------------------------------------------------------------------------
   5. Discreet action link («Cancel», «Back»): 44px touch area
   -------------------------------------------------------------------------- */
.subtle-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 0 1rem;
  /* Usually sits directly on --bg-page: blue-gray AA, not --text-muted */
  color: var(--text-secundario-en-pagina);
  text-decoration: none;
}

.subtle-link:hover {
  color: var(--text-main);
  text-decoration: underline;
}

/* --------------------------------------------------------------------------
   6. Secondary header (sub-screens with «Back»): 56px
   -------------------------------------------------------------------------- */
.secondary-header {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  min-height: 56px;
  padding: 0 0.5rem;
  background-color: var(--bg-surface);
  border-bottom: 1px solid var(--border-color);
}

.secondary-header .screen-title {
  margin: 0;
  font-size: 1.25rem;
  font-weight: 600;
}

.back-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  padding: 0 0.5rem;
  color: var(--color-primary);
  text-decoration: none;
  font-weight: 500;
}

.back-link:hover {
  color: var(--color-primary-dark);
  text-decoration: underline;
}

/* Top-level header (no «Back») */
.main-header {
  display: flex;
  align-items: center;
  min-height: 56px;
  padding: 0 1rem;
  background-color: var(--bg-surface);
  border-bottom: 1px solid var(--border-color);
  /* It. 4 (spec PART B): the language trigger anchors to the right without
     pushing the title; the title stays on the left and takes the rest. */
  gap: 0.5rem;
}

.main-header .screen-title {
  margin: 0;
  font-size: 1.25rem;
  font-weight: 600;
  /* Pushes the language trigger (if any) to the far right of the header. */
  margin-right: auto;
  /* Lets the title give up room to the action button (P-11 mobile) without
     overflowing the header on narrow screens. */
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Optional top-level header action (P-11 mobile → «Mis vencimientos»,
   UX §1). btn-sm with a guaranteed 44px touch target and no line breaks. */
.main-header__action {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  min-height: 44px;
  white-space: nowrap;
  flex-shrink: 0;
}

/* --------------------------------------------------------------------------
   7. Bottom navigation bar (authenticated user only)
   -------------------------------------------------------------------------- */
.bottom-bar {
  position: fixed;
  inset: auto 0 0 0;
  z-index: 1030;
  display: flex;
  height: var(--bottom-bar-height);
  background-color: var(--bg-surface);
  border-top: 1px solid var(--border-color);
  box-shadow: var(--shadow-bottom-bar);
}

.bottom-bar__item {
  /* flex-basis:0 + equal distribution: with 4 items each takes 1/4 of the width
     (≈90px at 360px, ≈80px at 320px). min-width:0 lets the cell shrink below the
     width of its content so the distribution stays exact. */
  flex: 1 1 0;
  min-width: 0;
  /* Relative positioning to anchor the alerts badge (.nav-badge--bottom-bar,
     absolutely positioned). */
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.125rem;
  padding: 0 0.125rem; /* minimal lateral breathing room between labels with 4 items */
  height: 100%; /* 64px > 44px minimum touch area */
  /* 0.625rem labels: --text-muted is right at that body size (v2 rule), so the
     darker blue-gray is used even on a white surface */
  color: var(--text-secundario-en-pagina);
  text-decoration: none;
  font-size: 0.625rem;
}

/* The label never breaks into two lines (that would break the bar's height) nor
   overflows: a single line, centered and clipped with an ellipsis if it doesn't fit. */
.bottom-bar__item span {
  max-width: 100%;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.bottom-bar__item .bi {
  font-size: 24px;
  line-height: 1;
}

.bottom-bar__item:hover {
  color: var(--text-main);
}

.bottom-bar__item--active {
  color: var(--color-primary);
}

.bottom-bar__item:focus-visible {
  outline-offset: -3px; /* the outline fits inside the bar */
}

/* --------------------------------------------------------------------------
   7-bis. Numeric alerts badge (HU-25)
   Red counter of overdue/upcoming plans next to the «Alerts» item. Reuses the
   existing danger token (--state-danger #B91C1C → white = 7.1:1, AA).
   Minimum size 16px and legible numbers on mobile (HU-25 spec).
   -------------------------------------------------------------------------- */
.nav-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 0.3125rem;
  border-radius: 9999px;
  background-color: var(--nav-badge-bg);
  color: var(--nav-badge-text);
  font-size: 0.75rem; /* 12px body inside the 18px pill */
  font-weight: 700;
  line-height: 1;
}

.nav-badge--bottom-bar {
  position: absolute;
  top: 6px;
  left: 50%;
  transform: translateX(2px); /* shifts the badge to the right of the icon */
  /* surface-colored border: separates the badge from the icon where they overlap */
  box-shadow: 0 0 0 2px var(--bg-surface);
}

/* --------------------------------------------------------------------------
   8. Flash messages
   -------------------------------------------------------------------------- */
.alerts-area .alert {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 56px;
  margin-bottom: 0;
  border-radius: 0;
}

/* Flash close button: 44×44px touch area */
.alert-close-button {
  width: 44px;
  height: 44px;
  padding: 0;
  margin-left: auto;
  background-size: 1em;
}

/* Bootstrap positions .btn-close absolutely inside alert-dismissible;
   with flex we bring it into the flow and reserve its spot. */
.alerts-area .alert-dismissible {
  padding-right: 1rem;
}

.alerts-area .alert-dismissible .btn-close {
  position: static;
}

/* Modal close X: 44×44px touch area (P-05 spec) */
.modal-header .btn-close {
  width: 44px;
  height: 44px;
  padding: 0;
  background-size: 1em;
}

/* --------------------------------------------------------------------------
   9. FAB — floating action button (P-04). CSS from the iteration 2 spec.
   -------------------------------------------------------------------------- */
.fab-action {
  position: fixed;
  bottom: calc(var(--bottom-bar-height) + 16px);
  right: 16px;
  z-index: 1020;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background-color: var(--color-primary);
  color: var(--color-primary-text);
  border: none;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: var(--shadow-float);
  font-size: 24px;
  cursor: pointer;
  text-decoration: none;
}

.fab-action:hover {
  background-color: var(--color-primary-dark);
  color: var(--color-primary-text);
}

.fab-action:focus-visible {
  outline: 3px solid var(--color-primary);
  outline-offset: 2px;
}

/* --------------------------------------------------------------------------
   10. Car card (P-04). CSS from the iteration 2 spec.
   -------------------------------------------------------------------------- */
.car-card {
  background-color: var(--bg-surface);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  padding: 1rem;
  margin-bottom: 0.75rem;
  box-shadow: var(--shadow-card);
  cursor: pointer;
}

.car-card__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 24px;
  margin-bottom: 0.25rem;
}

.car-card__name {
  font-size: 1.125rem;
  font-weight: 700;
  color: var(--text-main);
  margin: 0 0 0.125rem;
}

.car-card__meta {
  font-size: 0.875rem;
  color: var(--text-muted);
  margin: 0;
  /* It. 4 (spec A.3): the license plate becomes the plate component; the meta
     turns into a flex row to align plate + separator + year in one line. */
  display: flex;
  align-items: center;
  gap: 0.375rem;
  flex-wrap: wrap;
}

.car-card__divider {
  border: none;
  border-top: 1px solid var(--border-color);
  margin: 0.75rem 0;
}

.car-card__km {
  font-size: 1.375rem;
  font-weight: 700;
  color: var(--text-main);
  margin: 0 0 0.125rem;
}

.car-card__km--empty {
  font-size: 0.875rem;
  font-weight: 400;
  font-style: italic;
  color: var(--text-muted);
}

.car-card__km-meta {
  font-size: 0.75rem;
  color: var(--text-muted);
  margin: 0;
}

.car-card__edit-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  color: var(--text-muted);
  border-radius: var(--radius-btn);
  text-decoration: none;
  margin: -0.5rem -0.25rem -0.5rem 0;
}

.car-card__edit-btn:hover {
  color: var(--color-primary);
  background-color: var(--bg-surface-alt);
}

.car-card__edit-btn:focus-visible {
  outline: 3px solid var(--color-primary);
  outline-offset: 2px;
}

/* --------------------------------------------------------------------------
   11. Plan status badges (pill)
   -------------------------------------------------------------------------- */
.status-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;          /* icon + text (spec it. 4 §1) */
  height: 24px;
  padding: 0.25rem 0.625rem;
  border-radius: 9999px;
  font-size: 0.75rem;
  font-weight: 600;
  white-space: nowrap;
}

.status-badge--up-to-date {
  background-color: var(--state-ok-bg);
  color: var(--state-ok);
}

.status-badge--upcoming {
  background-color: var(--state-warning-bg);
  color: var(--state-warning);
}

.status-badge--overdue {
  background-color: var(--state-danger-bg);
  color: var(--state-danger);
}

/* HU-33 (P-19b §1.2) — Telegram linking-state badges, same pill as the plan
   status badges. «Pending» reuses the new info token; «unlinked» the warning
   token. The state is always shown as text too (icon + word), not by colour
   alone (WCAG 1.4.1). */
.status-badge--pending {
  background-color: var(--state-info-bg);
  color: var(--state-info);
}

.status-badge--unlinked {
  background-color: var(--state-warning-bg);
  color: var(--state-warning);
}

/* HU-45 (P-27, UX §0) — «Silenced» badge: the plan is still active and has a
   date, but its reminders are paused (notification_enabled=False). Neutral gray
   (--state-muted on --state-muted-bg = 9.2:1, AA). Like the rest, the state is
   also conveyed by text + icon (bi-bell-slash-fill), never by color alone
   (WCAG 1.4.1). */
.status-badge--silenciado {
  background-color: var(--state-muted-bg);
  color: var(--state-muted);
}

/* Placeholder — reserves the 24px of height until iteration 4 (P-04 spec) */
.status-badge--placeholder {
  display: inline-block;
  height: 24px;
  width: 0;
  padding: 0;
  visibility: hidden;
}

/* --------------------------------------------------------------------------
   12. Danger zone (P-05 edit). CSS from the iteration 2 spec.
   -------------------------------------------------------------------------- */
.danger-zone {
  background-color: var(--state-danger-bg);
  border: 1px solid var(--state-danger);
  border-radius: var(--radius-card);
  padding: 1rem;
  margin-top: 2rem;
}

/* On --state-danger-bg (#FEE2E2): --text-muted does not pass AA (~3.7:1); so
   --state-danger (#B91C1C → 7.1:1) and --text-main are used for main text. */
.danger-zone__title {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--state-danger);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin: 0 0 0.75rem;
}

.danger-zone__description {
  font-size: 0.875rem;
  color: var(--text-main);
  margin: 0 0 1rem;
}

/* --------------------------------------------------------------------------
   13. Login screen (P-01)
   -------------------------------------------------------------------------- */
.login-wrapper {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
}

.login-card {
  width: 100%;
  max-width: 420px;
}

.app-logo {
  font-size: 64px;
  line-height: 1;
  color: var(--color-primary);
}

/* --------------------------------------------------------------------------
   14. Narrow container for forms and lists (mobile-first, capped on desktop
       so the lines don't stretch)
   -------------------------------------------------------------------------- */
.narrow-container {
  width: 100%;
  max-width: 480px;
  margin-inline: auto;
  padding-inline: 1rem;
}

/* --------------------------------------------------------------------------
   15. Empty state
   -------------------------------------------------------------------------- */
.empty-state {
  text-align: center;
  padding: 3rem 1.5rem;
  /* The secondary text sits directly on --bg-page: blue-gray AA */
  color: var(--text-secundario-en-pagina);
}

.empty-state .bi {
  font-size: 48px;
  line-height: 1;
}

/* Key-screen variant (P-04): 64px icon in the primary color */
.empty-state--featured .bi {
  font-size: 64px;
  color: var(--color-primary);
}

.empty-state__title {
  font-size: 1rem;
  font-weight: 700;
  color: var(--text-main);
  margin: 0.75rem 0 0.25rem;
}

.empty-state__text {
  font-size: 0.875rem;
  margin: 0;
}

/* Empty-state action button: max-width 280px, centered (P-04 spec) */
.empty-state__action {
  width: 100%;
  max-width: 280px;
  margin-top: 1.5rem;
}

/* --------------------------------------------------------------------------
   16. Action row in lists (e.g. «Change password» in Profile)
   -------------------------------------------------------------------------- */
.action-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 48px;
  padding: 0.5rem 1rem;
  background-color: var(--bg-surface);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  color: var(--text-main);
  text-decoration: none;
}

/* The «Language» row in Profile (it. 4, spec B.6) uses a <button> that opens the
   offcanvas; it is normalized to 100% width and left-aligned text. */
button.action-row {
  width: 100%;
  text-align: left;
  font: inherit;
  cursor: pointer;
}

button.action-row:focus-visible {
  outline: 3px solid var(--color-primary);
  outline-offset: 2px;
}

.action-row:hover {
  background-color: var(--bg-surface-alt);
  color: var(--text-main);
}

.action-row .bi-chevron-right {
  color: var(--text-muted);
}

/* Row label with a leading icon (Profile): muted icon + text. */
.action-row__label {
  display: inline-flex;
  align-items: center;
  gap: 0.625rem;
  min-width: 0;
}

.action-row__label .bi {
  color: var(--text-muted);
  font-size: 1.125rem;
  flex-shrink: 0;
}

.action-row:hover .action-row__label .bi {
  color: var(--color-primary);
}

/* --------------------------------------------------------------------------
   17. HU-17 — Car photo in the list card (P-04)
   Spec: docs/ux/addendum-hu17-foto-coche.md («ready-to-copy CSS»).
   Two-column layout: 56×56 thumbnail on the left + body on the right.
   -------------------------------------------------------------------------- */
.car-card__layout {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
}

.car-card__photo-wrap {
  flex-shrink: 0;
}

.car-card__photo {
  width: 56px;
  height: 56px;
  border-radius: var(--radius-btn);
  object-fit: cover;
  object-position: center;
  display: block;
  /* Subtle inner frame (Solar White): lifts the light thumbnail off the card
     background without changing its size. Per-theme token (HU-50): dark hairline
     in light mode, light hairline in dark mode. */
  box-shadow: var(--shadow-photo-inset);
}

.car-card__photo--placeholder {
  background-color: var(--bg-surface-alt);
  display: flex;
  align-items: center;
  justify-content: center;
  /* Placeholder icon in muted coral (consistent with the detail hero). */
  color: var(--color-primary);
  opacity: 0.45;
  font-size: 24px;
}

.car-card__body {
  flex: 1;
  min-width: 0; /* allows the name to truncate inside the flex */
}

/* --------------------------------------------------------------------------
   18. P-06 — Car header in the detail view
   Spec: docs/ux/iteracion-3-detalle-historiales.md + addendum-hu17.
   The card + the 16:9 banner (or placeholder) on top.
   -------------------------------------------------------------------------- */
.car-detail-header {
  background-color: var(--bg-surface);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  padding: 1rem;
  margin: 1rem;
}

/* Hero (Solar White): the car photo is treated as the lead banner.
   Wraps the 16:9 banner and the status badge, which overlaps the top-right
   corner. It extends to the card edges by compensating for its padding
   (negative margin) and rounds only the top corners (20px). */
.car-detail-header__hero {
  position: relative;
  width: calc(100% + 2rem);
  margin: -1rem -1rem 0.75rem -1rem;
  border-radius: var(--radius-card) var(--radius-card) 0 0;
  overflow: hidden;
}

.car-detail-header__photo {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  object-position: center;
  display: block;
  /* Subtle inner border: separates light photos from the card border without
     changing the size (inset shadow, no layout impact). Per-theme token (HU-50). */
  box-shadow: var(--shadow-photo-inset);
}

.car-detail-header__photo--placeholder {
  background-color: var(--bg-surface-alt);
  display: flex;
  align-items: center;
  justify-content: center;
  /* Placeholder icon in muted coral (Solar White). */
  color: var(--color-primary);
  opacity: 0.45;
  font-size: 56px;
}

/* Status badge overlaid on the hero (top-right corner). The _badge_estado.html
   partial stays intact; this wrapper positions it and gives it a translucent
   background for legibility over any photo. */
.car-detail-header__hero .status-badge:not(.status-badge--placeholder) {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  z-index: 1;
  box-shadow: var(--shadow-photo-badge);
}

/* If there are no active plans the badge is the invisible placeholder: it must
   not reserve space inside the hero or break the banner. */
.car-detail-header__hero .status-badge--placeholder {
  position: absolute;
}

/* Car data below the banner. Same sizes/weights as .car-card__*
   (design system: 700 for values, km as the lead figure). */
.car-detail-header__name {
  font-size: 1.125rem;
  font-weight: 700;
  color: var(--text-main);
  margin: 0 0 0.125rem;
}

.car-detail-header__meta {
  font-size: 0.875rem;
  color: var(--text-muted);
  margin: 0;
  /* It. 4 (spec A.4): plate --detail + separator + year in one row. */
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.car-detail-header__divider {
  border: none;
  border-top: 1px solid var(--border-color);
  margin: 0.75rem 0;
}

.car-detail-header__km {
  font-size: 1.375rem;
  font-weight: 700;
  color: var(--text-main);
  margin: 0 0 0.125rem;
}

.car-detail-header__km--empty {
  font-size: 0.875rem;
  font-weight: 400;
  color: var(--text-muted);
  margin: 0;
}

.car-detail-header__km-meta {
  font-size: 0.75rem;
  color: var(--text-muted);
  margin: 0;
}

/* Edit pencil (44×44) in the detail's secondary header. Analogous to other
   icon-buttons; floats right without affecting login/profile. */
.edit-car-button {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  margin-left: auto; /* pushes the pencil to the far right of the header */
  color: var(--text-muted);
  border-radius: var(--radius-btn);
  text-decoration: none;
}

.edit-car-button:hover {
  color: var(--color-primary);
  background-color: var(--bg-surface-alt);
}

.edit-car-button:focus-visible {
  outline: 3px solid var(--color-primary);
  outline-offset: 2px;
}

/* --------------------------------------------------------------------------
   19. P-06 — Section segmented control (Maintenance / Readings)
   Spec: docs/ux/iteracion-3-detalle-historiales.md («new CSS»).
   -------------------------------------------------------------------------- */
.seg-control {
  display: flex;
  background-color: var(--bg-surface);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  overflow: hidden;
  margin: 0 1rem 0.75rem;
}

.seg-tab {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 44px;
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--text-muted);
  text-decoration: none;
  border: none;
  background: transparent;
  transition: background-color 0.15s, color 0.15s;
}

.seg-tab--active {
  background-color: var(--color-primary);
  color: var(--color-primary-text);
  font-weight: 600;
  pointer-events: none;
}

.seg-tab:not(.seg-tab--active):hover {
  background-color: var(--bg-surface-alt);
  color: var(--text-main);
}

.seg-tab:focus-visible {
  outline: 3px solid var(--color-primary);
  outline-offset: -3px;
  z-index: 1;
}

/* --------------------------------------------------------------------------
   19b. P-10b — Plan modality switch (HU-30, two options)
   Spec: docs/ux/p-10b-planes-solo-fecha.md §2. A .seg-control variant for use
   INSIDE a form: two <label>s each wrapping a hidden <input type=radio>.
   Clones .seg-control / .seg-tab (same tokens) without breaking the base.
   -------------------------------------------------------------------------- */
.seg-control--dos {
  /* Analogous to .seg-control--cinco: a two-equal-column grid. The lateral
     margin of .seg-control does not apply here (it lives inside .form-section). */
  display: grid;
  grid-template-columns: 1fr 1fr;
  margin: 0;
}

/* .seg-tab--radio: replicates the look of .seg-tab but as a <label> wrapping a
   radio (native keyboard operability). The radio is .visually-hidden. */
.seg-tab--radio {
  cursor: pointer;
  /* The <label> already gets display:flex and the .seg-tab height. */
}

.seg-tab--radio.seg-tab--active {
  /* The base .seg-tab--active applies pointer-events:none (valid for the <a>s
     of a tablist); on a radio it must stay clickable to toggle. */
  pointer-events: auto;
}

/* Visible focus on the label when its inner radio receives it (WCAG 2.4.7).
   :has() is the modern way; the :focus-within fallback covers browsers without
   :has (the radio is inside the label, so :focus-within also matches). */
.seg-tab--radio:focus-within {
  outline: 3px solid var(--color-primary);
  outline-offset: -3px;
  z-index: 1;
}

.seg-tab--radio:has(input:focus-visible) {
  outline: 3px solid var(--color-primary);
  outline-offset: -3px;
  z-index: 1;
}

/* Contextual help for the modality (role=note): secondary text below the
   switch, without the extra margin of the base .form-text. */
.mode-help {
  margin-top: 0.5rem;
  margin-bottom: 0;
}

/* --------------------------------------------------------------------------
   20. P-06 — Fixed contextual action bar (64px)
   Spec: docs/ux/iteracion-3-detalle-historiales.md. The sub-screen has no
   bottom navigation bar; this bar takes its place with the primary button of
   the active tab. <main> reserves its space with .with-action-bar.
   -------------------------------------------------------------------------- */
main.with-action-bar {
  /* The bar (64px fixed) must not cover the last content element.
     Reserve analogous to .with-bottom-bar (72px for the 64px bar). */
  padding-bottom: 80px;
}

/* «Info» tab (it. 5a): does not render a contextual action bar, so the reserved
   80px are unnecessary. This modifier restores the standard page bottom spacing
   without breaking the other tabs (backend debt #2). */
main.with-action-bar--no-bar {
  padding-bottom: 1rem;
}

.context-action-bar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  height: 64px;
  background-color: var(--bg-surface);
  border-top: 1px solid var(--border-color);
  display: flex;
  align-items: center;
  padding: 0 1rem;
  z-index: 1020;
}

.context-action-bar .btn {
  width: 100%;
  /* True vertical centering of the text: the button is an <a> with py-3;
     without flex, the baseline leaves it slightly high inside the 64px bar. */
  display: flex;
  align-items: center;
  justify-content: center;
}

/* --------------------------------------------------------------------------
   21. P-06 — History rows (maintenance and readings)
   Spec: docs/ux/iteracion-3-detalle-historiales.md («new CSS»).
   -------------------------------------------------------------------------- */
.history-list {
  margin: 0;
  padding: 0;
}

.reading-row {
  padding: 0.75rem 1rem;
  border-bottom: 1px solid var(--border-color);
  background-color: var(--bg-surface);
}

/* Maintenance row: the whole block is clickable → edit (HU-24).
   Same affordance pattern as .plan-row (no underline, visible focus). */
.maintenance-row {
  display: block;
  padding: 0.75rem 1rem;
  border-bottom: 1px solid var(--border-color);
  background-color: var(--bg-surface);
  text-decoration: none;
  color: inherit;
}

.maintenance-row:last-child {
  border-bottom: none;
}

.maintenance-row:hover {
  background-color: var(--bg-surface-alt);
}

.maintenance-row:focus-visible {
  outline: 3px solid var(--color-primary);
  outline-offset: -3px;
}

.reading-row--maintenance {
  background-color: var(--bg-surface-alt);
}

.history-row__header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.5rem;
  margin-bottom: 0.25rem;
}

.history-row__type {
  font-size: 1rem;
  font-weight: 600;
  color: var(--text-main);
  display: flex;
  align-items: center;
  gap: 0.375rem;
}

.history-row__km {
  font-size: 1rem;
  font-weight: 700;
  color: var(--text-main);
}

.history-row__date {
  font-size: 0.875rem;
  color: var(--text-muted);
  white-space: nowrap;
}

.history-row__meta {
  font-size: 0.875rem;
  color: var(--text-muted);
}

.history-row__price {
  font-size: 0.875rem;
  color: var(--text-muted);
  margin-top: 0.125rem;
}

.history-row__source {
  font-size: 0.75rem;
  color: var(--text-muted);
  display: flex;
  align-items: center;
  gap: 0.25rem;
  margin-top: 0.125rem;
}

/* ADR-024: a maintenance can be tagged with SEVERAL types. Each type is shown
   as a chip inside .history-row__type. The chips wrap on narrow screens and sit
   on the row surface (--bg-surface / slate), so the tokens keep AA in both
   themes. min-width:0 lets the chip container shrink beside the date. */
.type-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 0.375rem;
  min-width: 0;
}

.type-chip {
  display: inline-flex;
  align-items: center;
  padding: 0.125rem 0.5rem;
  font-size: 0.8125rem;
  font-weight: 600;
  line-height: 1.3;
  color: var(--color-primary);
  background-color: var(--bg-surface-alt);
  border: 1px solid var(--border-color);
  border-radius: 999px;
}

/* «Load more» button: 48px tall (touch area), full width. */
.load-more-button {
  min-height: 48px;
}

/* End-of-pagination line: sits on --bg-page → blue-gray AA (v2 rule). */
.pagination-end {
  font-size: 0.75rem;
  color: var(--text-secundario-en-pagina) !important;
  text-align: center;
  padding: 0.75rem 1rem;
}

/* --------------------------------------------------------------------------
   22. P-07/P-08 — Odometer rollback warning
   Spec: docs/ux/iteracion-3-detalle-historiales.md («new CSS»).
   The km field uses an amber border (--state-warning #92400E, 5.5:1 on white),
   NOT is-invalid.
   -------------------------------------------------------------------------- */
.form-control.km-warning {
  border-color: var(--state-warning); /* #92400E, 5.5:1 on white */
  border-width: 2px;
}

.form-control.km-warning:focus {
  box-shadow: 0 0 0 0.25rem rgba(146, 64, 14, 0.25);
}

.warning-block {
  background-color: var(--state-warning-bg);
  border: 1px solid var(--state-warning);
  border-radius: var(--radius-btn);
  padding: 0.75rem;
  margin-bottom: 1rem;
  color: var(--state-warning);
}

.warning-block__title {
  font-size: 0.875rem;
  font-weight: 600;
  display: flex;
  align-items: center;
  gap: 0.375rem;
  margin-bottom: 0.375rem;
}

.warning-block__text {
  font-size: 0.875rem;
  margin-bottom: 0.75rem;
}

.warning-block .form-check-label {
  font-size: 0.875rem;
  line-height: 1.4;
  cursor: pointer;
}

.warning-block .form-check {
  min-height: 44px;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding-left: 0;
}

.warning-block .form-check-input {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  margin: 0;
}

/* --------------------------------------------------------------------------
   23. P-05 — Photo section of the car form (HU-17)
   Spec: docs/ux/addendum-hu17-foto-coche.md («ready-to-copy CSS»).
   -------------------------------------------------------------------------- */
/* The «Vencimientos» section (HU-43, P-05b) uses <fieldset class="form-section">
   with <legend class="form-section-title">. The fieldset's native border/padding
   is neutralized (some browsers don't reset it) so it looks like a flat section,
   just like the rest of the form. */
.form-section {
  min-width: 0;     /* prevents the fieldset from overflowing in flex/grid */
  margin: 0;
  padding: 0;
  border: 0;
}

.form-section-title {
  font-size: 0.75rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
  margin: 0 0 0.75rem;
  /* <legend> brings a large font-size and float by default: it is normalized so
     it looks identical to the photo section title (which is an <h2>). */
  float: none;
  width: auto;
  padding: 0;
}

.current-photo-preview {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 0.75rem;
}

.current-photo-preview__img {
  width: 80px;
  height: 80px;
  border-radius: var(--radius-btn);
  object-fit: cover;
  object-position: center;
  border: 1px solid var(--border-color);
  flex-shrink: 0;
}

.current-photo-preview__label {
  font-size: 0.875rem;
  color: var(--text-muted);
}

.remove-photo {
  margin-bottom: 0.75rem;
}

/* 44px touch area for the «Remove current photo» checkbox (WCAG 2.5.8). */
.remove-photo .form-check-input {
  width: 20px;
  height: 20px;
  margin-top: 0;
}

.remove-photo .form-check-label {
  min-height: 44px;
  display: flex;
  align-items: center;
  font-size: 0.875rem;
  cursor: pointer;
}

/* --------------------------------------------------------------------------
   24. P-09 — Maintenance types management (HU-12)
   Spec: docs/ux/iteracion-3-p09-tipos-mantenimiento.md («new CSS»).
   «My types» (editable) + «Factory types» (collapsible, read-only).
   -------------------------------------------------------------------------- */

/* Card wrapping the «My types» block (header + rows / empty state). */
.types-list-wrapper {
  background-color: var(--bg-surface);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  margin: 0 1rem 1rem;
  overflow: hidden;
}

/* Block header: «My types (N)». */
.types-header {
  display: flex;
  align-items: baseline;
  gap: 0.375rem;
  padding: 0.75rem 1rem;
  background-color: var(--bg-surface);
  border-bottom: 1px solid var(--border-color);
}

.types-header__title {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--text-main);
}

.types-header__counter {
  font-size: 0.875rem;
  color: var(--text-muted);
}

/* Row for an own type (active). */
.own-type-row {
  padding: 0.75rem 1rem;
  border-bottom: 1px solid var(--border-color);
  background-color: var(--bg-surface);
}

/* Last row without a double border where the card closes. */
.own-type-row:last-child {
  border-bottom: none;
}

/* Inactive variant: section background and muted italic text. */
.own-type-row--inactive {
  background-color: var(--bg-surface-alt);
}

.own-type-row__header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.25rem;
}

.own-type-row__indicator {
  width: 10px;
  height: 10px;
  flex-shrink: 0;
}

.own-type-row__name {
  font-size: 1rem;
  font-weight: 600;
  color: var(--text-main);
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.own-type-row--inactive .own-type-row__name {
  font-weight: 400;
  font-style: italic;
  color: var(--text-muted);
}

.own-type-row__description {
  font-size: 0.875rem;
  color: var(--text-muted);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  margin-bottom: 0.25rem;
}

.own-type-row__actions {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  flex-shrink: 0;
}

/* Row action buttons: minimum 44px touch area (WCAG 2.5.8). The «Reactivate»
   form must not break the flex layout of the actions. */
.own-type-row__actions .btn,
.own-type-row__actions .btn-sm {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.own-type-row__actions form {
  margin: 0;
  display: inline-flex;
}

/* Card for the «Factory types» block (collapsible). */
.factory-block {
  background-color: var(--bg-surface);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  margin: 0 1rem 1rem;
  overflow: hidden;
}

/* <details> trigger header: chevron that rotates when opened. */
.factory-block-summary {
  list-style: none;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.75rem 1rem;
  background-color: var(--bg-surface-alt);
  cursor: pointer;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--text-muted);
  min-height: 44px;
  user-select: none;
}

.factory-block-summary::-webkit-details-marker {
  display: none;
}

.factory-block-summary .bi-chevron-down {
  margin-left: auto;
  transition: transform 0.2s ease;
}

details[open] .factory-block-summary .bi-chevron-down {
  transform: rotate(180deg);
}

.factory-block-summary:focus-visible {
  outline: 3px solid var(--color-primary);
  outline-offset: -3px;
}

/* «Factory» badge (informational pill, read-only). */
.factory-badge {
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--text-muted);
  background-color: var(--bg-surface-alt);
  border: 1px solid var(--border-color);
  border-radius: 9999px;
  padding: 0.125rem 0.5rem;
  white-space: nowrap;
  flex-shrink: 0;
}

/* Row for a global (factory) type. */
.global-type-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.75rem 1rem;
  border-bottom: 1px solid var(--border-color);
  background-color: var(--bg-surface);
}

.global-type-row:last-child {
  border-bottom: none;
}

.global-type-row .bi-lock {
  color: var(--text-muted);
  flex-shrink: 0;
}

.global-type-row__name {
  font-size: 1rem;
  font-weight: 400;
  color: var(--text-muted);
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Empty state of «My types» inside the card: on a white surface, so the
   secondary text can use --text-muted (AA rule). */
.types-list-wrapper .empty-state {
  color: var(--text-muted);
}

.types-list-wrapper .empty-state .bi-tag {
  color: var(--color-primary);
}

/* --------------------------------------------------------------------------
   25. P-08 — «Manage my maintenance types» link below the select
   Spec: docs/ux/iteracion-3-p09-tipos-mantenimiento.md (dual access to P-09).
   Discreet link consistent with .subtle-link, with an icon and 44px touch area.
   -------------------------------------------------------------------------- */
.manage-types-link {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  min-height: 44px;
  margin-top: 0.25rem;
  color: var(--color-primary);
  text-decoration: none;
  font-size: 0.875rem;
  font-weight: 500;
}

.manage-types-link:hover {
  color: var(--color-primary-dark);
  text-decoration: underline;
}

.manage-types-link:focus-visible {
  outline: 3px solid var(--color-primary);
  outline-offset: 2px;
  border-radius: var(--radius-btn);
}

/* --------------------------------------------------------------------------
   25b. P-08 — Multi-type picker (ADR-024)
   The single <select> became a <fieldset> of ``name="types"`` checkboxes split
   into two groups (Catálogo / «Mis tipos»). Mobile-first, no JS. The <fieldset>
   reset mirrors .form-section (some browsers keep native border/padding).
   -------------------------------------------------------------------------- */
.types-picker {
  min-width: 0;
  margin: 0 0 1rem;
  padding: 0;
  border: 0;
}

.types-picker__legend {
  /* <legend> defaults to a large font and float: normalize to a form label. */
  float: none;
  width: auto;
  padding: 0;
  margin-bottom: 0.25rem;
}

.types-picker__hint {
  margin-top: 0;
  margin-bottom: 0.5rem;
}

.types-group + .types-group {
  margin-top: 0.75rem;
}

/* Group heading (Catálogo / «Mis tipos»): sits on --bg-page; use the AA token
   for text on the page background. */
.types-group__title {
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-secundario-en-pagina);
  margin: 0 0 0.375rem;
}

/* The catalog is large (56 items): a scroll-contained, multi-column grid keeps
   it comfortable instead of an endless single column. On mobile it is a single
   column; from 480px it flows into auto-fill columns. The max-height caps the
   list and scrolls inside, so the submit button stays reachable. */
.types-group__list {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.125rem 0.75rem;
  max-height: 15rem;
  overflow-y: auto;
  padding: 0.5rem 0.75rem;
  background-color: var(--bg-surface);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-btn);
}

@media (min-width: 480px) {
  .types-group__list {
    grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr));
  }
}

/* Comfortable touch target per checkbox row (WCAG 2.5.8): the label spans the
   full row and is at least 44px tall. */
.types-check {
  margin-bottom: 0;
  padding-left: 1.75rem;
}

.types-check .form-check-input {
  width: 1.15rem;
  height: 1.15rem;
  margin-left: -1.75rem;
  margin-top: 0.6rem;
}

.types-check__label {
  display: flex;
  align-items: center;
  min-height: 44px;
  font-size: 0.9375rem;
  color: var(--text-main);
  cursor: pointer;
}

.types-group__empty {
  font-size: 0.875rem;
  color: var(--text-secundario-en-pagina);
  margin: 0;
}

/* Invalid state on the whole group: red hairline around the lists (the field
   error text is rendered below via .invalid-feedback). */
.types-picker.is-invalid .types-group__list {
  border-color: var(--color-error);
}

/* --------------------------------------------------------------------------
   26. Iteration 4 — Maintenance plans (HU-13)
   Spec: docs/ux/iteracion-4-planes.md (§1, §2). Plan rows in the «Plans» tab of
   P-06 + a 3-tab segmented control. Tokens v3 «Solar White».
   -------------------------------------------------------------------------- */

/* Plan row: the whole block is clickable → edit the plan. */
.plan-row {
  display: block;
  padding: 0.75rem 1rem;
  border-bottom: 1px solid var(--border-color);
  background-color: var(--bg-surface);
  text-decoration: none;
  color: inherit;
}

.plan-row:last-child {
  border-bottom: none;
}

.plan-row:hover {
  background-color: var(--bg-surface-alt);
}

.plan-row:focus-visible {
  outline: 3px solid var(--color-primary);
  outline-offset: -3px;
}

.plan-row__header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 0.5rem;
  margin-bottom: 0.375rem;
}

.plan-row__type {
  font-size: 1rem;
  font-weight: 600;
  color: var(--text-main);
  display: flex;
  align-items: center;
  gap: 0.375rem;
  flex: 1;
  min-width: 0;
}

.plan-row__rule {
  font-size: 0.875rem;
  color: var(--text-muted);
  margin: 0 0 0.25rem;
}

.plan-row__due {
  font-size: 0.875rem;
  color: var(--text-main);
  font-weight: 500;
  margin: 0 0 0.125rem;
}

.plan-row__due-note {
  font-size: 0.75rem;
  color: var(--text-muted);
  margin: 0;
}

/* HU-30 / P-10b §5 — Actions for the row of a date-only plan.
   In these plans the row is a <div> (not an <a>) with explicit «Editar» and
   «Renovar» buttons, to avoid nesting interactive elements inside a link. */
.plan-row__actions {
  display: flex;
  gap: 0.5rem;
  margin-top: 0.625rem;
}

/* Row action buttons: minimum 44px touch area (WCAG 2.5.8) and equal width
   distribution on mobile. .btn-outline-* already provides min-height 48px.
   HU-26 adds «Registrar ahora» (.plan-row__register) with the same sizing:
   in the Plans tab it accompanies «Editar» (overdue/upcoming interval plans);
   in the alerts panel it stands alone (interval plan) or is replaced by
   «Renovar» (date-only plan). */
.plan-row__edit,
.plan-row__renew,
.plan-row__register {
  flex: 1;
  min-height: 44px;
}

/* Alerts panel (HU-26): when the row carries a quick action it is no longer an
   <a> and becomes a <div> (no nesting of interactive elements inside a link).
   The plan type becomes an inline link to the car's Plans tab; it keeps the
   row affordance (no underline except on hover/focus). */
.plan-row__type-link {
  text-decoration: none;
  color: var(--text-main);
}

.plan-row__type-link:hover {
  text-decoration: underline;
}

.plan-row__type-link:focus-visible {
  outline: 3px solid var(--color-primary);
  outline-offset: 2px;
  border-radius: 4px;
}

/* --------------------------------------------------------------------------
   Alerts panel (P-11 / HU-15). Reuses .history-list + .plan-row +
   .status-badge from the Plans tab so each alert reads identically to the
   car detail. It only adds the per-car frame (a clickable header that links
   to the Plans tab) and the intro. Mobile-first.
   -------------------------------------------------------------------------- */
.alerts-panel__intro {
  font-size: 0.875rem;
  color: var(--text-muted);
  margin: 0 0 1rem;
}

/* Per-car group: card wrapping the car header + its plan rows, with the same
   visual language as .car-card (radius, shadow, border). */
.alerts-car-group {
  background-color: var(--bg-surface);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  margin-bottom: 0.75rem;
  box-shadow: var(--shadow-card);
  overflow: hidden;
}

/* Car header: full link to the detail's Plans tab. Comfortable touch area
   (>=56px), visible focus, no underline (row affordance). */
.alerts-car-group__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  min-height: 56px;
  padding: 0.75rem 1rem;
  border-bottom: 1px solid var(--border-color);
  text-decoration: none;
  color: inherit;
}

.alerts-car-group__header:hover {
  background-color: var(--bg-surface-alt);
}

.alerts-car-group__header:focus-visible {
  outline: 3px solid var(--color-primary);
  outline-offset: -3px;
}

.alerts-car-group__car {
  min-width: 0;
}

.alerts-car-group__name {
  font-size: 1.125rem;
  font-weight: 700;
  color: var(--text-main);
  margin: 0 0 0.125rem;
}

.alerts-car-group__meta {
  font-size: 0.875rem;
  color: var(--text-muted);
  display: flex;
  align-items: center;
  gap: 0.375rem;
}

.alerts-car-group__chevron {
  color: var(--text-muted);
  font-size: 1.25rem;
  flex-shrink: 0;
}

/* --------------------------------------------------------------------------
   Visual license plate (it. 4, spec A.2/A.5). Solar White, WCAG 2.2 AA.
   Variants: --compact (list P-04), --detail (P-06 and P-05 preview),
   --eu (with a blue band) / --other (plain white, no band, for 'OTHER').
   -------------------------------------------------------------------------- */
.plate{display:inline-flex;align-items:stretch;background-color:var(--plate-bg);border:1.5px solid var(--plate-border);border-radius:var(--plate-radius);overflow:hidden;box-shadow:0 1px 3px rgba(0,0,0,0.18),inset 0 1px 0 rgba(255,255,255,0.8);vertical-align:middle;flex-shrink:0}
.plate__band{display:flex;flex-direction:column;align-items:center;justify-content:center;background-color:var(--plate-band-bg);color:var(--plate-band-text);padding:0 3px}
.plate__country{font-weight:700;line-height:1;letter-spacing:0.5px;text-transform:uppercase;color:var(--plate-band-text)}
.plate__number-wrap{display:flex;align-items:center;justify-content:center;padding:0 6px}
.plate__number{font-family:ui-monospace,"Courier New",Courier,monospace;font-weight:700;color:var(--plate-text);text-transform:uppercase;letter-spacing:1px;line-height:1;white-space:nowrap}
.plate--compact{height:26px}
.plate--compact .plate__band{width:16px;min-width:16px}
.plate--compact .plate__country{font-size:9px;letter-spacing:0}
.plate--compact .plate__number-wrap{padding:0 5px}
.plate--compact .plate__number{font-size:0.75rem;letter-spacing:1.5px}
.plate--detail{height:38px}
.plate--detail .plate__band{width:24px;min-width:24px}
.plate--detail .plate__country{font-size:13px;letter-spacing:0.5px}
.plate--detail .plate__number-wrap{padding:0 8px}
.plate--detail .plate__number{font-size:1rem;letter-spacing:2px}
.plate--other .plate__number-wrap{padding:0 8px}

/* Preview in the form (spec A.5): plate --detail + label. */
.plate-preview{display:flex;align-items:center;gap:0.75rem;margin:0.5rem 0 1rem}
.plate-preview__label{font-size:0.75rem;color:var(--text-muted);margin:0;white-space:nowrap}

/* --------------------------------------------------------------------------
   Language selector (6 languages, it. 4, spec PART B). Triple access (header,
   login, profile) + shared offcanvas bottom sheet. Solar White, WCAG 2.2 AA.
   Contrasts verified: name 17.9:1, active coral 5.5:1, active code 5.5:1.
   -------------------------------------------------------------------------- */
.lang-trigger{display:flex;align-items:center;justify-content:center;min-width:44px;min-height:44px;padding:0 8px;background-color:var(--bg-surface-alt);border:1.5px solid var(--border-color);border-radius:8px;cursor:pointer;flex-shrink:0}
.lang-trigger:hover{background-color:var(--border-color)}
.lang-trigger:focus-visible{outline:3px solid var(--color-primary);outline-offset:2px}
.lang-trigger[aria-expanded="true"]{background-color:var(--color-primary);border-color:var(--color-primary)}
.lang-trigger__code{font-size:0.75rem;font-weight:700;letter-spacing:0.5px;color:var(--text-main);line-height:1}
.lang-trigger[aria-expanded="true"] .lang-trigger__code{color:var(--color-primary-text)}
.lang-offcanvas{height:auto;max-height:70vh;border-radius:16px 16px 0 0;border-top:1px solid var(--border-color)}
.lang-offcanvas .offcanvas-header{border-bottom:1px solid var(--border-color);padding:1rem 1rem 1rem 1.25rem}
.lang-offcanvas .offcanvas-title{font-size:1rem;font-weight:600;color:var(--text-main);display:flex;align-items:center;gap:0.5rem;margin:0}
.lang-offcanvas__body{padding:0.5rem 0;overflow-y:auto}
.lang-offcanvas__list{list-style:none;margin:0;padding:0}
.lang-offcanvas__form{margin:0}
.lang-offcanvas__option{display:flex;align-items:center;gap:0.75rem;width:100%;min-height:56px;padding:0 1.25rem;background:transparent;border:none;text-align:left;cursor:pointer;color:var(--text-main);font-size:1rem;font-weight:400}
.lang-offcanvas__option:hover{background-color:var(--bg-surface-alt)}
.lang-offcanvas__option:focus-visible{outline:3px solid var(--color-primary);outline-offset:-3px;z-index:1;position:relative}
.lang-offcanvas__option--active{color:var(--color-primary);font-weight:600}
.lang-offcanvas__check{display:flex;align-items:center;justify-content:center;width:20px;height:20px;flex-shrink:0;font-size:1rem;color:var(--color-primary)}
.lang-offcanvas__name{flex:1}

/* --------------------------------------------------------------------------
   27. Iteration 5a — «Info» tab: Personal notes (HU-20) and Technical data
   (HU-22) in P-06.
   Spec: docs/ux/iteracion-5a-notas-info.md (§«new CSS» + a 4-tab segmented
   control). Tokens v3 «Solar White», mobile-first 360px, WCAG 2.2 AA.
   -------------------------------------------------------------------------- */

/* 5-tab tab rail (Maintenance / Readings / Plans / Info / Documents),
   spec v2 §1. The 5 don't fit fixed at 360px: a scrollable pattern (overflow-x
   with scroll-snap, no visible scrollbar). Active tab = 3px coral underline +
   coral text 600 (NOT a filled background). Replaces --three/--four (removed).
   These selectors are MORE specific than the base .seg-control / .seg-tab, so
   they win: the base border/radius/overflow:hidden and the filled background of
   the base .seg-tab--active are overridden. At 360px: 4 visible tabs (88px each)
   + a peek of the 5th, inviting horizontal scrolling. */
/* Card-shaped container: same lateral margins (1rem) as the rest of the
   surfaces to fix the full-bleed misalignment; the radius clips the tabs and
   position:relative anchors the scroll affordance gradient. */
.seg-control--five {
  display: flex;
  background-color: var(--bg-surface);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  overflow: hidden; /* the radius clips the tabs */
  margin: 0 1rem 0.75rem; /* same lateral margin as the cards */
  position: relative; /* for the affordance gradient */
}

/* Inner rail: the horizontal-scroll container with scroll-snap, no visible
   scrollbar (scrolling still works). */
.seg-control--five__rail {
  display: flex;
  overflow-x: auto;
  overflow-y: visible;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none; /* Firefox: no visible scrollbar */
  width: 100%;
}

/* WebKit/Blink: hide the rail's scrollbar. */
.seg-control--five__rail::-webkit-scrollbar {
  display: none;
}

.seg-control--five .seg-tab {
  flex: 0 0 auto;
  min-width: 96px;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 44px;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--text-muted);
  text-decoration: none;
  white-space: nowrap;
  scroll-snap-align: start;
  background: transparent;
  border: none;
  border-bottom: 3px solid transparent;
  padding: 0 0.75rem;
  transition: color 0.15s, border-color 0.15s;
  position: relative;
}

.seg-control--five .seg-tab--active {
  background-color: transparent; /* overrides the base coral fill */
  color: var(--color-primary);
  font-weight: 600;
  border-bottom-color: var(--color-primary);
  pointer-events: none;
}

.seg-control--five .seg-tab:not(.seg-tab--active):hover {
  color: var(--text-main);
  background-color: var(--bg-surface-alt);
}

.seg-control--five .seg-tab:focus-visible {
  outline: 3px solid var(--color-primary);
  outline-offset: -3px; /* ring inside the rounded border, no clipping */
  z-index: 1;
  border-radius: 4px;
}

/* Scroll affordance: a gradient on the right that hints at hidden content.
   At >=768px the tabs share the width and there is no scroll, so it is hidden. */
.seg-control--five::after {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  width: 48px;
  height: 100%;
  background: linear-gradient(
    to right,
    rgba(var(--scroll-fade-rgb), 0) 0%,
    rgba(var(--scroll-fade-rgb), 0.92) 100%
  );
  border-radius: 0 var(--radius-card) var(--radius-card) 0;
  pointer-events: none;
  z-index: 2;
  transition: opacity 0.2s;
}

@media (min-width: 768px) {
  .seg-control--five .seg-tab {
    flex: 1;
    min-width: 0;
    padding: 0 1rem;
  }

  .seg-control--five::after {
    display: none;
  }
}

/* Section card of the Info tab («Personal notes» and «Technical data»): same
   depth as the rest of the system's surfaces. 1rem lateral margins (aligned
   with the header and the segmented control) and vertical spacing between the
   two cards. */
.info-section-card {
  background-color: var(--bg-surface);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  padding: 1rem;
  margin: 0 1rem 0.75rem;
}

/* Header of each section card: title (with icon) + «Editar» button anchored to
   the right. */
.info-section-header {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  margin-bottom: 0.75rem;
}

.info-section-header__title {
  font-size: 1rem;
  font-weight: 600;
  color: var(--text-main);
  flex: 1;
  display: flex;
  align-items: center;
  gap: 0.375rem;
  margin: 0;
}

.info-section-header__title .bi {
  color: var(--color-primary);
}

/* Each section's «Editar» button: minimum 44×44px touch area (WCAG 2.5.8).
   The 44px min-height coexists with the 48px of .btn-primary because this is a
   .btn-outline-secondary, which does not receive that rule. */
.info-section-header__edit {
  min-height: 44px;
  min-width: 44px;
  padding: 0.375rem 0.75rem;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* Bootstrap's .btn-outline-secondary uses a gray (#6c757d) that does not reach
   AA on white; it is reassigned to the main text token with the system border so
   «Editar» is legible and consistent with Solar White. */
.info-section-header__edit.btn-outline-secondary {
  --bs-btn-color: var(--text-main);
  --bs-btn-border-color: var(--border-color);
  --bs-btn-hover-bg: var(--bg-surface-alt);
  --bs-btn-hover-border-color: var(--color-primary);
  --bs-btn-hover-color: var(--color-primary);
  --bs-btn-active-bg: var(--bg-surface-alt);
  --bs-btn-active-border-color: var(--color-primary);
  --bs-btn-active-color: var(--color-primary);
  font-weight: 500;
}

.info-section-header__edit:focus-visible {
  outline: 3px solid var(--color-primary);
  outline-offset: 2px;
  box-shadow: none;
}

/* --- «Personal notes» section (HU-20): read mode --- */
.personal-notes__text {
  font-size: 1rem;
  color: var(--text-main);
  margin: 0;
  white-space: pre-wrap;
  word-break: break-word;
}

/* Empty notes state: muted italic (0.875rem). On a white surface, --text-muted
   meets AA. Bootstrap's .fst-italic/.text-muted already apply; this rule only
   sets the body size and removes the margin. */
.personal-notes__empty {
  font-size: 0.875rem;
  margin: 0;
}

/* --- «Technical data» section (HU-22): read mode --- */
.technical-data {
  margin: 0;
}

.technical-data__pair {
  margin-bottom: 0.75rem;
}

.technical-data__pair:last-of-type {
  margin-bottom: 0;
}

.technical-data__label {
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  margin-bottom: 0.125rem;
}

.technical-data__value {
  font-size: 1rem;
  color: var(--text-main);
  margin: 0;
}

.technical-data__value--empty {
  font-style: italic;
  color: var(--text-muted);
}

/* Empty state of the whole technical sheet: muted italic (0.875rem). */
.technical-data__empty {
  font-size: 0.875rem;
  margin: 0;
}

/* --- Inline flash (save success/error, role="alert") --- */
/* Compact notice inside the section card (not the global .alerts-area bar).
   System success green on its background (AA verified). */
.inline-flash {
  font-size: 0.875rem;
  border-radius: var(--radius-btn);
  padding: 0.5rem 0.75rem;
  margin: 0 0 0.75rem;
}

.inline-flash--success {
  color: var(--color-success);
  background-color: var(--color-success-bg);
}

.inline-flash--error {
  color: var(--color-error);
  background-color: var(--color-error-bg);
}

/* --- Inline editing: fields and actions --- */
/* Block for one field of the technical sheet form (label + input + help/error). */
.form-field {
  margin-bottom: 0.75rem;
}

.form-field .form-text {
  margin-top: 0.25rem;
}

/* Inline-editing actions: «Guardar» (primary, full width, 48px) and «Cancelar»
   (link, 44px). In a column and centered for the mobile pattern. */
.info-section-actions {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 0.25rem;
  margin-top: 1rem;
}

/* «Cancelar» (.btn-link): minimum 44px touch area and the system link color;
   .btn-primary already gets its 48px from section 3. */
.info-section-actions .btn-link {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--color-primary);
  font-weight: 500;
}

.info-section-actions .btn-link:hover {
  color: var(--color-primary-dark);
}

/* --- External links at the foot of the «Technical data» card, always visible ---
   Container with the parts and parts-diagram links, plus the recommended-oil
   dropdown (.oil-selector). The plain links share the same visual treatment;
   the container handles the separation from the sheet above and the layout
   (column on mobile, row from tablet up). */
.external-links {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  border-top: 1px solid var(--border-color);
  margin-top: 0.75rem;
  padding-top: 0.25rem;
}

.parts-link,
.parts-diagram-link {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--color-primary);
  text-decoration: none;
  padding: 0.5rem 0;
  min-height: 44px;
}

.parts-link:hover,
.parts-diagram-link:hover {
  text-decoration: underline;
  color: var(--color-primary-dark);
}

.parts-link:focus-visible,
.parts-diagram-link:focus-visible {
  outline: 3px solid var(--color-primary);
  outline-offset: 2px;
  border-radius: 4px;
}

/* From tablet up (≥768px) the links lay out in a row, left-aligned and with
   generous spacing; flex-wrap lets the third one wrap to a new line if it
   doesn't fit on narrow screens within this range. */
@media (min-width: 768px) {
  .external-links {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 1.5rem;
  }
}

/* --- Recommended-oil dropdown (native <details>) ---
   Replaces the old plain .oil-link link. The <summary> is the trigger (same
   visual look as its sibling plain links) and on opening it expands the links
   by brand. The native marker is hidden and a custom rotating chevron is used,
   following the .factory-block-summary pattern. */
.oil-selector {
  width: 100%;
}

.oil-selector__trigger {
  list-style: none;
  display: flex;
  align-items: center;
  gap: 0.375rem;
  min-height: 44px;
  padding: 0.5rem 0;
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--color-primary);
  cursor: pointer;
  user-select: none;
  text-decoration: none;
}

.oil-selector__trigger::-webkit-details-marker {
  display: none;
}

.oil-selector__trigger:hover {
  color: var(--color-primary-dark);
  text-decoration: underline;
}

.oil-selector__trigger:focus-visible {
  outline: 3px solid var(--color-primary);
  outline-offset: 2px;
  border-radius: 4px;
}

.oil-selector__chevron {
  margin-left: auto;
  transition: transform 0.2s ease;
  font-size: 1rem;
}

.oil-selector[open] .oil-selector__chevron {
  transform: rotate(180deg);
}

.oil-selector__brands {
  display: flex;
  flex-direction: column;
  padding-left: 1.625rem;
  padding-top: 0.25rem;
}

.oil-selector__brand-link {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  min-height: 44px;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--color-primary);
  text-decoration: none;
}

.oil-selector__brand-link .bi {
  font-size: 0.8125rem;
}

.oil-selector__brand-link:hover {
  color: var(--color-primary-dark);
  text-decoration: underline;
}

.oil-selector__brand-link:focus-visible {
  outline: 3px solid var(--color-primary);
  outline-offset: 2px;
  border-radius: 4px;
}

/* From tablet up (≥768px) the dropdown blends into the link row: it takes only
   the space it needs and the brands align left without indentation. */
@media (min-width: 768px) {
  .oil-selector {
    flex: 0 0 auto;
    width: auto;
  }

  .oil-selector__trigger {
    width: auto;
  }

  .oil-selector__chevron {
    margin-left: 0.25rem;
  }

  .oil-selector__brands {
    padding-left: 0;
    width: max-content;
  }
}

/* --- htmx loading indicator (spinner while the save POST travels) --- */
/* htmx toggles .htmx-request on the element that fires the request. The
   .htmx-indicator span of the «Guardar» button is hidden at rest and appears
   (inline) only during the request. We keep it as a visible Bootstrap spinner. */
.htmx-indicator {
  display: none;
}

.htmx-request .htmx-indicator,
.htmx-request.htmx-indicator {
  display: inline-flex;
}

/* The span is .visually-hidden (text «Saving» for screen readers). During the
   request we show a visible spinner without taking the text out of the
   accessible flow: a ::before is added with Bootstrap's spinning spinner. */
.htmx-request .info-section-actions .btn-primary::before {
  content: "";
  display: inline-block;
  width: 1rem;
  height: 1rem;
  margin-right: 0.5rem;
  border: 0.15em solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: garagio-spin 0.75s linear infinite;
}

@keyframes garagio-spin {
  to { transform: rotate(360deg); }
}

/* While submitting, the «Guardar» button accepts no further clicks (prevents a
   double POST) without changing its color (still primary, not visually «disabled»). */
.htmx-request .info-section-actions .btn-primary {
  pointer-events: none;
}

/* --------------------------------------------------------------------------
   28. Iteration v2 — «Documents» tab (P-06 / P-11), VIN lookup (NHTSA)
   and equivalent tires.
   Spec: docs/ux/iteracion-v2-pestanas-documentos-vin-neumaticos.md.
   Tokens v3 «Solar White», mobile-first 360px, WCAG 2.2 AA.
   -------------------------------------------------------------------------- */

/* Empty state of «Documents» (spec v2 §2): coral icon at 48px (the base size is
   already 48px; here only the primary color is applied, as the spec asks). */
.empty-state--documents .bi {
  color: var(--color-primary);
}

/* --- «Documents» tab: list of rows (spec v2 §2) --- */
/* Each row: header (extension icon + type), optional description and date, and
   «View» / «Delete» actions. No lateral margins of their own: they already live
   inside #panel-tab, which reserves the page gutter. */
.document-row {
  padding: 0.75rem 1rem;
  border-bottom: 1px solid var(--border-color);
  background-color: var(--bg-surface);
}

.document-row:first-child {
  border-top: 1px solid var(--border-color);
}

.document-row__header {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  margin-bottom: 0.25rem;
}

/* File-type icon: system coral, legible size within the row. */
.document-row__header .bi {
  color: var(--color-primary);
  font-size: 1.25rem;
  line-height: 1.4;
  flex-shrink: 0;
}

.document-row__type {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--text-main);
  flex: 1;
}

.document-row__description {
  font-size: 0.875rem;
  color: var(--text-muted);
  margin: 0 0 0.125rem;
  word-break: break-word;
}

.document-row__date {
  font-size: 0.75rem;
  color: var(--text-muted);
  margin: 0 0 0.5rem;
}

.document-row__actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.5rem;
}

/* Minimum 44px touch area (WCAG 2.5.8). Overrides the 48px min-height of
   .btn-outline-primary/-danger for these more compact row actions. */
.document-row__actions .btn {
  min-height: 44px;
  font-size: 0.875rem;
  padding: 0.375rem 0.875rem;
}

/* --- VIN / NHTSA lookup (spec v2 §3): VIN + inline «Consultar» button --- */
/* The group is flex (declared by the template with Bootstrap utilities); here
   we make sure the button doesn't shrink and keeps its touch height next to the
   48px input. The VIN lives OUTSIDE #bloque-ficha-campos so it isn't lost in the
   htmx swap of the lookup. */
.vin-field-group .btn-outline-secondary {
  --bs-btn-color: var(--text-main);
  --bs-btn-border-color: var(--border-color);
  --bs-btn-hover-bg: var(--bg-surface-alt);
  --bs-btn-hover-border-color: var(--color-primary);
  --bs-btn-hover-color: var(--color-primary);
  --bs-btn-active-bg: var(--bg-surface-alt);
  --bs-btn-active-border-color: var(--color-primary);
  --bs-btn-active-color: var(--color-primary);
  min-height: 48px;
  flex-shrink: 0;
  white-space: nowrap;
  font-weight: 500;
}

.vin-field-group .btn-outline-secondary:focus-visible {
  outline: 3px solid var(--color-primary);
  outline-offset: 2px;
  box-shadow: none;
}

/* «Looking up…» indicator: during the htmx request, htmx sets .htmx-request on
   the button. The «Consultar» text is hidden and spinner + «Consultando…» is
   shown. The button becomes inert (no double firing) and keeps its size. */
.vin-field-group .btn-outline-secondary .lookup-text {
  display: inline;
}

.vin-field-group .btn-outline-secondary .looking-up-text {
  display: none;
  align-items: center;
  gap: 0.375rem;
}

.htmx-request.vin-field-group .btn-outline-secondary .lookup-text,
.vin-field-group .btn-outline-secondary.htmx-request .lookup-text {
  display: none;
}

.htmx-request.vin-field-group .btn-outline-secondary .looking-up-text,
.vin-field-group .btn-outline-secondary.htmx-request .looking-up-text {
  display: inline-flex;
}

.vin-field-group .btn-outline-secondary.htmx-request {
  pointer-events: none;
}

/* --- Multi-source autofill of the technical sheet (ADR-009, UX doc) --- */

/* Expectations note below the VIN field: always visible in edit mode. Makes
   clear that «no data» is normal in ES/EU (not an app error). Left border and
   icon in gray for a sober informational notice, without a color alarm. */
.autofill-note {
  display: flex;
  gap: 0.5rem;
  align-items: flex-start;
  background-color: var(--bg-surface-alt);
  border-left: 3px solid var(--border-color);
  border-radius: 0.375rem;
  padding: 0.625rem 0.75rem;
  margin-top: 0.5rem;
  font-size: 0.875rem;
  color: var(--text-main);
  line-height: 1.5;
}

.autofill-note .bi {
  color: var(--text-muted);
  flex-shrink: 0;
  margin-top: 0.125rem;
}

/* Reusable «loading» state for any button: while the htmx request is in flight,
   htmx adds .htmx-request to the button. The «Consultar» label hides and the
   spinner + «Consultando…» label shows. The button becomes inert (no double
   submit). Not scoped to .vin-field-group so it works for any .btn variant
   (e.g. the .btn-primary «Leer datos»). */
.loading-btn .lookup-text {
  display: inline;
}

.loading-btn .looking-up-text {
  display: none;
  align-items: center;
  gap: 0.375rem;
}

.loading-btn.htmx-request .lookup-text {
  display: none;
}

.loading-btn.htmx-request .looking-up-text {
  display: inline-flex;
}

.loading-btn.htmx-request {
  pointer-events: none;
}

/* Fields the server autofilled (.autofilled-field on the .form-field): subtle
   highlight with a left border and a faint success background. Uses the tokens
   --color-success (#065F46) and --color-success-bg (#D1FAE5) already defined in
   :root; the input text keeps --text-main over the faint background (AA). The
   state is NOT conveyed by color alone: there is a role=alert banner + a11y text. */
.autofilled-field .form-control {
  border-left: 3px solid var(--color-success);
  background-color: var(--color-success-bg);
}

/* States during the htmx lookup (the template sets the input readonly and the
   button disabled via hx-on). Scoped to the VIN group so it doesn't affect other
   readonly inputs in the app. The global visible focus stays intact. */
.vin-field-group .btn-outline-secondary[disabled],
.vin-field-group .btn-outline-secondary:disabled {
  cursor: not-allowed;
  opacity: 0.75;
}

.vin-field-group .form-control[readonly] {
  background-color: var(--bg-surface-alt);
  color: var(--text-muted);
  cursor: not-allowed;
}

/* NHTSA status banner (success / no results / error): the .alert already takes
   the system tokens (section 1). Bottom spacing inside the block. */
#bloque-ficha-campos > .alert {
  margin-bottom: 0.75rem;
}

/* --- Equivalent tires (spec v2 §4): block in the sheet's read mode --- */
.tire-equiv {
  background-color: var(--bg-surface-alt);
  border: 1px solid var(--border-color);
  border-radius: 0.5rem;
  padding: 0.75rem;
  margin-top: 0.375rem;
  margin-bottom: 0.75rem;
}

/* <details> trigger: hides the native marker and uses a custom chevron that
   goes from pointing right (closed) to pointing down (open). The focus-visible
   uses a NEGATIVE offset so it doesn't overflow the container's radius. */
.tire-equiv__summary {
  list-style: none;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 44px;
  padding: 0.375rem 0;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--text-muted);
  cursor: pointer;
  user-select: none;
}

.tire-equiv__summary::-webkit-details-marker {
  display: none;
}

.tire-equiv__summary:hover {
  color: var(--text-main);
}

.tire-equiv__summary:focus-visible {
  outline: 3px solid var(--color-primary);
  outline-offset: -3px;
  border-radius: 4px;
}

.tire-equiv__chevron {
  font-size: 0.875rem;
  flex-shrink: 0;
  transition: transform 0.2s ease;
}

.tire-equiv[open] .tire-equiv__chevron {
  transform: rotate(90deg);
}

.tire-equiv__list {
  list-style: none;
  padding: 0;
  margin: 0 0 0.5rem;
  margin-top: 0.375rem;
}

.tire-equiv__list li {
  font-size: 0.875rem;
  color: var(--text-main);
  padding: 0.125rem 0;
}

.tire-equiv__note {
  font-size: 0.75rem;
  font-style: italic;
  color: var(--text-muted);
  margin: 0;
}

/* --------------------------------------------------------------------------
   28. «Read document» flow (OCR, ADR-010, UX doc «leer-documento-ocr»).
   Hooks from the _seccion_ficha.html and _selector_documento_ocr.html partials.
   Minimal styling, consistent with the rest of the technical sheet form.
   -------------------------------------------------------------------------- */

/* «or» divider (spec section 1): separates the VIN + «Autofill» group from the
   «Read document» button. A line on both sides of the «o» text, discreet, with
   the system tokens. It is aria-hidden (decorative). */
.or-divider {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: 0.75rem 0;
  color: var(--text-muted);
  font-size: 0.875rem;
}

.or-divider::before,
.or-divider::after {
  content: "";
  flex: 1;
  border-top: 1px solid var(--border-color);
}

/* Selector panel container (fieldset + radios + buttons). Fits consistently
   with the form's .form-field (same bottom margin) and resets the <fieldset>
   (no native border/padding) so it inherits the form's rhythm. */
.ocr-document-selector {
  border: 0;
  margin: 0 0 0.75rem;
  padding: 0;
  min-width: 0; /* prevents the <fieldset> from overflowing on mobile */
}

/* The <legend> uses .form-label, but by default a <legend> takes 100% width and
   ignores the label body size; it is normalized to the rhythm of the other labels. */
.ocr-document-selector legend.form-label {
  float: none;
  width: auto;
  margin-bottom: 0.5rem;
}

/* OCR empty state (spec section 3): no eligible documents. Consistent with the
   .empty-state pattern (same padding/centering/hierarchy and 48px muted icon).
   The selectors are grouped to reuse the exact values of the existing pattern;
   only the secondary text color changes: this state lives INSIDE the white card
   (#bloque-ficha-campos), not on --bg-page, so --text-muted does meet AA here
   (unlike .empty-state). */
.empty-state-ocr {
  text-align: center;
  padding: 3rem 1.5rem;
  color: var(--text-muted);
}

.empty-state-ocr .bi {
  font-size: 48px;
  line-height: 1;
}

.empty-state-ocr__title {
  font-size: 1rem;
  font-weight: 700;
  color: var(--text-main);
  margin: 0.75rem 0 0.25rem;
}

.empty-state-ocr__text {
  font-size: 0.875rem;
  margin: 0 0 1.5rem;
}

/* --------------------------------------------------------------------------
   29. Hybrid OCR flow (ADR-011): method radio-cards + AI consent panel.
   Spec: ux-ui hybrid OCR. Rendered INSIDE #bloque-ficha-campos (white surface),
   so --text-muted meets AA here (it sits on white, not on --bg-page). Contrasts
   already validated by ux-ui (AA/AAA). Tokens v3 «Solar White», mobile-first.
   -------------------------------------------------------------------------- */

/* Method choice as a vertical stack of radio-cards inside <fieldset>/<legend>.
   The <legend> is visually hidden (the document selector already names the
   block); the cards themselves are the visible labels. */
.ocr-method-selector {
  border: 0;
  margin: 0 0 0.75rem;
  padding: 0;
  min-width: 0; /* prevents the <fieldset> from overflowing on mobile */
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

/* Radio-card: the whole <label> is the touch target. The radio <input> stays
   visually-hidden (NOT display:none, so it keeps keyboard focus and a11y) and
   the card reflects its checked/focus state via :has(). */
.method-card {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  min-height: 72px; /* comfortable touch area (WCAG 2.5.8) */
  padding: 16px;
  background-color: var(--bg-surface);
  border: 1px solid var(--ocr-card-border);
  border-radius: 8px;
  cursor: pointer;
  /* The 2px selected border must not shift the layout: compensate with an inner
     transparent ring kept at the same thickness in both states. */
  transition: background-color 0.15s, border-color 0.15s;
}

/* Selected state: coral border + tinted background (ux-ui). */
.method-card:has(input[type="radio"]:checked) {
  background-color: var(--ocr-card-selected-bg);
  border: 2px solid var(--color-primary);
  /* Keep the inner box stable when the border grows 1px → 2px. */
  padding: 15px;
}

/* Keyboard focus: visible ring around the whole card (the radio is hidden, so
   the focus indicator must live on the card). WCAG 2.4.7 / 2.4.11. */
.method-card:has(input[type="radio"]:focus-visible) {
  outline: 3px solid var(--color-primary);
  outline-offset: 2px;
}

/* Disabled method (AI option without an API key): muted, non-interactive. */
.method-card--disabled {
  background-color: var(--ocr-card-disabled-bg);
  opacity: 0.6;
  cursor: not-allowed;
}

.method-card--disabled:has(input[type="radio"]:checked) {
  /* A disabled card never adopts the selected styling. */
  background-color: var(--ocr-card-disabled-bg);
  border: 1px solid var(--ocr-card-border);
  padding: 16px;
}

/* Leading icon of each card (decorative; the text carries the meaning). */
.method-card__icon {
  flex-shrink: 0;
  font-size: 1.25rem;
  line-height: 1.4;
  color: var(--color-primary);
}

.method-card--disabled .method-card__icon {
  color: var(--text-muted);
}

.method-card__body {
  flex: 1;
  min-width: 0; /* allows the description to wrap inside the flex row */
}

/* Title row: method name + optional «Recomendado» badge. */
.method-card__title {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  font-size: 1rem;
  font-weight: 600;
  color: var(--text-main);
}

.method-card__description {
  font-size: 0.875rem;
  color: var(--text-muted);
  margin: 0.125rem 0 0;
  line-height: 1.5;
}

/* «Recomendado» badge: coral pill on the recommended (local) method. */
.recommended-tag {
  display: inline-flex;
  align-items: center;
  background-color: var(--color-primary);
  color: var(--color-primary-text);
  font-size: 11px;
  font-weight: 600;
  padding: 2px 8px;
  border-radius: 4px;
  white-space: nowrap;
}

/* «Ya diste tu consentimiento» badge on the AI card: success green + check. */
.method-card__consented {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  margin-top: 0.375rem;
  color: var(--color-success); /* #065F46, AA on white */
  font-size: 0.8125rem;
  font-weight: 600;
}

.method-card__consented .bi {
  font-size: 0.875rem;
}

/* AI consent panel (ADR-011 §6.3 / RGPD): left coral rule, tinted surface. */
.ai-consent-panel {
  background-color: var(--ai-consent-bg);
  border-left: 4px solid var(--color-primary);
  border-radius: 8px;
  padding: 20px 16px;
}

.ai-consent-panel__title {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 18px;
  font-weight: 600;
  color: var(--text-main);
  margin: 0 0 0.5rem;
}

.ai-consent-panel__title .bi {
  color: var(--color-primary);
  flex-shrink: 0;
}

/* Title is focused after the htmx swap (tabindex=-1): no default outline jump. */
.ai-consent-panel__title:focus {
  outline: none;
}

.ai-consent-panel__title:focus-visible {
  outline: 3px solid var(--color-primary);
  outline-offset: 2px;
  border-radius: 4px;
}

/* Always-visible summary. #495057 on #FFF8F7 ≈ 8.6:1 (AAA, verified by ux-ui);
   tokenized in --ai-consent-text to have an AA equivalent in dark mode. */
.ai-consent-panel__summary {
  font-size: 15px;
  line-height: 1.6;
  color: var(--ai-consent-text);
  margin: 0 0 0.75rem;
}

/* Collapsible legal detail («Ver más información»). The native marker is hidden
   and a coral chevron is used, matching the other <details> in the app. */
.ai-consent-panel__detail {
  margin-bottom: 1rem;
}

.ai-consent-panel__detail-summary {
  list-style: none;
  display: flex;
  align-items: center;
  gap: 0.375rem;
  min-height: 44px; /* touch area (WCAG 2.5.8) */
  padding: 0.375rem 0;
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--color-primary);
  cursor: pointer;
  user-select: none;
}

.ai-consent-panel__detail-summary::-webkit-details-marker {
  display: none;
}

.ai-consent-panel__detail-summary:hover {
  color: var(--color-primary-dark);
  text-decoration: underline;
}

.ai-consent-panel__detail-summary:focus-visible {
  outline: 3px solid var(--color-primary);
  outline-offset: 2px;
  border-radius: 4px;
}

.ai-consent-panel__detail-summary .bi {
  transition: transform 0.2s ease;
}

.ai-consent-panel__detail[open] .ai-consent-panel__detail-summary .bi {
  transform: rotate(180deg);
}

/* Legal body inside the detail: kept readable, slightly smaller than the
   summary. #495057 on #FFF8F7 (AAA, verified by ux-ui). */
.ai-consent-panel__detail p {
  font-size: 0.875rem;
  line-height: 1.6;
  color: var(--ai-consent-text);
  margin: 0 0 0.5rem;
}

.ai-consent-panel__detail p:last-child {
  margin-bottom: 0;
}

.ai-consent-panel__detail a {
  color: var(--color-primary);
}

/* Consent checkbox row: comfortable touch area, never pre-checked. */
.ai-consent-panel .form-check {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  min-height: 44px;
  padding-left: 0;
  margin-bottom: 0.5rem;
}

.ai-consent-panel .form-check-input {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  margin: 0.125rem 0 0;
}

.ai-consent-panel .form-check-label {
  font-size: 0.9375rem;
  line-height: 1.5;
  color: var(--text-main);
  cursor: pointer;
}

/* --------------------------------------------------------------------------
   30. Legal pages (privacy policy). Readable long-form prose on the page
   background. The privacy policy is reached from the AI consent link and may
   be opened by an unauthenticated visitor too. Tokens v3, mobile-first.
   -------------------------------------------------------------------------- */
.legal-page {
  /* Slightly wider than the form container: long-form text needs more room,
     but capped so the line length stays comfortable to read. */
  max-width: 640px;
}

.legal-page h2 {
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--text-main);
  margin: 0 0 1rem;
}

.legal-page h3 {
  font-size: 1rem;
  font-weight: 600;
  color: var(--text-main);
  margin: 1.5rem 0 0.375rem;
}

.legal-page p {
  font-size: 0.9375rem;
  line-height: 1.6;
  color: var(--text-main);
  margin: 0 0 0.75rem;
}

/* Draft notice at the top of the legal page: informative amber block (uses the
   warning state tokens; --state-warning #92400E reaches AA on its tinted bg). */
.legal-draft-notice {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  background-color: var(--state-warning-bg);
  border-left: 4px solid var(--state-warning);
  border-radius: var(--radius-btn);
  padding: 0.75rem;
  margin-bottom: 1.5rem;
  font-size: 0.875rem;
  line-height: 1.5;
  color: var(--state-warning);
}

.legal-draft-notice .bi {
  flex-shrink: 0;
  margin-top: 0.125rem;
}

/* ==========================================================================
   31. Desktop UX MVP (ux-ui «improve PC without breaking mobile»).
   Mobile-first is preserved: NOTHING below md (768px) changes here. All the
   desktop rules live behind md/lg/xl breakpoints (Bootstrap 5 scale:
   md>=768, lg>=992, xl>=1200). Tokens v3 «Solar White». WCAG 2.2 AA.
   -------------------------------------------------------------------------- */

/* --- MVP-2: adaptive content container -----------------------------------
   Single wrapper that grows the readable width on wider viewports while
   staying centred. Replaces .narrow-container on the list/profile and
   wraps the detail components. Mobile stays at the narrow 480px width. */
.app-container {
  width: 100%;
  max-width: 480px;
  margin-inline: auto;
  padding-inline: 1rem;
}

@media (min-width: 768px) {
  .app-container {
    max-width: 720px;
  }
}

@media (min-width: 992px) {
  .app-container {
    max-width: 960px;
    padding-inline: 1.5rem;
  }
}

@media (min-width: 1200px) {
  .app-container {
    max-width: 1120px;
    padding-inline: 2rem;
  }
}

/* Detail wrapper: its children (.car-detail-header, .seg-control,
   .info-section-card, .*-row lists…) carry their own lateral margins on
   mobile, so the wrapper stays transparent below lg (no own padding/max-width
   that would double the gutter). From lg it limits and centres the column and
   neutralises the children's lateral margins so they breathe inside it. */
.app-container--detail {
  max-width: none;
  padding-inline: 0;
}

@media (min-width: 992px) {
  .app-container--detail {
    max-width: 960px;
    padding-inline: 1.5rem;
  }

  .app-container--detail > .car-detail-header,
  .app-container--detail > .seg-control,
  .app-container--detail .info-section-card,
  .app-container--detail .types-list-wrapper,
  .app-container--detail .factory-block {
    margin-inline: 0;
  }
}

@media (min-width: 1200px) {
  .app-container--detail {
    max-width: 1120px;
    padding-inline: 2rem;
  }
}

/* --- v4-3: cars grid ------------------------------------------------------
   Single column on <md (no change); 2 columns from md, 3 from lg, 4 from xl
   (Desktop Premium v4). The cards keep their own .car-card margin-bottom
   on mobile; inside the grid the row-gap takes over, so the trailing margin is
   dropped from md upwards. */
@media (min-width: 768px) {
  .car-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 1rem;
  }

  .car-grid .car-card {
    margin-bottom: 0;
  }
}

@media (min-width: 992px) {
  .car-grid {
    grid-template-columns: repeat(3, 1fr);
    gap: 1.25rem;
  }
}

@media (min-width: 1200px) {
  .car-grid {
    grid-template-columns: repeat(4, 1fr);
  }
}

/* --- v4-5: vertical car cards (>=lg) -------------------------------------
   On mobile the card keeps its lateral-thumbnail layout (.car-card__layout
   is a flex row, no change). From lg the layout turns into a vertical column:
   the photo becomes a 16:9 hero on top (rounded top corners) and the body sits
   below it. The chevron/edit affordance is dropped on PC (the whole card is the
   link target via app.js). */
@media (min-width: 992px) {
  .car-grid .car-card {
    padding: 0;
    overflow: hidden;
  }

  .car-grid .car-card__layout {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
  }

  /* Photo as a full-width 16:9 hero with only the top corners rounded. */
  .car-grid .car-card__photo-wrap {
    flex-shrink: 1;
    width: 100%;
  }

  .car-grid .car-card__photo {
    width: 100%;
    height: auto;
    aspect-ratio: 16 / 9;
    border-radius: var(--radius-card) var(--radius-card) 0 0;
  }

  .car-grid .car-card__photo--placeholder {
    font-size: 48px;
  }

  /* Body padding restored inside the now-padless card. */
  .car-grid .car-card__body {
    padding: 1rem;
  }
}

/* --- v4-1: desktop sidebar (>=lg) ----------------------------------------
   Hidden below lg; the mobile bottom bar (.bottom-bar) is the primary
   navigation there. From lg it is a fixed 240px left rail and the bottom bar is
   hidden; the page content is shifted right via body padding. */
.sidebar {
  display: none;
}

@media (min-width: 992px) {
  .sidebar {
    display: flex;
    flex-direction: column;
    position: fixed;
    inset: 0 auto 0 0;
    width: var(--sidebar-width);
    z-index: 1040;
    overflow-y: auto;
    background-color: var(--bg-surface);
    border-right: 1px solid var(--border-color);
  }

  /* Brand header (56px) with bottom border. The coral car icon + «GaragIO». */
  .sidebar__brand {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-height: 56px;
    padding: 0 1.25rem;
    border-bottom: 1px solid var(--border-color);
    color: var(--text-main);
    text-decoration: none;
    font-size: 1.125rem;
    font-weight: 700;
    flex-shrink: 0;
  }

  .sidebar__brand .bi {
    font-size: 1.5rem;
    color: var(--color-primary);
    line-height: 1;
  }

  .sidebar__brand:focus-visible {
    outline: 3px solid var(--color-primary);
    outline-offset: -3px;
  }

  /* Navigation: column of items, takes the remaining height so the user footer
     can be pushed to the bottom. */
  .sidebar__nav {
    display: flex;
    flex-direction: column;
    padding: 0.75rem 0.5rem;
    gap: 0.125rem;
    flex: 1 1 auto;
  }

  .sidebar__item {
    position: relative;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    min-height: 48px;
    padding: 0 1rem;
    border-radius: var(--radius-btn);
    color: var(--text-secundario-en-pagina);
    text-decoration: none;
    font-size: 0.9375rem;
    font-weight: 500;
  }

  .sidebar__item .bi {
    font-size: 1.25rem;
    line-height: 1;
    flex-shrink: 0;
  }

  .sidebar__item:hover {
    background-color: var(--bg-surface-alt);
    color: var(--text-main);
  }

  /* Active item: tinted coral background, coral text 600, 3px coral rule on the
     left edge. The tint uses the accent rgb (--bs-primary-rgb), which changes
     with the theme; in dark mode the opacity is raised so the stripe is visible
     over the slate (7% would be almost invisible). */
  .sidebar__item--active {
    background-color: rgba(var(--bs-primary-rgb), 0.07);
    color: var(--color-primary);
    font-weight: 600;
  }

  [data-theme="dark"] .sidebar__item--active {
    background-color: rgba(var(--bs-primary-rgb), 0.16);
  }

  .sidebar__item--active::before {
    content: "";
    position: absolute;
    inset: 0.375rem auto 0.375rem 0;
    width: 3px;
    border-radius: 0 3px 3px 0;
    background-color: var(--color-primary);
  }

  .sidebar__item:focus-visible {
    outline: 3px solid var(--color-primary);
    outline-offset: 2px;
  }

  /* HU-25 badge inside a sidebar item: pushed to the right edge of the rail.
     The base .nav-badge (red pill) is shared with the bottom bar; here it only
     needs the right alignment. */
  .sidebar__item .nav-badge {
    margin-left: auto;
  }

  /* Quick theme switcher row above the user footer. The trigger keeps its own
     44×44 box; the row just adds the lateral padding/separator of the rail. */
  .sidebar__theme {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 1rem;
    border-top: 1px solid var(--border-color);
    flex-shrink: 0;
  }

  /* User footer: avatar (initials) + name, anchored at the bottom. */
  .sidebar__user {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    min-height: 56px;
    padding: 0 1rem;
    border-top: 1px solid var(--border-color);
    color: var(--text-main);
    text-decoration: none;
    flex-shrink: 0;
  }

  .sidebar__user:hover {
    background-color: var(--bg-surface-alt);
  }

  .sidebar__user:focus-visible {
    outline: 3px solid var(--color-primary);
    outline-offset: -3px;
  }

  .sidebar__avatar {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    flex-shrink: 0;
    border-radius: 50%;
    background-color: var(--color-primary);
    color: var(--color-primary-text);
    font-size: 0.875rem;
    font-weight: 700;
    text-transform: uppercase;
  }

  .sidebar__user-name {
    font-size: 0.875rem;
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  /* The authenticated content is shifted right to clear the fixed sidebar
     (.with-session is set on <body> only when the user is logged in, so the
     unauthenticated login split-screen is NOT shifted). The bottom bar is
     hidden and the page no longer reserves its bottom space. */
  body.with-session {
    padding-left: var(--sidebar-width);
  }

  .bottom-bar {
    display: none;
  }

  main.with-bottom-bar {
    padding-bottom: 1rem;
  }
}

/* --- v4-2: section topbar (>=lg) -----------------------------------------
   60px sticky bar inside the content area (right of the sidebar), rendered per
   screen. Not rendered on <lg (the mobile headers stay). Title on the left,
   actions on the right. */
.section-topbar {
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  min-height: var(--section-topbar-height);
  padding: 0 var(--content-padding-desktop);
  background-color: var(--bg-surface);
  border-bottom: 1px solid var(--border-color);
  position: sticky;
  top: 0;
  z-index: 1030;
}

.section-topbar__title {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  min-width: 0;
}

.section-topbar__title .screen-title {
  margin: 0;
  font-size: 1.25rem;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.section-topbar__actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-shrink: 0;
}

/* The action buttons in the topbar are compact (not the 48px tall block of
   forms): 44px touch area is enough here. */
.section-topbar__actions .btn {
  min-height: 44px;
}

/* --- v4 (FAB): from md there is no bottom bar offset to clear -------------
   On >=md the bottom bar is either hidden (>=lg) or visually irrelevant to the
   FAB anchoring; the offset is dropped and it is pinned at 1.5rem. From lg the
   FAB is hidden entirely (the «+ Añadir coche» action lives in the section
   topbar). */
@media (min-width: 768px) {
  .fab-action {
    bottom: 1.5rem;
  }
}

@media (min-width: 992px) {
  .fab-action {
    display: none;
  }
}

/* --- v4-3/4: detail header two-column layout + button placement (>=lg) ----
   Fixes the two user complaints: the photo no longer gets cropped (4:3 column
   that fills the height) and the action buttons are well placed (the contextual
   button moves into the data column; the fixed bottom action bar is hidden). */
@media (min-width: 992px) {
  .car-detail-header {
    display: grid;
    grid-template-columns: 360px 1fr;
    padding: 0;
    overflow: hidden;
  }

  /* Photo column: the hero spans the full height of the card at 4:3, with only
     the left corners rounded. Reset the mobile negative margins/radius. */
  .car-detail-header__hero {
    width: auto;
    margin: 0;
    height: 100%;
    border-radius: var(--radius-card) 0 0 var(--radius-card);
  }

  .car-detail-header__hero .car-detail-header__photo {
    aspect-ratio: 4 / 3;
    height: 100%;
    border-radius: var(--radius-card) 0 0 var(--radius-card);
  }

  /* Data column: padding 2rem, vertical flex, action button pinned to the foot. */
  .car-detail-header__data-column {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    padding: 2rem;
  }

  /* The contextual primary action at the foot of the data column. */
  .car-detail-header__action {
    margin-top: 1.5rem;
  }

  .car-detail-header__action .btn {
    width: auto;
    min-width: 240px;
  }

  /* Buttons fix: the fixed bottom action bar is hidden on PC and the <main> no
     longer reserves its 80px hole. */
  .context-action-bar {
    display: none;
  }

  main.with-action-bar {
    padding-bottom: 1rem;
  }
}

/* --- v4-6: login split-screen (>=lg) -------------------------------------
   On <lg the wrapper is a no-op (single column) and the existing login is
   intact. From lg it becomes two columns: a coral brand panel + the login card
   without its own shadow/border. */
@media (min-width: 992px) {
  .login-split {
    display: grid;
    grid-template-columns: 1fr 1fr;
    min-height: 100vh;
  }

  /* Brand panel: coral background, white text. Contrast white on coral
     (#FFFFFF on #C13209) ≈ 5.5:1, verified AA. */
  .login-split__brand {
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 2rem;
    background-color: var(--color-primary);
    color: var(--color-primary-text);
    text-align: center;
  }

  .login-split__logo {
    font-size: 80px;
    line-height: 1;
    color: var(--color-primary-text);
  }

  .login-split__title {
    font-size: 2rem;
    font-weight: 700;
  }

  .login-split__subtitle {
    font-size: 1.125rem;
    /* Token-driven so it stays AA in both themes (HU-50 dark mode). In light,
       --color-primary-text=#FFFFFF on coral #C13209 = 5.6:1; in dark, #1A120D
       on lightened coral #FF6B3D = 6.5:1. The old rgba(255,255,255,0.85) fell to
       2.4:1 over the dark theme's light coral. */
    color: var(--color-primary-text);
    max-width: 24ch;
  }

  /* Right panel: the login card loses its shadow/border (the split is the
     visual container now). */
  .login-split__panel {
    min-height: 100vh;
  }

  .login-split__panel .login-card {
    box-shadow: none;
    border: none;
  }
}

/* --- v4-7: form / profile widths (>=lg) ----------------------------------
   On <lg these keep the narrow mobile width (no change). The car form widens to
   680px and the profile narrows to ~520px, both centred. */
@media (min-width: 992px) {
  .narrow-container--form-width {
    max-width: 680px;
  }

  .app-container--profile {
    max-width: 520px;
  }
}

/* --- v4 (login subtitle): mobile keeps the muted small subtitle ----------
   (no change below lg). */

/* --- MVP-5: enriched hover/focus (pointer devices only) ------------------
   The lift (translateY) lives inside @media (hover:hover) so touch devices
   never get a stuck hover state; it is also disabled by reduced-motion below. */
.car-card {
  transition: box-shadow 0.18s ease, transform 0.18s ease;
}

@media (hover: hover) {
  .car-card:hover {
    box-shadow: var(--shadow-card-hover);
    transform: translateY(-1px);
  }
}

/* Subtle transitions on the interactive rows/links (existing selectors only). */
.maintenance-row,
.reading-row,
.plan-row,
.document-row,
.back-link,
.edit-car-button {
  transition: background-color 0.15s ease, color 0.15s ease;
}

/* --------------------------------------------------------------------------
   HU-34 — Public self-registration (P-20)
   -------------------------------------------------------------------------- */

/* Honeypot trap (ADR-014 §6.1): rendered in the DOM (bots fill it) but kept
   off-screen for humans. NOT display:none / visibility:hidden / type=hidden,
   because bots skip those; off-screen positioning is the standard honeypot
   technique. The field also carries aria-hidden + tabindex=-1 so screen readers
   ignore it and the keyboard cannot focus it. */
.honeypot-field {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* hCaptcha widget wrapper (ADR-014 §4): the provider's iframe is ~300px wide.
   overflow-x: hidden stops it from forcing horizontal scroll on the 360px
   layout; the fieldset/legend give the widget an accessible name. */
.hcaptcha-field {
  overflow-x: hidden;
  /* The widget injects an <iframe>/<div>; cap its box to the card width. */
  max-width: 100%;
}

.hcaptcha-field .h-captcha {
  /* Center the iframe within the card and avoid a flush-left look on mobile. */
  display: flex;
  justify-content: center;
}

/* --------------------------------------------------------------------------
   HU-33 / P-19b §8 — Notifications section of the profile (Telegram).
   Mobile-first; reuses existing tokens. Touch targets >= 44px and a visible
   focus ring (3px coral) on every interactive element.
   -------------------------------------------------------------------------- */

/* Subsection subtitle: uppercase muted label that separates «Channels» from
   «Telegram». The <hr> between subsections already draws the divider; this is
   just the heading style (it is a real <h2> for the document outline). */
.notif-section__titulo {
  margin: 0 0 0.75rem;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-muted);
}

/* Each toggle row: the Bootstrap form-switch plus its description note. */
.notif-toggle {
  /* Comfortable vertical rhythm; the switch itself is >=44px tall via padding. */
  padding-block: 0.5rem;
  margin-bottom: 0.25rem;
  min-height: 44px;
}

.notif-toggle .form-check-input {
  /* Larger switch for an easy touch target (Bootstrap default is ~2em wide). */
  width: 2.5em;
  height: 1.4em;
  margin-top: 0.1em;
  cursor: pointer;
}

.notif-toggle .form-check-input:focus-visible {
  outline: 3px solid var(--color-primary);
  outline-offset: 2px;
}

.notif-toggle .form-check-label {
  font-weight: 600;
  cursor: pointer;
}

/* Description / «link your account to enable this» note under a toggle. */
.notif-toggle__nota {
  margin: 0.1rem 0 0;
  font-size: 0.875rem;
  color: var(--text-muted);
}

/* Telegram state line (holds the status badge). */
.notif-telegram__estado {
  margin: 0 0 0.75rem;
}

/* «Pending» hint: explains that the user must refresh after sending the code. */
.notif-telegram__espera-hint {
  margin: 0 0 0.75rem;
  font-size: 0.875rem;
  color: var(--text-muted);
}

/* --- Link-code modal (P-19b §2) --- */
.vincular-codigo__pasos {
  margin: 0 0 1rem;
  padding-left: 1.25rem;
}

.vincular-codigo__pasos li {
  margin-bottom: 0.25rem;
}

.vincular-codigo__pasos a {
  margin-left: 0.25rem;
}

/* The code block: large monospace value + Copy button, full-width and centred
   so it reads well at 360px. */
.vincular-codigo {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  padding: 1rem;
  background-color: var(--bg-surface-alt);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-btn);
}

.vincular-codigo__valor {
  /* Big, monospaced, fully selectable by hand (in addition to the Copy button). */
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 2rem;
  font-weight: 700;
  letter-spacing: 0.25em;
  color: var(--text-main);
  user-select: all;
  /* Keep the wide letter-spacing from pushing the last digit off-centre. */
  padding-left: 0.25em;
}

.vincular-codigo__copiar {
  /* Touch target >= 44px. */
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}

.vincular-codigo__copiar:focus-visible {
  outline: 3px solid var(--color-primary);
  outline-offset: 2px;
}

/* Expiry note under the code. */
.notif-telegram__caducidad {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin: 1rem 0 0;
  font-size: 0.875rem;
  color: var(--text-muted);
}

/* --------------------------------------------------------------------------
   HU-56 / P-19d (ADR-021) — Calendar subscription (iCal): read-only URL field
   + Copy button, and collapsible subscription instructions.
   Reuses the system tokens (Solar White v3 + token-based dark theme), so AA
   contrast and dark mode resolve on their own.
   -------------------------------------------------------------------------- */

/* URL + Copy row: on a single line at >=480px, stacked on narrow mobile. */
.calendar-feed-url {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  gap: 0.5rem;
}

.calendar-feed-url .form-control {
  /* The URL is long: the field takes the remaining space and never drops below 12rem. */
  flex: 1 1 12rem;
  min-width: 0;
  /* Monospaced so the secret link reads without ambiguity. */
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.875rem;
}

/* The Copy button: >=44px tall touch area and a comfortable width on mobile. */
.calendar-feed-url__copiar {
  flex: 0 0 auto;
  min-height: 48px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  white-space: nowrap;
}

.calendar-feed-url__copiar:focus-visible {
  outline: 3px solid var(--color-primary);
  outline-offset: 2px;
}

/* At 360px the button becomes full-width below the field (large touch target). */
@media (max-width: 479.98px) {
  .calendar-feed-url__copiar {
    flex-basis: 100%;
  }
}

/* Collapsible instructions: native <details> styled as a soft card. */
.calendar-feed-help {
  border: 1px solid var(--border-color);
  border-radius: var(--radius-btn);
  background-color: var(--bg-surface-alt);
  overflow: hidden;
}

.calendar-feed-help__summary {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 48px;
  padding: 0.75rem 1rem;
  font-weight: 600;
  color: var(--text-main);
  cursor: pointer;
  /* Removes the native triangle: we use the Bootstrap icon on the left. */
  list-style: none;
}

.calendar-feed-help__summary::-webkit-details-marker {
  display: none;
}

.calendar-feed-help__summary .bi {
  color: var(--color-primary);
}

.calendar-feed-help__summary:focus-visible {
  outline: 3px solid var(--color-primary);
  outline-offset: -3px;
}

.calendar-feed-help__body {
  padding: 0 1rem 1rem;
}

/* Definition list of the apps: name (bold) + steps. */
.calendar-feed-help__list dt {
  font-weight: 700;
  color: var(--text-main);
  margin-top: 0.5rem;
}

.calendar-feed-help__list dd {
  margin: 0.1rem 0 0;
  font-size: 0.875rem;
  /* --text-muted (#6B7280) passes AA only on a light surface; here the
     background is --bg-surface-alt, so we use the main body color. */
  color: var(--text-main);
}

/* --------------------------------------------------------------------------
   HU-32 (UX spec §6) — Share a car: accordion, collaborator list and a
   «Shared by X» badge. Reuses the system tokens (Solar White v3).
   -------------------------------------------------------------------------- */

/* «Compartir este coche» accordion: white card between the header and the rail. */
.sharing-accordion {
  display: block;
  background-color: var(--bg-surface);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  margin-bottom: 1rem;
  overflow: hidden;
}

/* Native trigger (<button>): 48px tall > 44px touch area. */
.sharing-accordion__toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  width: 100%;
  min-height: 48px;
  padding: 0.75rem 1rem;
  background: transparent;
  border: 0;
  color: var(--text-main);
  font-size: 1rem;
  font-weight: 600;
  text-align: left;
  cursor: pointer;
}

.sharing-accordion__title {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
}

.sharing-accordion__title .bi {
  color: var(--color-primary);
}

/* Chevron on the right: rotates 180° when the panel is open. */
.sharing-accordion__icon-right {
  flex-shrink: 0;
  color: var(--text-muted);
  transition: transform 0.2s ease;
}

.sharing-accordion__toggle[aria-expanded="true"] .sharing-accordion__icon-right {
  transform: rotate(180deg);
}

.sharing-accordion__toggle:focus-visible {
  outline: 3px solid var(--color-primary);
  outline-offset: -3px;
}

/* Accordion body: visible only when the panel does NOT have [hidden]. */
.sharing-accordion__body {
  padding: 0 1rem 1rem;
  border-top: 1px solid var(--border-color);
  padding-top: 1rem;
}

/* Section subtitle (uppercase, muted). --text-muted on white = AA. */
.sharing-section__subtitle {
  margin: 0 0 0.25rem;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.sharing-section__subtitle--list {
  margin-top: 1.5rem;
}

.sharing-section__help {
  margin: 0 0 0.75rem;
  font-size: 0.875rem;
  color: var(--text-muted);
}

/* List of collaborators with access. */
.sharing-collab-list {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.sharing-collab-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.75rem;
  background-color: var(--bg-surface-alt);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-btn);
}

.sharing-collab-row__info {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  min-width: 0; /* allows the long email to truncate */
}

.sharing-collab-row__avatar {
  flex-shrink: 0;
  font-size: 1.75rem;
  color: var(--text-muted);
}

.sharing-collab-row__name {
  margin: 0;
  font-weight: 600;
  color: var(--text-main);
}

.sharing-collab-row__email {
  margin: 0;
  font-size: 0.875rem;
  color: var(--text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sharing-collab-row__date {
  margin: 0.125rem 0 0;
  font-size: 0.75rem;
  color: var(--text-muted);
}

/* «Revoke» button: outline danger, minimum touch area. */
.sharing-collab-row__revoke {
  flex-shrink: 0;
  min-height: 44px;
}

/* Empty state of the collaborator list. */
.sharing-collab-list__empty {
  margin: 0;
  font-size: 0.875rem;
  color: var(--text-muted);
}

/* «Shared by X» pill: informational (--state-info on --state-info-bg = 7.2:1,
   passes AA). Never color alone: icon + text + aria-label. */
.badge-compartido {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.25rem 0.625rem;
  border-radius: 9999px;
  background-color: var(--state-info-bg);
  color: var(--state-info);
  font-size: 0.75rem;
  font-weight: 600;
  white-space: nowrap;
}

/* Containers for the pill in the list card and in the detail header. */
.car-card__shared-by {
  margin: 0.5rem 0 0;
}

.car-detail-header__shared-by {
  margin: 0.5rem 0 0;
}

/* ==========================================================================
   P-27 — «Mis vencimientos» panel (HU-44/HU-45, UX §3)
   --------------------------------------------------------------------------
   A SINGLE responsive DOM (no duplicated htmx IDs): each car is a
   .tarjeta-vencimientos whose three cells (.fila-vencimiento, id
   "celda-{car}-{type}") are the fragments htmx swaps by outerHTML. The returned
   fragment is ALWAYS a <div class="fila-vencimiento"> (fixed by the backend),
   which is why the desktop tabular presentation is solved with CSS Grid over
   those divs, NOT with <table>/<td> (swapping a <div> inside a table would break
   the structure). The accessible semantics come from <section aria-label> and
   the role="group" aria-label on each cell.
   Mobile-first: stacked cards on mobile; horizontal grid at >=lg.
   ========================================================================== */
.vencimientos-panel__intro {
  font-size: 0.875rem;
  color: var(--text-secundario-en-pagina);
  margin: 0 0 1rem;
}

.tarjeta-vencimientos {
  background-color: var(--bg-surface);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  margin-bottom: 1rem;
  overflow: hidden;
}

.tarjeta-vencimientos__cabecera {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.75rem 1rem;
  border-bottom: 1px solid var(--border-color);
}

.tarjeta-vencimientos__nombre {
  font-size: 1rem;
  font-weight: 700;
  color: var(--text-main);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tarjeta-vencimientos__meta {
  font-size: 0.875rem;
  color: var(--text-muted);   /* on --bg-surface (white): AA */
  flex-shrink: 0;
}

/* The detail link is pushed to the far right of the header. */
.tarjeta-vencimientos__enlace-detalle {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  margin-left: auto;
  color: var(--text-muted);
  text-decoration: none;
  flex-shrink: 0;
}

.tarjeta-vencimientos__enlace-detalle:hover {
  color: var(--color-primary);
}

.tarjeta-vencimientos__enlace-detalle:focus-visible {
  outline: 3px solid var(--color-primary);
  outline-offset: -3px;
  border-radius: var(--radius-btn);
}

/* Due-date cell: on mobile it is a stacked row (type on top with the toggle,
   value below). It is the container that htmx swaps. */
.fila-vencimiento {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  padding: 0.75rem 1rem;
  border-bottom: 1px solid var(--border-color);
  cursor: pointer;
  transition: background-color 0.1s ease;
}

.fila-vencimiento:last-child {
  border-bottom: none;
}

.fila-vencimiento:hover {
  background-color: var(--bg-surface-alt);
}

.fila-vencimiento:focus-visible {
  outline: 3px solid var(--color-primary);
  outline-offset: -3px;
}

.fila-vencimiento__cabecera {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  min-height: 44px;
}

.fila-vencimiento__tipo {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--text-main);
}

.fila-vencimiento__dato {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.fila-vencimiento__fecha {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--text-main);
}

.fila-vencimiento__vacia {
  font-size: 0.875rem;
  color: var(--text-muted);   /* on --bg-surface: AA */
}

.fila-vencimiento__dias {
  font-size: 0.75rem;
  /* Micro text on the card's white surface. */
  color: var(--text-secundario-en-pagina);
}

/* While editing the row is no longer clickable and lifts slightly. */
.fila-vencimiento--editando {
  cursor: default;
  background-color: var(--bg-surface-alt);
}

.fila-vencimiento--editando:hover {
  background-color: var(--bg-surface-alt);
}

/* htmx marks the in-flight row: it dims and blocks further clicks (prevents a
   double toggle submission or reopening the edit). */
.fila-vencimiento.htmx-request {
  opacity: 0.5;
  pointer-events: none;
}

/* 🔔/🔕 toggle: 44×44 touch target, round, no background. */
.btn-conmutador-aviso {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  min-width: 44px;
  padding: 0;
  border: none;
  background: none;
  cursor: pointer;
  border-radius: 50%;
  color: var(--color-primary);
  font-size: 1.125rem;
  line-height: 1;
  transition: background-color 0.1s ease;
  flex-shrink: 0;
}

.btn-conmutador-aviso:hover {
  background-color: var(--bg-surface-alt);
}

.btn-conmutador-aviso:focus-visible {
  outline: 3px solid var(--color-primary);
  outline-offset: 2px;
}

.btn-conmutador-aviso--silenciado {
  color: var(--text-muted);   /* on --bg-surface: AA */
}

/* «+ Añadir fecha»: action link with a 44px touch target. */
.btn-anadir-fecha {
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--color-primary);
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
}

.btn-anadir-fecha:hover {
  text-decoration: underline;
}

.btn-anadir-fecha:focus-visible {
  outline: 3px solid var(--color-primary);
  outline-offset: 2px;
  border-radius: var(--radius-btn);
}

/* Inline editing: the input takes the full width and the actions align below. */
.edicion-inline {
  padding-top: 0.25rem;
}

.edicion-inline .form-control {
  margin-bottom: 0.5rem;
}

.edicion-inline__acciones {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
  align-items: center;
}

.edicion-inline__acciones .btn {
  min-height: 44px;
}

/* --- Desktop (>=lg): tabular presentation --------------------------------
   The card header (car + plate + link) spans one strip and the three cells lay
   out in a 3-equal-column grid. Each cell keeps its htmx id and its
   role="group"; only the layout changes. */
@media (min-width: 992px) {
  .tarjeta-vencimientos__cabecera {
    /* The plate is separated from the name by a decorative middle dot. */
    padding: 1rem 1.25rem;
  }

  .tarjeta-vencimientos__cuerpo {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
  }

  .fila-vencimiento {
    border-bottom: none;
    border-right: 1px solid var(--border-color);
    padding: 1rem 1.25rem;
    /* The date/badge/days sit below the type, left-aligned. */
    justify-content: flex-start;
  }

  .fila-vencimiento:last-child {
    border-right: none;
  }

  /* The top strip of each column (type + toggle) stays at the same height even
     if one cell is empty and another has a badge. */
  .fila-vencimiento__cabecera {
    min-height: 44px;
  }

  .fila-vencimiento__dato {
    margin-top: 0.25rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }

  .car-card:hover {
    transform: none !important;
  }
}

/* --------------------------------------------------------------------------
   ADR-019 — Usage-based predictive reminders (HU-47 / HU-49)
   Visual treatment of the ESTIMATE: it must always read as approximate, never
   as a confirmed due date. Two surfaces:
     1) Secondary line in the km-based plan row (Plans tab, P-06).
     2) «Estimación de uso» section in the plan detail/edit (P-10).
   Tokens v3 «Solar White». The «Est.» pill reuses the «Upcoming» state tokens
   (amber warning, #92400E on #FEF3C7 → 6.7:1 AA).
   -------------------------------------------------------------------------- */

/* 1) Estimate line inside the plan row (sits on --bg-surface, white:
   --text-muted #6B7280 at 0.875rem meets AA 4.6:1). Discreet, below the rule
   and the certain due date, so it does not compete with them. */
.plan-row__estimate {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.375rem;
  font-size: 0.875rem;
  color: var(--text-muted);
  margin: 0.25rem 0 0;
}

/* «Est.» pill: an unambiguous estimate marker. Same tokens as the «Upcoming»
   badge for consistency with the state it triggers (amber warning). */
.plan-row__estimate-tag {
  flex: 0 0 auto;
  font-size: 0.6875rem;
  font-weight: 700;
  line-height: 1;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 0.1875rem 0.4375rem;
  border-radius: 999px;
  background-color: var(--state-warning-bg);
  color: var(--state-warning);
}

.plan-row__estimate-text {
  min-width: 0;
}

/* The pace (~X km/month) in an even fainter tone and micro size: supporting data. */
.plan-row__estimate-pace {
  white-space: nowrap;
}

/* No-data state (HU-49): same discreet tone, no pill (nothing to estimate),
   with an actionable link to record a reading. */
.plan-row__estimate--none {
  align-items: center;
}

.plan-row__estimate-link {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  min-height: 44px;          /* touch target WCAG 2.5.8 */
  padding: 0 0.25rem;
  font-weight: 600;
  color: var(--color-primary);   /* #C13209 on white → 5.5:1 AA */
  text-decoration: none;
}

.plan-row__estimate-link:hover {
  color: var(--color-primary-dark);
  text-decoration: underline;
}

.plan-row__estimate-link:focus-visible {
  outline: 3px solid var(--color-primary);
  outline-offset: 2px;
  border-radius: 6px;
}

/* 2) «Estimación de uso» section (P-10): its own surface card so it stands out
   from the page background without competing with the danger zone. */
.usage-estimate {
  background-color: var(--bg-surface);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  padding: 1rem 1.25rem;
  margin-top: 2rem;
}

.usage-estimate__title {
  display: flex;
  align-items: center;
  gap: 0.4375rem;
  font-size: 1rem;
  font-weight: 700;
  color: var(--text-main);
  margin: 0 0 0.75rem;
}

.usage-estimate__title .bi {
  color: var(--color-primary);
  font-size: 1.125rem;
}

/* «Est.» pill in the section header: same signal as in the row. */
.usage-estimate__tag {
  margin-left: auto;
  font-size: 0.6875rem;
  font-weight: 700;
  line-height: 1;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 0.1875rem 0.4375rem;
  border-radius: 999px;
  background-color: var(--state-warning-bg);
  color: var(--state-warning);
}

/* List of key facts: label + value in pairs. A single column on mobile; the
   value at 700 (the design system's data hierarchy). */
.usage-estimate__facts {
  margin: 0 0 0.75rem;
}

.usage-estimate__fact {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.75rem;
  padding: 0.375rem 0;
  border-bottom: 1px solid var(--border-color);
}

.usage-estimate__fact:last-child {
  border-bottom: none;
}

.usage-estimate__label {
  font-size: 0.875rem;
  color: var(--text-muted);   /* on --bg-surface (white): 4.6:1 AA */
}

.usage-estimate__value {
  font-size: 0.9375rem;
  font-weight: 700;
  color: var(--text-main);
  margin: 0;
  text-align: right;
}

/* Uncertainty note: sits on --bg-surface, so --text-muted works. */
.usage-estimate__note {
  font-size: 0.8125rem;
  color: var(--text-muted);
  margin: 0;
}

/* Already-overdue case: «Overdue» state tone but subtle (text, no background). */
.usage-estimate__overdue {
  font-size: 0.875rem;
  color: var(--state-danger);   /* #B91C1C on white → 6:1 AA */
  margin: 0;
}

/* No-data case (HU-49): honest message + button to record a reading. */
.usage-estimate__none {
  font-size: 0.875rem;
  color: var(--text-main);
  margin: 0 0 1rem;
}

.usage-estimate__action {
  width: 100%;
  min-height: 48px;
}

@media (min-width: 992px) {
  .usage-estimate__action {
    width: auto;
  }
}

/* ==========================================================================
   DARK — component adjustments that CANNOT be solved with tokens alone.
   The vast majority of the dark theme is achieved by redefining the custom
   properties (the «1-OSCURO» block). What's left here are the few cases where a
   rule uses a fixed opacity/RGB that is perceived differently in dark mode. The
   selector is duplicated for data-theme="dark" (always) and for
   data-theme="auto" under prefers-color-scheme:dark (follows the system), just
   like the token map.
   ========================================================================== */

/* Sidebar: the active stripe raises its opacity to be visible over slate (the
   light version is rgba(.,0.07), almost invisible in dark mode). The base
   selector lives inside @media (min-width:992px), so it also does here to
   preserve cascade specificity. */
@media (min-width: 992px) {
  :root[data-theme="auto"] .sidebar__item--active {
    /* In auto, only if the SYSTEM requests dark (see the @media below). The
       default light value (0.07) comes from the base rule. */
    background-color: rgba(var(--bs-primary-rgb), 0.07);
  }
}

@media (min-width: 992px) and (prefers-color-scheme: dark) {
  :root[data-theme="auto"] .sidebar__item--active {
    background-color: rgba(var(--bs-primary-rgb), 0.16);
  }
}

/* Quick theme switcher (a 3-option segmented control in the profile + a
   shortcut in the sidebar/header). Reuses the language selector and segmented
   control language; system tokens, so it already changes with the theme. It
   only needs its own layout. Mobile-first, WCAG 2.2 AA. */
.theme-quick {
  position: relative;
  flex-shrink: 0;
}

/* Quick-menu trigger: same size/shape as .lang-trigger (44×44). */
.theme-trigger {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  padding: 0 8px;
  background-color: var(--bg-surface-alt);
  border: 1.5px solid var(--border-color);
  border-radius: 8px;
  color: var(--text-main);
  cursor: pointer;
}

.theme-trigger .bi {
  font-size: 1.125rem;
  line-height: 1;
}

.theme-trigger:hover {
  background-color: var(--border-color);
}

.theme-trigger:focus-visible {
  outline: 3px solid var(--color-primary);
  outline-offset: 2px;
}

.theme-trigger[aria-expanded="true"] {
  background-color: var(--color-primary);
  border-color: var(--color-primary);
  color: var(--color-primary-text);
}

/* Bottom sheet of the quick switcher: clones the lang-offcanvas. */
.theme-offcanvas {
  height: auto;
  max-height: 70vh;
  border-radius: 16px 16px 0 0;
  border-top: 1px solid var(--border-color);
}

.theme-offcanvas .offcanvas-header {
  border-bottom: 1px solid var(--border-color);
  padding: 1rem 1rem 1rem 1.25rem;
}

.theme-offcanvas .offcanvas-title {
  font-size: 1rem;
  font-weight: 600;
  color: var(--text-main);
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0;
}

.theme-offcanvas__body {
  padding: 0.5rem 0;
  overflow-y: auto;
}

.theme-offcanvas__list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.theme-offcanvas__form {
  margin: 0;
}

.theme-offcanvas__option {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  width: 100%;
  min-height: 56px;
  padding: 0 1.25rem;
  background: transparent;
  border: none;
  text-align: left;
  cursor: pointer;
  color: var(--text-main);
  font-size: 1rem;
  font-weight: 400;
}

.theme-offcanvas__option:hover {
  background-color: var(--bg-surface-alt);
}

.theme-offcanvas__option:focus-visible {
  outline: 3px solid var(--color-primary);
  outline-offset: -3px;
  z-index: 1;
  position: relative;
}

.theme-offcanvas__option--active {
  color: var(--color-primary);
  font-weight: 600;
}

/* Leading icon of each option (sun/moon/auto): coral when active. */
.theme-offcanvas__icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  flex-shrink: 0;
  font-size: 1.125rem;
  color: var(--text-muted);
}

.theme-offcanvas__option--active .theme-offcanvas__icon {
  color: var(--color-primary);
}

.theme-offcanvas__name {
  flex: 1;
}

/* Check of the active option, at the end of the row (like the language selector). */
.theme-offcanvas__check {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  font-size: 1rem;
  color: var(--color-primary);
}

/* --- PROFILE switcher: 3 segmented buttons (Light/Dark/Auto) ---
   A .seg-control variant (same tokens) used INSIDE the preferences form. Each
   option is a <label> wrapping a .visually-hidden radio (native keyboard
   operability), the same pattern as .seg-tab--radio. */
.theme-segmented {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  background-color: var(--bg-surface);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  overflow: hidden;
  margin: 0;
}

.theme-segmented__option {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.25rem;
  min-height: 64px;            /* generous touch target (WCAG 2.5.8) */
  padding: 0.5rem 0.25rem;
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--text-muted);
  cursor: pointer;
  text-align: center;
  border-right: 1px solid var(--border-color);
}

.theme-segmented__option:last-child {
  border-right: none;
}

.theme-segmented__option .bi {
  font-size: 1.25rem;
  line-height: 1;
}

.theme-segmented__option:hover {
  background-color: var(--bg-surface-alt);
  color: var(--text-main);
}

/* Selected state: coral fill + text on coral (like .seg-tab--active). */
.theme-segmented__option--active {
  background-color: var(--color-primary);
  color: var(--color-primary-text);
  font-weight: 600;
}

.theme-segmented__option--active:hover {
  background-color: var(--color-primary-dark);
  color: var(--color-primary-text);
}

/* Visible focus on the option when its inner radio receives it (WCAG 2.4.7). */
.theme-segmented__option:has(input:focus-visible) {
  outline: 3px solid var(--color-primary);
  outline-offset: -3px;
  z-index: 1;
}

.theme-segmented__option:focus-within {
  outline: 3px solid var(--color-primary);
  outline-offset: -3px;
  z-index: 1;
}

/* --------------------------------------------------------------------------
   38. P-08 — Maintenance attachments (HU-51..HU-55, ADR-020)
   Functional backend spec; here the styling, thumbnails, modal and i18n.
   Design system v3 «Solar White» + «Midnight Garage» dark theme: EVERYTHING via
   tokens, so light and dark work without duplicated rules. AA contrast; touch
   targets ≥ 44px (WCAG 2.5.8).
   -------------------------------------------------------------------------- */

/* --- Upload control: discreet box with the limits microcopy --------------- */
/* Lives inside the create/edit form (.attachments-upload is a
   <fieldset class="form-section">; the fieldset reset is already given by
   .form-section). The box visually groups the help + type + files. */
.attachments-upload__box {
  background-color: var(--bg-surface-alt);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-card);
  padding: 1rem;
}

/* Limits microcopy: sits on --bg-surface-alt (light #F8F9FB / dark #222C38).
   --text-muted passes AA on both surface-alt surfaces. */
.attachments-upload__hint {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  font-size: 0.875rem;
  color: var(--text-muted);
  margin: 0 0 0.75rem;
}

.attachments-upload__hint .bi {
  color: var(--color-primary);
  font-size: 1rem;
  line-height: 1.45;
  flex-shrink: 0;
}

/* --- List of existing attachments (in edit mode) -------------------------- */
.attachment-list {
  border-top: 1px solid var(--border-color);
}

/* Each attachment: thumbnail/icon + body (name, type, date) + actions.
   Mobile-first: the actions wrap to a second line on the right. */
.attachment-item {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem;
  padding: 0.75rem 0;
  border-bottom: 1px solid var(--border-color);
}

/* Thumbnail (images) or icon (PDF/other): a 56px square, a link that opens the
   protected served file in a new tab. It is a 56×56 touch target. */
.attachment-item__media {
  flex-shrink: 0;
  display: block;
  width: 56px;
  height: 56px;
  border-radius: var(--radius-btn);
  overflow: hidden;
  text-decoration: none;
}

.attachment-item__media:focus-visible {
  outline: 3px solid var(--color-primary);
  outline-offset: 2px;
}

.attachment-item__thumb {
  width: 56px;
  height: 56px;
  object-fit: cover;
  object-position: center;
  display: block;
  background-color: var(--bg-surface-alt);
  /* Per-theme inner frame (dark hairline in light mode, light in dark mode):
     lifts the thumbnail off the card background without changing its size. */
  box-shadow: var(--shadow-photo-inset);
}

/* File icon (PDF / other) within the same 56px square. */
.attachment-item__icon {
  width: 56px;
  height: 56px;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: var(--bg-surface-alt);
  color: var(--text-muted);
  box-shadow: var(--shadow-photo-inset);
}

.attachment-item__icon .bi {
  font-size: 28px;
  line-height: 1;
}

/* The PDF stands out with the system coral (same as the Documents tab icons).
   In dark mode the coral lightens on its own (token). */
.attachment-item__icon--pdf {
  color: var(--color-primary);
}

/* Body: name (can wrap) + meta (type · date). min-width:0 allows the long name
   to be clipped inside the flex. */
.attachment-item__body {
  flex: 1 1 12rem;
  min-width: 0;
}

.attachment-item__name {
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--text-main);
  word-break: break-word;
}

/* The name is also a link to the protected served file (besides the thumbnail). */
.attachment-item__name-link {
  color: inherit;
  text-decoration: none;
}

.attachment-item__name-link:hover {
  color: var(--color-primary);
  text-decoration: underline;
}

.attachment-item__name-link:focus-visible {
  outline: 3px solid var(--color-primary);
  outline-offset: 2px;
  border-radius: 2px;
}

.attachment-item__meta {
  font-size: 0.8125rem;
  color: var(--text-muted);
  margin-top: 0.125rem;
}

.attachment-item__sep {
  margin: 0 0.25rem;
}

/* «View» / «Delete» actions: on the right, 44px touch target. On narrow mobile
   the row wraps and the actions take the available width. */
.attachment-item__actions {
  display: flex;
  gap: 0.5rem;
  margin-left: auto;
  flex-shrink: 0;
}

.attachment-item__actions .btn {
  min-height: 44px;
  font-size: 0.875rem;
  padding: 0.375rem 0.75rem;
}

.attachment-item__actions .btn .bi {
  font-size: 1rem;
}

/* Discreet empty state: clip + text on --bg-page (blue-gray AA). */
.attachments-empty {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.875rem;
  color: var(--text-secundario-en-pagina);
  margin: 0;
}

.attachments-empty .bi {
  font-size: 1rem;
}

/* --- «Has attachments» indicator on the history rows (HU-55) -------------- */
/* Discreet pill: clip + number. Sits inside .maintenance-row (white surface /
   slate); --text-muted passes AA on both. The number is decorative for AT (the
   accessible name is given by the aria-label of .attachment-chip). */
.history-row__attachments {
  margin-top: 0.25rem;
}

.attachment-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--text-muted);
}

.attachment-chip .bi {
  font-size: 0.875rem;
  line-height: 1;
}
