/* ==========================================================================
   RODALICO site-wide visual system
   Contract: docs/P2_SITEWIDE_VISUAL_SHELL_v0.1.md
   --------------------------------------------------------------------------
   Every shared component below already reads these tokens, and font-family is
   declared exactly once (on :root, inherited by body). That is the whole
   migration lever: re-pointing the values here moves all 24 inner pages onto
   the RODALICO palette and typography at once, with no per-page rule changes.

   The homepage is unaffected — public/home.css scopes its own --rod-* tokens
   under .rod-home and does not read the names below.
   ========================================================================== */

/* Self-hosted variable faces (SIL OFL, public/assets/brand/fonts/OFL.txt).
   Declared here rather than in home.css so every page gets the same
   typography; the binaries are shared, never duplicated. latin-ext is
   deliberately omitted — UA/RU/EN are covered by latin + cyrillic. */
@font-face {
  font-family: 'Inter Var';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('/assets/brand/fonts/Inter-Variable-cyrillic.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Inter Var';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('/assets/brand/fonts/Inter-Variable-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Inter Tight Var';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('/assets/brand/fonts/InterTight-Variable-cyrillic.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Inter Tight Var';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('/assets/brand/fonts/InterTight-Variable-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  /* RODALICO palette (contract §4). The legacy names are kept as the public
     vocabulary because every existing rule already reads them — only the
     values move. */
  --bg: #0B1E2D;
  --surface: #1A2733;
  --surface-alt: #2E3A46;
  --border: rgba(255, 255, 255, 0.10);
  --text: #FFFFFF;
  --text-muted: rgba(255, 255, 255, 0.72);
  --text-faint: rgba(255, 255, 255, 0.54);
  --accent: #FFC844;
  --accent-strong: #FFD978;
  --accent-contrast: #11212E;
  --danger: #F0787B;
  --verified: #79C99B;

  /* Canonical --rod-* vocabulary, published alongside the legacy names so new
     rules can use the contract's own token names. Same values, one source. */
  --rod-bg: var(--bg);
  --rod-bg-soft: #0D2233;
  --rod-surface: var(--surface);
  --rod-surface-raised: var(--surface-alt);
  --rod-border: var(--border);
  --rod-border-strong: rgba(255, 255, 255, 0.18);
  --rod-gold: var(--accent);
  --rod-gold-hover: var(--accent-strong);
  --rod-text: var(--text);
  --rod-text-muted: var(--text-muted);
  --rod-danger: var(--danger);
  --rod-success: var(--verified);
  --rod-warning: var(--accent);

  --radius-badge: 6px;
  --radius-control: 8px;
  --radius-card: 12px;
  --radius-panel: 16px;
  --radius: var(--radius-card);

  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 20px;
  --sp-6: 24px;
  --sp-8: 32px;
  --sp-12: 48px;
  --sp-16: 64px;

  --max-width: 1328px;
  --gutter: 24px;

  /* Motion tokens (contract §4): restrained, 120-220ms, state-communicating. */
  --motion-fast: 120ms;
  --motion-base: 160ms;
  --motion-slow: 220ms;
  --ease-out: cubic-bezier(0.22, 0.61, 0.36, 1);

  /* The homepage's lift shadow, promoted to the shared layer so inner pages
     use the same one instead of a second, slightly different value. */
  --shadow-2: 0 10px 30px rgba(0, 0, 0, 0.45);

  --font-display: 'Inter Tight Var', 'Inter Var', system-ui, "Segoe UI", sans-serif;

  font-family: 'Inter Var', system-ui, -apple-system, "Segoe UI", sans-serif;
}

/* Display face for headings across every page (contract §5). Page-specific
   sizes stay where they already are; this only sets the family and tightens
   tracking so headings match the homepage. */
h1, h2, h3, h4 {
  font-family: var(--font-display);
  letter-spacing: -0.015em;
}

* {
  box-sizing: border-box;
}

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: inherit;
  line-height: 1.5;
  overflow-x: hidden;
}

a {
  color: inherit;
}

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}

.container {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

/* ==========================================================================
   HEADER + MOBILE MENU
   ========================================================================== */

header.site-header {
  position: sticky;
  top: 0;
  z-index: 30;
  background: rgba(11, 30, 45, 0.92);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--border);
}

/* 20px matches the homepage's own header row (home.css), which is the layout
   every other page is being unified with. The old 24px was inherited from the
   pre-RODALICO header and cost 12px across the row's three gaps — enough to
   matter, because the full-size header only just fits a 1440px screen. */
.header-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 76px;
  gap: 20px;
}

.brand {
  display: block;
  line-height: 0;
  flex-shrink: 0;
}

/* logo-rodalico.png is the emblem+wordmark lockup, tightly cropped to
   its own content with a real alpha channel (no background patch) —
   sized by HEIGHT, width left to scale automatically so its wide
   aspect ratio is never stretched or cropped. */
.brand-logo {
  height: 40px;
  width: auto;
  display: block;
}

/* Brand lockup: the RODALICO logo stays primary; the descriptor is
   visually subordinate (smaller, muted, never gold) so it never competes
   with the logo. RODALICO has no parent-brand hierarchy to show.

   The descriptor sits BELOW the wordmark, never beside it — a real vertical
   lockup. Besides the hierarchy this is the point, it also stops the brand
   from spending the descriptor's full width on the header row, which is the
   scarcest space on the page. */
.brand-block {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 3px;
  flex-shrink: 0;
  min-width: 0;
}

.brand-tagline-desc {
  font-size: 12px;
  font-weight: 600;
  line-height: 1.2;
  color: var(--text-muted);
  white-space: nowrap;
}

.nav-links {
  display: flex;
  align-items: center;
  gap: var(--sp-6);
  flex: 1;
  justify-content: center;
}

.nav-links a {
  position: relative;
  text-decoration: none;
  color: var(--text-muted);
  font-size: 14px;
  font-weight: 600;
  white-space: nowrap;
  padding: 4px 0;
  transition: color 0.15s ease;
}

.nav-links a::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -4px;
  height: 2px;
  background: var(--accent);
  transform: scaleX(0);
  transition: transform 0.15s ease;
}

.nav-links a:hover {
  color: var(--text);
}

.nav-links a.active {
  color: var(--accent);
}

.nav-links a.active::after {
  transform: scaleX(1);
}

/* Garage keeps the pill accent it has on the homepage — it is the
   personalisation anchor, not just another nav item (contract §7). */
.nav-links a.nav-pill {
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 999px;
  padding: 7px 16px;
}

.nav-links a.nav-pill::after { display: none; }

.nav-links a.nav-pill:hover,
.nav-links a.nav-pill.active {
  border-color: var(--accent);
  color: var(--accent);
}

.nav-actions {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  flex-shrink: 0;
}

/* A header button is not a page button: the homepage already sizes its own at
   14px / 42px, so the shared header follows it rather than using the 15px / 44px
   page default. On /login and /sell, whose buttons carry a full sentence, this
   is also what keeps the full-size row inside a 1440px screen. */
.nav-actions .btn {
  font-size: 14px;
  padding: 10px 16px;
  min-height: 42px;
}

.menu-toggle {
  display: none;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 4px;
  width: 44px;
  height: 44px;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--radius-control);
  cursor: pointer;
  flex-shrink: 0;
}

.menu-toggle-bar {
  display: block;
  width: 18px;
  height: 2px;
  background: var(--text);
  border-radius: 2px;
}

.mobile-menu {
  border-top: 1px solid var(--border);
  background: var(--bg);
  padding: var(--sp-4) var(--gutter) var(--sp-6);
}

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

.mobile-menu nav {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-bottom: var(--sp-4);
}

.mobile-menu nav a {
  display: block;
  padding: 12px 4px;
  min-height: 44px;
  display: flex;
  align-items: center;
  color: var(--text);
  text-decoration: none;
  font-size: 16px;
  font-weight: 600;
  border-bottom: 1px solid var(--border);
}

.mobile-menu nav a.active {
  color: var(--accent);
}

.mobile-menu-actions {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}

/* The localized descriptor, also shown in the mobile menu since the
   header itself hides it below 1200px (nav collapses to hamburger there). */
.mobile-menu-tagline {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin: 0 0 var(--sp-3);
  padding-bottom: var(--sp-3);
  border-bottom: 1px solid var(--border);
}

/* ==========================================================================
   BUTTONS / GENERIC
   ========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 44px;
  padding: 11px 20px;
  border-radius: var(--radius-control);
  font-weight: 700;
  font-size: 15px;
  text-decoration: none;
  border: 1px solid transparent;
  cursor: pointer;
  transition: transform var(--motion-fast) var(--ease-out),
    background var(--motion-base) var(--ease-out),
    border-color var(--motion-base) var(--ease-out),
    color var(--motion-base) var(--ease-out),
    box-shadow var(--motion-base) var(--ease-out);
}

/* :not(:disabled) matches the hover rules below. Without it a disabled button
   still pressed down when clicked, which is exactly the false affordance this
   milestone is meant to remove. */
.btn:active:not(:disabled) {
  transform: translateY(1px);
}

.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* .btn-primary is the same primary treatment under the name catalog-search.html
   already uses. It was referenced there but defined nowhere, so that page's
   submit button rendered as a bare .btn with no fill at all. */
.btn-accent,
.btn-primary {
  background: var(--accent);
  color: var(--accent-contrast);
}

.btn-accent:hover:not(:disabled),
.btn-primary:hover:not(:disabled) {
  background: var(--accent-strong);
}

.btn-ghost {
  background: transparent;
  color: var(--text-muted);
  border-color: var(--border);
}

.btn-ghost:hover:not(:disabled) {
  color: var(--text);
  border-color: var(--text-muted);
}

.btn-lg { padding: 14px 26px; font-size: 16px; min-height: 56px; }
.btn-sm { padding: 6px 12px; font-size: 13px; min-height: 36px; }
.btn-block { width: 100%; }

.muted { color: var(--text-muted); }
.muted.small, .small { font-size: 12px; }

.sr-label {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

.mono {
  font-family: ui-monospace, Consolas, monospace;
}

.part-number {
  font-family: ui-monospace, Consolas, monospace;
  font-size: 18px;
  line-height: 24px;
  font-weight: 600;
  word-break: break-all;
}

/* ==========================================================================
   SECTIONS / GENERIC LAYOUT
   ========================================================================== */

.section {
  padding: clamp(48px, 6vh, 76px) 0 clamp(60px, 8vh, 96px);
}

/* A flat fill read as a grey box between dark sections; the homepage already
   fades its alternate band instead, and this matches it. */
.section-alt {
  background: linear-gradient(180deg, rgba(26, 39, 51, 0.72), rgba(26, 39, 51, 0));
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}

.section-heading {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-bottom: var(--sp-4);
  flex-wrap: wrap;
}

.section-heading h2 {
  font-size: clamp(22px, 2.2vw, 30px);
  line-height: 1.15;
  letter-spacing: -0.015em;
  margin: 0;
}

.section-heading .count {
  color: var(--text-faint);
  font-size: 14px;
}

.section-link {
  color: var(--accent);
  text-decoration: none;
  font-size: 14px;
  font-weight: 700;
}

/* Every inner page opens with this band, so it is the one lever that reaches
   all 25 of them at once. References 04, 05, 07, 08 and 09 all open the same
   way — a dark band carrying a kicker, a large headline, a lead and a primary
   action — where this was a thin label strip with a rule under it. */
.page-header {
  position: relative;
  padding: clamp(56px, 7vh, 88px) 0 clamp(32px, 4vh, 48px);
  border-bottom: 1px solid var(--border);
  background:
    radial-gradient(900px 340px at 8% 0%, rgba(255, 200, 68, 0.07), transparent 62%),
    linear-gradient(180deg, var(--surface) 0%, var(--bg) 100%);
}

/* Scaled towards the H1 of the brand system (64/72) without reaching it —
   these are section pages, not the homepage. The gold rule gives every inner
   page the accent the references put under their headings, and it is done with
   a pseudo-element so no page markup has to change. */
.page-header h1 {
  font-size: clamp(30px, 3.4vw, 50px);
  line-height: 1.08;
  letter-spacing: -0.02em;
  margin: 0 0 var(--sp-4);
  text-wrap: balance;
}

.page-header h1::after {
  content: '';
  display: block;
  width: 56px;
  height: 3px;
  margin-top: var(--sp-4);
  border-radius: 2px;
  background: var(--accent);
}

.page-header p {
  color: var(--text-muted);
  font-size: 17px;
  line-height: 1.6;
  max-width: 720px;
  margin: 0 0 var(--sp-6);
}

.page-header .section-link {
  display: inline-block;
  margin-bottom: var(--sp-6);
}

/* ==========================================================================
   LEGACY HOMEPAGE HERO/SEARCH — REMOVED
   --------------------------------------------------------------------------
   The old centred hero and its four-tab search widget belonged to the
   pre-ROD-VIS-001 homepage. index.html now renders .rod-hero / .rod-search
   from home.css, and an audit confirmed no page and no renderer references
   .hero-cinematic, .hero-copy, .hero-lead, .hero-kicker, .search-widget,
   .search-tabs, .tab-future or .search-panel any more.

   Two members of that block are deliberately KEPT below because they are
   still live elsewhere:
     .tab-radio  — login.html's auth tabs
     .search-note — garage.html's honest VIN note, catalog-search.js
   ========================================================================== */

.tab-radio {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

/* Kept: the honest "VIN is stored, not decoded" note under garage.html's VIN
   field, and the same note style reused by catalog-search.js. */
.search-note {
  margin: var(--sp-2) 2px 0;
  font-size: 12px;
  color: var(--text-faint);
}

/* ==========================================================================
   CATEGORY GRID
   ========================================================================== */

/* Matches the homepage grid. The fixed five-column rule made /categories
   lay out differently from the identical tiles on the homepage. */
/* Reference 09 leads each category with a photograph. We have no category
   imagery of our own, and every photo in that reference carries third-party
   marks (Bosch, Mann-Filter, Mobil, Shell, Castrol, Brembo), so the literal
   card is not available to us. The honest equivalent keeps the reference's
   proportion and gold mark and drops the photograph rather than inventing or
   borrowing one. */
.category-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(212px, 1fr));
  gap: var(--sp-4);
}

.category-tile {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: flex-start;
  gap: var(--sp-3);
  min-height: 118px;
  background: linear-gradient(180deg, var(--surface) 0%, rgba(26, 39, 51, 0.55) 100%);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: var(--sp-5);
  text-decoration: none;
  color: var(--text);
  /* Interaction states live in INTERACTIVE SURFACES, further down. */
}

/* The gold mark carries the card now that there is no photograph above it, so
   it is sized as a mark rather than a bullet — reference 09 gives its icon
   similar weight beside the label. */
.category-tile-icon {
  width: 44px;
  height: 44px;
  border-radius: 10px;
  background: rgba(255, 200, 68, 0.10);
  border: 1px solid rgba(255, 200, 68, 0.22);
  color: var(--accent);
  display: flex;
  align-items: center;
  justify-content: center;
}

.category-tile-icon svg {
  width: 24px;
  height: 24px;
}

.category-tile-icon svg {
  width: 100%;
  height: 100%;
}

/* Reference 09 leads each tile with a photograph and lets the label sit on the
   baseline beneath it. Two attempts at borrowing that proportion without the
   photograph failed in opposite directions — content stranded against the
   ceiling at 148px, then against the floor at 136px — because the empty middle
   reads as a hole whichever way it is aligned. The tile is therefore compact
   and dense instead: mark and label as one group, height set by content. */
.category-tile-label {
  font-size: 15px;
  line-height: 20px;
  font-weight: 700;
}

/* ==========================================================================
   PROMO / TWO-COLUMN LAYOUT
   ========================================================================== */

.two-col {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-6);
}

.two-col-garage { grid-template-columns: 1.3fr 1fr; align-items: start; }

.promo-card {
  display: flex;
  flex-direction: column;
  height: 100%;
  background: linear-gradient(180deg, var(--surface) 0%, rgba(26, 39, 51, 0.55) 100%);
  border: 1px solid var(--border);
  border-radius: var(--radius-panel);
  padding: var(--sp-6);
}

.promo-card > .btn { margin-top: auto; align-self: flex-start; }

.promo-card-accent {
  border-color: rgba(255, 200, 68, 0.35);
  background: linear-gradient(180deg, rgba(255, 200, 68, 0.06), var(--surface) 60%);
}

.promo-tag {
  display: inline-block;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: var(--sp-2);
}

.promo-card h3 { margin: 0 0 var(--sp-2); font-size: 20px; }
.promo-card p { color: var(--text-muted); font-size: 14px; margin: 0 0 var(--sp-4); }

/* ==========================================================================
   BUSINESS GRID
   ========================================================================== */

.business-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: var(--sp-4);
}

.business-grid-lg { grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }

/* Grid items stretch to the row's tallest card by default; laying the
   card out as a column and pinning its trailing link to the bottom via
   margin-top:auto keeps every button in a row on the same baseline
   regardless of how much title/description text each card has. */
/* Same shell family as .promo-card and .form-card so the B2B and supplier
   surfaces stop reading as a different product from the homepage. Still a
   container, not an action: no lift, no accent border on hover — that
   distinction was set in ROD-VIS-002C and holds. */
.business-card {
  display: flex;
  flex-direction: column;
  height: 100%;
  background: linear-gradient(180deg, var(--surface) 0%, rgba(26, 39, 51, 0.55) 100%);
  border: 1px solid var(--border);
  border-radius: var(--radius-panel);
  padding: var(--sp-5);
}

.business-card h4 { margin: 0 0 var(--sp-2); font-size: 16px; }
.business-card p { color: var(--text-muted); font-size: 13px; margin: 0 0 var(--sp-3); }
.business-card > .btn { margin-top: auto; align-self: flex-start; }

/* ==========================================================================
   COMPACT TRUST / VALUE SECTION
   ========================================================================== */

.trust-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: var(--sp-4);
}

.trust-feature h4 { margin: 0 0 var(--sp-2); font-size: 15px; color: var(--text); }
.trust-feature p { color: var(--text-muted); font-size: 13px; margin: 0; }

/* .cta-banner belonged to the retired homepage banner — no page or renderer
   references it any more (verified by audit). Removed. */

/* ==========================================================================
   MARKETPLACE
   ========================================================================== */

.filter-bar {
  display: flex;
  gap: var(--sp-3);
  margin-bottom: var(--sp-6);
  flex-wrap: wrap;
}

.filter-bar input,
.filter-bar select {
  min-height: 44px;
  background: var(--surface-alt);
  border: 1px solid var(--border);
  border-radius: var(--radius-control);
  padding: 0 var(--sp-3);
  color: var(--text);
  font-size: 14px;
  font-family: inherit;
}

.filter-bar input { flex: 2; min-width: 220px; }
.filter-bar select { flex: 1; min-width: 180px; }

.listings-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: var(--sp-3);
}

a.offer-card,
a.offer-card * {
  text-decoration: none;
}

a.offer-card {
  cursor: pointer;
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--sp-1) var(--sp-3);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: var(--sp-4);
  color: var(--text);
  /* Interaction states live in INTERACTIVE SURFACES, further down. */
}

/* Service Marketplace v1 — same base card visual as a.offer-card, but a
   simpler single-column layout (no price/availability row). */
a.service-card,
a.service-card * {
  text-decoration: none;
}

a.service-card {
  cursor: pointer;
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: var(--sp-4);
  color: var(--text);
  /* Interaction states live in INTERACTIVE SURFACES, further down. */
}

a.service-card h3 { margin: 0; font-size: 15px; font-weight: 700; }
a.service-card .meta-line { color: var(--text-muted); font-size: 13px; }
a.service-card .service-card-desc { color: var(--text-muted); font-size: 13px; overflow-wrap: anywhere; }

/* ==========================================================================
   INTERACTIVE SURFACES — one interaction language for the whole site
   ==========================================================================
   The homepage already had one: a card takes the gold border, lifts 2px and
   gains a soft shadow on hover, presses back down on click, and runs on the
   --motion-* tokens. Inner pages only ever changed border-color, which is the
   whole reason the homepage felt alive and everything behind it felt static.
   This is that same language, written once, in the shared layer.

   Every selector here is an <a> that actually navigates:
     .category-tile  -> /marketplace?category=...  (categories.js, landing.js)
     a.offer-card    -> /offer?id=...              (marketplace.js)
     a.service-card  -> /service?id=..., /repair-request?id=...  (services.js,
                        repair-requests.js)

   Deliberately excluded, because they are containers and not actions:
   .business-card and .promo-card (informational tiles, several of them marked
   ПЛАНУЄТЬСЯ), .form-card, .auth-card, .compare-card, and .vehicle-card — the
   last one looks like a card but is a panel whose buttons are the real
   actions. A lift on any of those would promise a click that does not exist. */
.category-tile,
a.offer-card,
a.service-card {
  transition: border-color var(--motion-base) var(--ease-out),
    transform var(--motion-base) var(--ease-out),
    box-shadow var(--motion-base) var(--ease-out);
}

.category-tile:hover,
a.offer-card:hover,
a.service-card:hover {
  border-color: var(--accent);
  transform: translateY(-2px);
  box-shadow: var(--shadow-2);
}

/* Pressing settles the card back onto the page. Deliberately not a scale: it
   must not reflow or nudge its neighbours. */
.category-tile:active,
a.offer-card:active,
a.service-card:active {
  transform: translateY(0);
  box-shadow: none;
  transition-duration: var(--motion-fast);
}

/* Keyboard focus must read as focus, not as hover: the shared :focus-visible
   outline near the top of this file supplies the ring, and the card takes the
   accent border so the target is unmistakable without borrowing the lift. */
.category-tile:focus-visible,
a.offer-card:focus-visible,
a.service-card:focus-visible {
  border-color: var(--accent);
}

/* This has to sit after the rules above, not with the global reduced-motion
   block near the top: media queries add no specificity, so an earlier
   transform: none simply loses to a later :hover. The homepage resolves it the
   same way, at the end of home.css. Motion goes; the border, the shadow and
   the focus ring stay, so an element never stops looking interactive. */
@media (prefers-reduced-motion: reduce) {
  .category-tile,
  a.offer-card,
  a.service-card,
  .category-tile:hover,
  a.offer-card:hover,
  a.service-card:hover,
  .category-tile:active,
  a.offer-card:active,
  a.service-card:active {
    transform: none;
  }

  .btn:active:not(:disabled) {
    transform: none;
  }
}

.offer-card .category-tag {
  grid-column: 1 / -1;
  align-self: flex-start;
  font-size: 11px;
  font-weight: 700;
  color: var(--text-muted);
  background: var(--surface-alt);
  border: 1px solid var(--border);
  padding: 2px 8px;
  border-radius: var(--radius-badge);
  justify-self: start;
}

.offer-card .offer-card-number {
  grid-column: 1 / -1;
  color: var(--text);
}

.offer-card .offer-card-number.is-missing {
  font-family: inherit;
  font-size: 13px;
  font-weight: 400;
  color: var(--text-faint);
  font-style: italic;
}

.offer-card h3 {
  grid-column: 1 / -1;
  margin: 0;
  font-size: 15px;
  font-weight: 700;
  line-height: 1.35;
}

.offer-card .meta-line {
  grid-column: 1 / -1;
  color: var(--text-muted);
  font-size: 13px;
}

.offer-card .price-row {
  grid-column: 1 / -1;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-2);
  margin-top: 2px;
}

.offer-card .price {
  font-size: 22px;
  line-height: 28px;
  font-weight: 800;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

.offer-card .availability {
  font-size: 13px;
  color: var(--text-muted);
}

.trust-badge {
  grid-column: 1 / -1;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  font-weight: 700;
  border-top: 1px solid var(--border);
  padding-top: var(--sp-2);
  margin-top: 2px;
}

.trust-badge.trust-unverified { color: var(--text-faint); }
.trust-badge.trust-verified { color: var(--verified); }

.offer-card .posted {
  grid-column: 1 / -1;
  font-size: 11px;
  color: var(--text-faint);
}

/* Compare selection — a sibling of a.offer-card (see marketplace.js),
   never nested inside it. */
.offer-card-wrap {
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
}

.compare-select {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  align-self: flex-start;
  font-size: 12px;
  color: var(--text-muted);
  cursor: pointer;
  padding: 2px 0;
}

.compare-select input[type="checkbox"] {
  width: 16px;
  height: 16px;
  accent-color: var(--accent);
  cursor: pointer;
}

.compare-select input[type="checkbox"]:disabled {
  cursor: not-allowed;
}

.compare-bar {
  position: sticky;
  bottom: 0;
  z-index: 5;
  background: var(--surface);
  border-top: 1px solid var(--border);
  box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.25);
}

.compare-bar-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  /* Extra right padding reserves the corner the ARTCOR launcher floats
     in (56px button + margin) so the Compare button is never covered by
     it when both are visible at once. */
  padding: var(--sp-3) calc(var(--gutter) + 72px) var(--sp-3) var(--gutter);
  flex-wrap: wrap;
}

@media (max-width: 560px) {
  .compare-bar-inner { padding-right: calc(var(--gutter) + 62px); }
}

.compare-bar-count {
  font-size: 13px;
  font-weight: 700;
  color: var(--text);
}

.compare-bar-actions {
  display: flex;
  gap: var(--sp-2);
  flex-wrap: wrap;
}

/* /compare — stacked key-value cards rather than a wide table, so a
   4-offer comparison stays usable at 375px with no horizontal scroll. */
.compare-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: var(--sp-4);
  align-items: start;
}

.compare-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: var(--sp-4);
}

.compare-card.is-cheapest {
  border-color: var(--accent);
}

.compare-card h3 {
  margin: 0 0 var(--sp-2);
  font-size: 16px;
  overflow-wrap: anywhere;
}

.compare-card .spec-table {
  margin: var(--sp-3) 0;
}

.compare-card .spec-table th {
  width: 42%;
}

.compare-cheapest-tag {
  display: inline-block;
  font-size: 11px;
  font-weight: 700;
  color: var(--accent);
  border: 1px solid var(--accent);
  border-radius: var(--radius-badge);
  padding: 2px 8px;
  margin-bottom: var(--sp-2);
}

.compare-missing-note {
  color: var(--text-muted);
  font-size: 13px;
  margin-bottom: var(--sp-4);
}

.empty-state,
.loading-state,
.error-state {
  color: var(--text-muted);
  font-size: 14px;
  padding: var(--sp-8) 0;
}

.error-state {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  flex-wrap: wrap;
}

/* P2 Search Core fuzzy candidates — a discovery suggestion, never a
   canonical/exact match, so this block is deliberately visually distinct
   from an exact-match result table (dashed border, muted note). */
/* --border-color has never existed in this project (the token is --border),
   so the #ccc fallback was painting a light-grey box on a dark ground. The
   dashed treatment itself is deliberate and kept: it marks discovery
   suggestions as visually distinct from an exact/canonical result. */
.catalog-search-fuzzy-block {
  margin-top: var(--sp-4);
  padding: var(--sp-4);
  border: 1px dashed var(--border);
  border-radius: var(--radius-card);
  background: rgba(255, 255, 255, 0.02);
}

.catalog-search-fuzzy-note {
  color: var(--text-muted);
  font-size: 13px;
  margin-bottom: var(--sp-3);
}

/* Rendered by catalog-search.js but never defined until now — the exact/
   ambiguous result tables and the ambiguity note had no rules at all. */
.catalog-search-form {
  display: grid;
  grid-template-columns: 1fr 1fr auto;
  gap: var(--sp-3);
  align-items: end;
  margin-bottom: var(--sp-6);
}

.catalog-search-form label {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 13px;
  font-weight: 700;
  color: var(--text-muted);
}

.catalog-search-form input {
  min-height: 48px;
  background: var(--surface-alt);
  border: 1px solid var(--border);
  border-radius: var(--radius-control);
  padding: 10px var(--sp-3);
  color: var(--text);
  font-size: 15px;
  font-family: inherit;
}

.catalog-search-form .btn { min-height: 48px; }

.catalog-search-note {
  color: var(--text-muted);
  font-size: 14px;
  margin: 0 0 var(--sp-3);
}

.catalog-search-table thead th {
  color: var(--text-faint);
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  width: auto;
}

.catalog-search-table td { font-size: 14px; }

@media (max-width: 620px) {
  .catalog-search-form { grid-template-columns: 1fr; }
  .catalog-search-result { overflow-x: auto; }
}

/* ==========================================================================
   ARTCOR — shared assistant panel (public/vegaAiWidget.js). Contextual,
   restrained: a ghost-button CTA that opens a small card, never a
   dominant fixed overlay or a second color system.
   ========================================================================== */

.vega-ai-widget {
  margin-top: var(--sp-4);
}

.vega-ai-panel {
  margin-top: var(--sp-3);
  padding: var(--sp-4);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
}

.vega-ai-input {
  width: 100%;
  min-height: 72px;
  background: var(--surface-alt);
  border: 1px solid var(--border);
  border-radius: var(--radius-control);
  padding: 10px var(--sp-3);
  color: var(--text);
  font-size: 14px;
  font-family: inherit;
  resize: vertical;
  margin-bottom: var(--sp-3);
}

.vega-ai-panel-actions {
  display: flex;
  gap: var(--sp-2);
  flex-wrap: wrap;
}

.vega-ai-result {
  margin-top: var(--sp-3);
}

.vega-ai-result:empty {
  margin-top: 0;
}

.vega-ai-result h4 {
  font-size: 13px;
  color: var(--text-muted);
  margin: var(--sp-3) 0 var(--sp-1);
}

.vega-ai-result ul {
  margin: 0 0 var(--sp-2);
  padding-left: 18px;
}

.vega-ai-error {
  color: var(--danger);
  font-size: 14px;
}

.vega-ai-disclaimer {
  margin-top: var(--sp-3);
  padding-top: var(--sp-3);
  border-top: 1px solid var(--border);
}

.vega-ai-divider {
  border: 0;
  border-top: 1px solid var(--border);
  margin: var(--sp-6) 0;
}

.vega-ai-hint-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--surface-alt);
  border: 1px solid var(--border);
  border-radius: var(--radius-badge);
  padding: 4px 10px;
  margin: 0 6px 6px 0;
  font-size: 13px;
}

/* ==========================================================================
   OFFER DETAIL
   ========================================================================== */

.back-link {
  display: inline-block;
  color: var(--text-muted);
  text-decoration: none;
  font-size: 13px;
  margin-bottom: var(--sp-4);
  min-height: 44px;
  display: inline-flex;
  align-items: center;
}

.back-link:hover { color: var(--accent); }

.offer-detail-grid {
  display: grid;
  grid-template-columns: 1fr 340px;
  gap: var(--sp-8);
  align-items: start;
}

.offer-detail-eyebrow {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  color: var(--text-muted);
  font-size: 13px;
  margin-bottom: var(--sp-2);
}

.offer-detail-main h1 {
  font-size: 32px;
  line-height: 40px;
  margin: 0 0 var(--sp-3);
  overflow-wrap: anywhere;
}

.spec-table {
  width: 100%;
  border-collapse: collapse;
  margin: var(--sp-4) 0;
}

.spec-table th,
.spec-table td {
  text-align: left;
  padding: 10px 0;
  border-bottom: 1px solid var(--border);
  font-size: 14px;
  vertical-align: top;
}

.spec-table td {
  overflow-wrap: anywhere;
}

.spec-table th {
  color: var(--text-faint);
  font-weight: 600;
  width: 220px;
  padding-right: var(--sp-3);
}

.offer-section { margin-top: var(--sp-6); }
.offer-section h3 { font-size: 15px; margin: 0 0 var(--sp-2); color: var(--text-muted); }
.offer-section p { margin: 0; font-size: 14px; line-height: 1.6; overflow-wrap: anywhere; }

.offer-detail-side {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-panel);
  padding: var(--sp-6);
  position: sticky;
  /* Header is 76px tall (contract §6) — this offset must clear it, otherwise
     the sticky side panel slides under the shared header. */
  top: calc(76px + var(--sp-3));
}

.price-block {
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  margin-bottom: var(--sp-4);
}

.price-block .price { font-size: 28px; font-weight: 800; color: var(--text); font-variant-numeric: tabular-nums; }
.price-block .availability { color: var(--text-muted); font-size: 13px; }

.offer-detail-side .btn-block + .btn-block { margin-top: var(--sp-2); }

/* ==========================================================================
   GARAGE
   ========================================================================== */

.garage-empty {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sp-3);
  padding: var(--sp-8) 0;
  color: var(--text-muted);
}

.garage-empty-icon {
  width: 48px;
  height: 48px;
  color: var(--text-faint);
}

.garage-empty h3 { margin: 0; font-size: 16px; color: var(--text); }
.garage-empty p { margin: 0; font-size: 14px; max-width: 360px; }

.vehicle-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: var(--sp-4);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-bottom: var(--sp-3);
  flex-wrap: wrap;
}

.vehicle-card h3 { margin: 0 0 4px; font-size: 16px; }
.vehicle-card-actions { display: flex; gap: var(--sp-2); flex-shrink: 0; }

/* ==========================================================================
   ARTCOR
   ========================================================================== */

.vega-badge {
  display: inline-flex;
  align-items: center;
  font-size: 12px;
  font-weight: 700;
  color: var(--text-muted);
  background: var(--surface-alt);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 4px 12px;
  margin-bottom: var(--sp-3);
}

.vega-examples {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin: var(--sp-2) 0 var(--sp-4);
}

.vega-example-chip {
  font-family: ui-monospace, Consolas, monospace;
  font-size: 13px;
  background: var(--surface-alt);
  border: 1px solid var(--border);
  border-radius: var(--radius-control);
  padding: 6px 12px;
  min-height: 36px;
  color: var(--text-muted);
  cursor: pointer;
}

.vega-example-chip:hover { color: var(--text); border-color: var(--accent); }

.feature-list {
  list-style: none;
  padding: 0;
  margin: 0 0 var(--sp-4);
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}

.feature-list li {
  padding-left: 22px;
  position: relative;
  font-size: 14px;
  color: var(--text-muted);
}

.feature-list li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 7px;
  width: 8px;
  height: 8px;
  border-radius: 2px;
  background: var(--accent);
}

/* ==========================================================================
   AUTH
   ========================================================================== */

.auth-section { padding: var(--sp-12) 0 var(--sp-16); }
.auth-container { display: flex; justify-content: center; }
.auth-card { width: 100%; max-width: 440px; padding: 32px; }

.auth-tabs {
  display: flex;
  gap: 4px;
  margin-bottom: var(--sp-6);
  border-bottom: 1px solid var(--border);
}

.auth-tabs label {
  flex: 1;
  text-align: center;
  padding: 10px 0;
  min-height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  font-weight: 700;
  color: var(--text-muted);
  cursor: pointer;
  border-bottom: 2px solid transparent;
}

.auth-panel { display: none; }
.auth-panel h1 { font-size: 22px; margin: 0 0 var(--sp-2); }
.auth-card .btn,
.auth-card .field input { min-height: 48px; }

#tab-login:checked ~ .auth-tabs label[for="tab-login"],
#tab-register:checked ~ .auth-tabs label[for="tab-register"] {
  color: var(--accent);
  border-bottom-color: var(--accent);
}

#tab-login:checked ~ .auth-panels .panel-login,
#tab-register:checked ~ .auth-panels .panel-register {
  display: block;
}

.form-status.pending { color: var(--accent); }

.password-field {
  position: relative;
  display: flex;
}

.password-field input {
  flex: 1;
  padding-right: 84px;
}

.password-toggle {
  position: absolute;
  right: 6px;
  top: 50%;
  transform: translateY(-50%);
  background: transparent;
  border: none;
  color: var(--text-muted);
  font-size: 12px;
  font-weight: 700;
  cursor: pointer;
  padding: 6px 8px;
  min-height: 32px;
}

.password-toggle:hover { color: var(--accent); }

.field-error {
  color: var(--danger);
  font-size: 13px;
  margin: -6px 0 var(--sp-4);
}

/* ==========================================================================
   ACCOUNT
   ========================================================================== */

.account-pill {
  font-weight: 700;
}

.account-actions {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  margin-bottom: var(--sp-3);
}

.profile-list {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  margin: var(--sp-4) 0;
}

.profile-row {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-bottom: var(--sp-3);
  border-bottom: 1px solid var(--border);
}

.profile-row .profile-label {
  font-size: 13px;
  color: var(--text-faint);
}

.profile-row .profile-value {
  font-size: 16px;
  color: var(--text);
  overflow-wrap: anywhere;
}

/* ==========================================================================
   FORMS (shared: sell, garage)
   ========================================================================== */

.form-card {
  background: linear-gradient(180deg, var(--surface) 0%, rgba(26, 39, 51, 0.55) 100%);
  border: 1px solid var(--border);
  border-radius: var(--radius-panel);
  padding: var(--sp-6);
  max-width: 680px;
}

.form-card h1 {
  font-size: 24px;
  margin: 0 0 var(--sp-2);
}

.form-note {
  color: var(--text-muted);
  font-size: 13px;
  margin: 0 0 var(--sp-6);
  line-height: 1.5;
}

.field-group {
  margin-bottom: var(--sp-6);
  padding-bottom: var(--sp-4);
  border-bottom: 1px solid var(--border);
}

.field-group:last-of-type {
  border-bottom: none;
}

.field-group-title {
  font-size: 12px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-faint);
  margin: 0 0 var(--sp-4);
}

.field {
  margin-bottom: var(--sp-4);
}

.field label {
  display: block;
  font-size: 13px;
  font-weight: 700;
  color: var(--text-muted);
  margin-bottom: 6px;
}

.field .hint {
  font-weight: 400;
  color: var(--text-faint);
  text-transform: none;
}

.field input,
.field select,
.field textarea {
  width: 100%;
  min-height: 48px;
  background: var(--surface-alt);
  border: 1px solid var(--border);
  border-radius: var(--radius-control);
  padding: 10px var(--sp-3);
  color: var(--text);
  font-size: 15px;
  font-family: inherit;
}

.field textarea {
  resize: vertical;
  min-height: 80px;
}

.field-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-3);
}

.form-status {
  margin-top: var(--sp-4);
  font-size: 14px;
  min-height: 20px;
}

.form-status.error {
  color: var(--danger);
}

.form-status.success {
  color: var(--text);
}

.form-status.success a {
  color: var(--accent);
  font-weight: 700;
}

.success-block {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sp-3);
  padding: var(--sp-6) 0;
}

.success-block .success-icon { color: var(--verified); width: 40px; height: 40px; }
.success-block h3 { margin: 0; font-size: 18px; }
.success-block p { margin: 0; color: var(--text-muted); font-size: 14px; }

.provenance-note {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-2);
  font-size: 12px;
  color: var(--text-faint);
  margin-top: var(--sp-4);
  padding-top: var(--sp-4);
  border-top: 1px solid var(--border);
}

.about-content p {
  max-width: 720px;
  color: var(--text-muted);
  font-size: 15px;
  line-height: 1.7;
  margin: 0 0 var(--sp-4);
}

.about-content h2 {
  font-size: 20px;
  margin: var(--sp-8) 0 var(--sp-3);
}

.about-content h2:first-child { margin-top: 0; }

/* /about — brand decode (RO/DA/LI/CO), lead statement and the
   AVAILABLE/IN DEVELOPMENT/PLANNED capability-status system. Reuses
   .trust-grid/.trust-feature and .business-grid/.business-card as-is;
   only these small additions are page-specific. */
.decode-code {
  color: var(--accent);
  font-weight: 800;
}

.about-lead {
  font-size: 17px;
  line-height: 1.7;
  color: var(--text);
  max-width: 760px;
  margin: var(--sp-8) 0 var(--sp-6);
}

.status-legend {
  display: flex;
  gap: var(--sp-3);
  flex-wrap: wrap;
  margin: var(--sp-2) 0 var(--sp-2);
}

/* One fixed slot for the status pill, always ABOVE the title — never
   inline with it — so badge position never shifts with title length
   (a 1-line vs 2-line title used to push an inline badge to a
   different row, which read as inconsistent placement). */
.card-status-row {
  margin-bottom: var(--sp-2);
}

.status-badge {
  display: inline-block;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 3px 9px;
  border-radius: var(--radius-badge);
  border: 1px solid;
  line-height: 1.4;
  white-space: nowrap;
}

.status-available { color: var(--verified); border-color: var(--verified); background: rgba(121, 201, 155, 0.1); }
.status-development { color: var(--accent); border-color: var(--accent); background: rgba(255, 200, 68, 0.1); }
.status-planned { color: var(--text-faint); border-color: var(--border); background: rgba(255, 255, 255, 0.04); }

/* ==========================================================================
   FREE BETA NOTE
   ========================================================================== */

/* One quiet line, not a banner. The owner-approved free public beta runs
   2026-09-20 .. 2026-12-20 and it only ever appears where a visitor would
   actually wonder about cost: the homepage, the three posting surfaces, the
   business overview and the account page. Built from existing tokens (navy
   surface, hairline border, gold accent for the dates) so it reads as part
   of the shell rather than a promo overlay. Static text on purpose -- no
   countdown, no automatic state change when the date passes: the end of the
   beta is a product decision, never a timer. */
.beta-note {
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  margin: var(--sp-4) 0 0;
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--border);
  border-left: 2px solid var(--accent);
  border-radius: var(--radius-card);
  background: rgba(255, 200, 68, 0.04);
  max-width: 640px;
}

.beta-note strong {
  color: var(--text);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.01em;
}

.beta-note span:not(:first-child),
.beta-note p {
  margin: 0;
  color: var(--text-faint);
  font-size: 12px;
  line-height: 1.5;
}

@media (max-width: 560px) {
  .beta-note { padding: var(--sp-3); }
}

/* ==========================================================================
   FOOTER
   ========================================================================== */

footer.site-footer {
  border-top: 1px solid var(--border);
  padding: var(--sp-8) 0 0;
  color: var(--text-faint);
  font-size: 12px;
}

/* Four children: .footer-brand plus three .footer-col groups, matching the
   homepage's own grid in home.css. The third column wraps onto a second row
   if this is left at three tracks. */
.footer-grid {
  display: grid;
  grid-template-columns: 1.6fr 1fr 1fr 1fr;
  gap: var(--sp-6);
  padding-bottom: var(--sp-6);
}

.footer-logo { height: 40px; width: auto; margin-bottom: var(--sp-2); }
.footer-brand p { color: var(--text-faint); font-size: 13px; max-width: 260px; margin: 0; }

.footer-col h4 {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
  margin: 0 0 var(--sp-3);
}

.footer-col a,
.footer-col .footer-placeholder {
  display: block;
  color: var(--text-faint);
  text-decoration: none;
  font-size: 13px;
  margin-bottom: var(--sp-2);
  min-height: 20px;
}

.footer-col a:hover { color: var(--accent); }

.footer-bottom {
  border-top: 1px solid var(--border);
  padding: var(--sp-4) 0;
  color: var(--text-faint);
  font-size: 12px;
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  flex-wrap: wrap;
}

.footer-bottom a {
  color: var(--text-faint);
  text-decoration: none;
}

.footer-bottom a:hover { color: var(--accent); }

/* ==========================================================================
   RESPONSIVE
   ========================================================================== */

/* Inner pages used to collapse at 1200px while the homepage collapsed at
   900px, so the same viewport showed a full nav on one page and a burger on
   the next — the most visible symptom of "new homepage, old site behind it".
   Matching the homepage's 900px looked like the obvious unification, but
   measuring the header in the browser disproved it: with the nav expanded the
   row has a hard minimum width, and anything below it overflowed horizontally.
   The threshold is re-derived from measurement every time the header's content
   changes. With seven nav items it is 1279px: the compacted row needs 1219px
   at its widest (en /login), so the expanded nav is only used where it
   demonstrably fits, in every language, with 61px to spare. */
@media (max-width: 1279px) {
  .nav-links { display: none; }
  .menu-toggle { display: flex; }
  .header-row { height: 68px; }
  .brand-logo { height: 36px; }
}

@media (min-width: 1280px) {
  .mobile-menu { display: none !important; }
}

@media (max-width: 1024px) {
  .category-grid { grid-template-columns: repeat(4, 1fr); }
}

@media (max-width: 860px) {
  .two-col, .two-col-garage { grid-template-columns: 1fr; }
  .offer-detail-grid { grid-template-columns: 1fr; }
  .offer-detail-side { position: static; }
  .footer-grid { grid-template-columns: 1fr 1fr; }
  .category-grid { grid-template-columns: repeat(3, 1fr); }
  .garage-form-col { order: 2; }
  .garage-list-col { order: 1; }
}

@media (max-width: 560px) {
  :root { --gutter: 16px; }
  .page-header h1 { font-size: 28px; line-height: 34px; }
  .offer-detail-main h1 { font-size: 28px; line-height: 34px; }
  .footer-grid { grid-template-columns: 1fr; }
  .category-grid { grid-template-columns: repeat(2, 1fr); }
  .field-row { grid-template-columns: 1fr; }
  .spec-table th { width: 40%; }
  .auth-card { padding: 20px; }
}

/* Compact language preference; independent of account controls. */
.language-selector { display: flex; gap: 2px; padding: 4px; border: 1px solid var(--border); border-radius: 8px; flex-shrink: 0; }
.language-selector button { border: 0; border-radius: 5px; padding: 6px 11px; background: transparent; color: var(--text-faint); font: inherit; font-size: 12px; font-weight: 600; cursor: pointer; }
.language-selector button[aria-pressed="true"] { color: var(--accent); background: var(--surface); font-weight: 700; }
.language-selector button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
@media (max-width: 560px) { .header-row { flex-wrap: wrap; height: auto; min-height: 64px; padding-top: 8px; padding-bottom: 8px; gap: 8px; } .language-selector { margin-left: auto; } }

/* Owner-only navigation can wrap without widening the public header
   (mobile slide-out panel only — the desktop header row uses the
   single-trigger .account-menu below instead). */
.header-row .operator-nav { flex-wrap: wrap; min-width: 0; max-width: 100%; }

/* Desktop authenticated account menu: name + Operator Center + Logout
   collapse into ONE fixed-max-width trigger button, so the header row's
   width never depends on display-name length or operator status (root
   cause of the authenticated-only overflow at ordinary laptop widths). */
.account-menu { position: relative; }

.account-menu-toggle { max-width: 220px; }

.account-menu-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 160px;
}

.account-menu-caret {
  font-size: 10px;
  color: var(--text-faint);
}

.account-menu-panel {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  min-width: 200px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-control);
  padding: var(--sp-2);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.4);
  z-index: 40;
}

.account-menu-panel[hidden] { display: none; }

.account-menu-item {
  display: block;
  width: 100%;
  min-height: 40px;
  padding: 10px 12px;
  border: 0;
  border-radius: var(--radius-control);
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
}

.account-menu-item:hover { background: var(--surface-alt); }
.account-menu-item:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* Progressive compaction of the public row before the 900px hamburger
   breakpoint. The descriptor now survives down to 1100px instead of being
   dropped at 1600px: with six nav items (not eight) and the account menu
   bounded below, the row has room, and hiding it that early was the old
   1200px-era compromise. */
/* Measured per part, in all three languages, because .nav-links is flex:1 and
   its rendered width is therefore never its intrinsic one — summing the row's
   children reports the container width and tells you nothing.
   Full size: brand-block 170-181, language selector 130, seven nav items plus
   six gaps 690-713, header button 197-221 on /login, 150-173 on /sell, ~80
   elsewhere, 3 x 20px row gaps and 2 x 24px container padding. Worst case is
   ru /login at 1329px; compacted it is en /login at 1219px, English winning
   there because "About platform" and "Continue without signing in" are the
   longest labels in the set.
   The seventh nav item (/about) and the vertical brand lockup both landed in
   this milestone: the lockup gave 182px back (the descriptor no longer sits
   beside the logo), the seventh item took ~130px, and the net effect still
   moved the hamburger threshold up.

   So the header has three honest states rather than one plus a patch:
     <= 1279px  hamburger; nav lives in the mobile menu
     1280..1439 compact nav (13px labels, tighter gaps, small header button)
     >= 1440px  full size

   The descriptor stays visible in all three states. Hiding it was inherited
   from the horizontal lockup, where it cost 182px of row width; stacked under
   the logo it costs the difference between its own width and the logo's —
   5 to 11px depending on language. Measurement does not justify hiding it,
   and the owner's requirement is that it only disappear where it must.

   The boundary is 1440 and not 1400 because the browser said so: at 1400 the
   full-size /login row still measured 1409px wide and overflowed by 9px. The
   arithmetic had missed the header container's side gutters, which is exactly
   why each of these numbers is a measurement rather than an estimate.
   Both bands keep real slack on the widest page, so a language switch that
   lengthens the labels cannot push the row over the edge. */
@media (min-width: 1280px) and (max-width: 1439px) {
  .header-row { gap: 16px; }
  .nav-links { gap: 18px; }
  .nav-links a { font-size: 13px; }

  /* login.html and sell.html carry their own long-text header buttons
     ("Продовжити без входу", "До маркетплейсу") instead of the short
     "Увійти", and deliberately omit the nav-action ids so common.js leaves
     them alone. They are the widest pages, so they set the floor above. */
  .nav-actions .btn {
    font-size: 13px;
    padding: 8px 14px;
    min-height: 38px;
  }
}

@media (max-width: 1000px) {
  .account-menu-toggle { max-width: 160px; }
  .account-menu-name { max-width: 100px; }
}

.google-auth-panel { margin-bottom: 20px; }
.google-auth-panel h3 { margin-bottom: 12px; }
.google-button { min-height: 40px; max-width: 100%; }
.google-status { margin-top: 10px; overflow-wrap: anywhere; }

/* ==========================================================================
   ARTCOR LAUNCHER + MINI-CHAT (public/artcorLauncher.js)
   Injected once on every page from common.js. Sits above the header's own
   z-index (30) but stays a small corner element — it must never obstruct
   page content, so it has no full-screen backdrop/overlay of its own.
   ========================================================================== */

.artcor-launcher {
  position: fixed;
  right: var(--sp-4);
  bottom: var(--sp-4);
  z-index: 40;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  border: 1px solid rgba(255, 200, 68, 0.5);
  background: linear-gradient(150deg, var(--accent-strong), var(--accent) 70%);
  color: var(--accent-contrast);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.artcor-launcher:hover { transform: translateY(-2px); box-shadow: 0 10px 28px rgba(0, 0, 0, 0.4); }
.artcor-launcher:active { transform: translateY(0); }

.artcor-launcher-avatar { width: 26px; height: 26px; display: flex; }
.artcor-launcher-avatar svg { width: 100%; height: 100%; }

.artcor-chat-panel {
  position: fixed;
  right: var(--sp-4);
  bottom: calc(56px + var(--sp-4) + var(--sp-3));
  z-index: 40;
  width: 360px;
  max-width: calc(100vw - (2 * var(--sp-4)));
  max-height: min(520px, 70vh);
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-panel);
  box-shadow: 0 16px 48px rgba(0, 0, 0, 0.5);
  overflow: hidden;
}

/* Same specificity as the class rule above, but declared after it —
   without this, source order alone would let display:flex win over the
   browser's own default [hidden]{display:none} and the panel would
   render open before the launcher is ever clicked. */
.artcor-chat-panel[hidden] { display: none; }

.artcor-chat-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}

.artcor-chat-title { font-weight: 800; letter-spacing: 0.02em; color: var(--accent); }

.artcor-chat-close {
  background: transparent;
  border: 0;
  color: var(--text-faint);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  padding: 4px 6px;
}

.artcor-chat-close:hover { color: var(--text); }

.artcor-chat-body {
  flex: 1;
  overflow-y: auto;
  padding: var(--sp-3) var(--sp-4);
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  min-height: 160px;
}

.artcor-chat-bubble {
  max-width: 85%;
  padding: 8px 12px;
  border-radius: 12px;
  font-size: 13px;
  line-height: 1.5;
  overflow-wrap: anywhere;
  white-space: pre-line;
}

.artcor-chat-bubble-assistant {
  align-self: flex-start;
  background: var(--surface-alt);
  color: var(--text);
  border-bottom-left-radius: 4px;
}

.artcor-chat-bubble-user {
  align-self: flex-end;
  background: var(--accent);
  color: var(--accent-contrast);
  border-bottom-right-radius: 4px;
}

.artcor-chat-quicklinks {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-self: stretch;
}

.artcor-chat-quicklink {
  display: inline-block;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-muted);
  background: var(--surface-alt);
  border: 1px solid var(--border);
  border-radius: var(--radius-badge);
  padding: 5px 10px;
  text-decoration: none;
}

.artcor-chat-quicklink:hover { color: var(--text); border-color: var(--accent); }

.artcor-chat-form {
  display: flex;
  gap: var(--sp-2);
  padding: var(--sp-3);
  border-top: 1px solid var(--border);
  flex-shrink: 0;
}

.artcor-chat-input {
  flex: 1;
  min-width: 0;
  background: var(--surface-alt);
  border: 1px solid var(--border);
  border-radius: var(--radius-control);
  padding: 8px 10px;
  color: var(--text);
  font: inherit;
  font-size: 13px;
}

.artcor-chat-input:disabled { opacity: 0.5; }

@media (max-width: 560px) {
  .artcor-launcher { right: var(--sp-3); bottom: var(--sp-3); width: 50px; height: 50px; }
  .artcor-chat-panel {
    right: var(--sp-2);
    left: var(--sp-2);
    width: auto;
    max-width: none;
    bottom: calc(50px + var(--sp-3) + var(--sp-2));
  }
}
