/* ==========================================================================
   Orvayo — Public Marketing Site — Design System
   Internal preview only (not yet published) — see index.html banner.
   Vanilla CSS, no framework/build step, mobile-first.
   ========================================================================== */

:root {
  --color-ink-950: #0a0e14;
  --color-ink-900: #11161f;
  --color-ink-800: #1a212d;
  --color-ink-700: #2a3342;
  --color-ink-500: #5c6779;
  --color-ink-300: #9aa4b2;
  --color-ink-100: #e4e7ec;
  --color-ink-50:  #f6f7f9;
  --color-surface: #fbfbfd;
  --color-white: #ffffff;

  /* Confident indigo/blue -- distinct from client-project palettes,
     conventional "trustworthy B2B tech" signal without being generic SaaS
     purple. Used deliberately, one accent only. */
  --color-accent-900: #14225c;
  --color-accent-700: #2a3f9e;
  --color-accent-600: #3450c4;
  --color-accent-500: #4d67e0;
  /* The accent scale only ever gets darker, which leaves nothing for
     a dark ground: accent-500 on ink-950 measures 4.00:1, just under
     the 4.5:1 that 13px bold text needs. This is the same blue,
     lightened until it clears that bar (5.9:1 measured). */
  --color-accent-400: #6f88e8;
  --color-accent-100: #e7ebfc;

  --color-success: #1a8f5a;
  --color-warning: #b8790a;

  --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

  --fs-100: 0.8125rem;
  --fs-200: 0.9375rem;
  --fs-300: 1.0625rem;
  --fs-400: 1.1875rem;
  --fs-500: 1.5rem;
  --fs-600: 2rem;
  --fs-700: 2.75rem;
  --fs-800: 3.5rem;

  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 3rem;
  --space-8: 4.5rem;
  --space-9: 7rem;

  --radius-sm: 8px;
  --radius-md: 14px;
  --radius-lg: 22px;
  --radius-pill: 999px;

  --shadow-sm: 0 1px 2px rgba(10,14,20,0.06);
  --shadow-md: 0 10px 28px rgba(10,14,20,0.10);
  --shadow-lg: 0 24px 56px rgba(10,14,20,0.20);

  --container-max: 1220px;
  --motion-fast: 130ms ease;
  --motion-med: 240ms ease;
}

*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
body {
  margin: 0; font-family: var(--font-sans); font-size: var(--fs-300); line-height: 1.6;
  color: var(--color-ink-800); background: var(--color-surface); -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  /* Global safeguard, not just a local fix -- a long, slash/hyphen-heavy
     compound word (found via a real mobile Playwright overflow check on
     a service description) could recur in any future dynamic text (a
     new service, a blueprint field, a long product/company name) rather
     than just this one place. */
  overflow-wrap: break-word;
}
img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
ul { list-style: none; margin: 0; padding: 0; }
button { font: inherit; cursor: pointer; }
input, textarea, select { font: inherit; }
h1, h2, h3, h4 { margin: 0; font-weight: 800; letter-spacing: -0.015em; }
p { margin: 0; }

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

:focus-visible { outline: 2px solid var(--color-accent-500); outline-offset: 2px; border-radius: 2px; }
.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}
.skip-link {
  position: absolute; left: 8px; top: -48px; background: var(--color-ink-950); color: #fff;
  padding: 10px 16px; border-radius: var(--radius-sm); z-index: 200; transition: top var(--motion-fast);
}
.skip-link:focus { top: 8px; }

.container { max-width: var(--container-max); margin: 0 auto; padding: 0 var(--space-4); }
@media (min-width: 768px) { .container { padding: 0 var(--space-6); } }
.container--prose { max-width: 780px; }

.section { padding: var(--space-8) 0; scroll-margin-top: calc(69px + var(--space-6)); }
.section--dark { background: var(--color-ink-950); color: var(--color-ink-100); }
.section--tint { background: var(--color-ink-50); }
.section-eyebrow {
  display: inline-block; font-size: var(--fs-100); font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.08em; color: var(--color-accent-600); margin-bottom: var(--space-3);
}
.section--dark .section-eyebrow { color: var(--color-accent-400); }
.section-title { font-size: var(--fs-600); max-width: 32ch; }
.section-lede { font-size: var(--fs-400); color: var(--color-ink-500); max-width: 62ch; margin-top: var(--space-3); }
.section--dark .section-lede { color: var(--color-ink-300); }
.section-head { margin-bottom: var(--space-7); }

/* ---------- Spacing/type utilities -----------------------------------
   Real bug found live (Playwright console check, not just reading the
   code): every one of these values used to be an inline style="..."
   attribute -- silently blocked by this deployment's CSP
   (default-src 'self', no style-src exception), so real, intended
   spacing/type never actually applied. Named after the exact
   --fs-*/--space-* tokens above (single source of truth), only the
   values genuinely used across the site -- never the full
   combinatorial set. */
.fs-400 { font-size: var(--fs-400); }
.fs-500 { font-size: var(--fs-500); }
.fs-600 { font-size: var(--fs-600); }
/* Same real mobile-overflow fix as .hero h1 above -- this utility's
   one real usage (knowledge-base.html's H1 "Wissensdatenbank") broke
   mid-word on a narrow viewport for the exact same reason. */
.fs-700 { font-size: clamp(1.75rem, 6vw, var(--fs-700)); }
.mb-2 { margin-bottom: var(--space-2); }
.mb-3 { margin-bottom: var(--space-3); }
.mb-4 { margin-bottom: var(--space-4); }
.mb-6 { margin-bottom: var(--space-6); }
.mt-3 { margin-top: var(--space-3); }
.mt-4 { margin-top: var(--space-4); }
.mt-6 { margin-top: var(--space-6); }
.mt-7 { margin-top: var(--space-7); }
.my-3 { margin: var(--space-3) 0; }
.hidden { display: none !important; }
/* configurator.html: a single-column, narrower variant of the shared
   .contact-card -- the wizard reads better centered and narrow than
   the two-column contact-grid layout. */
.contact-card--narrow { max-width: 720px; margin: 0 auto; }
.contact-field select {
  width: 100%; border: 1.5px solid var(--color-ink-100); border-radius: var(--radius-sm); padding: 12px 14px; background: var(--color-ink-50);
}
/* Real goal-selection checkboxes (Smart Solution Finder) -- each
   option maps 1:1 to a real packageConfiguratorService.CAPABILITIES
   key, never an invented capability. */
.cfg-goal-grid { display: grid; grid-template-columns: 1fr; gap: var(--space-2); }
@media (min-width: 640px) { .cfg-goal-grid { grid-template-columns: 1fr 1fr; } }
.cfg-goal-option {
  display: flex; align-items: center; gap: var(--space-2); border: 1.5px solid var(--color-ink-100); border-radius: var(--radius-sm);
  padding: 10px 14px; background: var(--color-ink-50); cursor: pointer;
}
.cfg-goal-option input { flex-shrink: 0; }
.cfg-tier-card {
  border: 1.5px solid var(--color-ink-100); border-radius: var(--radius-sm); padding: var(--space-4); margin-bottom: var(--space-3);
}
.cfg-tier-card h3 { margin-bottom: var(--space-2); }
.cfg-tier-card .btn { margin-top: var(--space-2); }
/* Real, reused layout pattern (wrapping tag/chip rows), not a bare
   spacing value -- a semantic class, not another utility. */
.tag-row { display: flex; flex-wrap: wrap; gap: var(--space-2); justify-content: center; }
/* Real, single-purpose component (service.html/industry.html's own
   breadcrumb trail) -- a real named component, not a generic spacing
   utility, same reasoning as .tag-row above. */
.breadcrumbs { margin-bottom: var(--space-5); font-size: var(--fs-100); color: var(--color-ink-500); }

/* ---------- Preview banner ---------- */
.preview-banner {
  background: var(--color-ink-950); color: var(--color-ink-100); text-align: center;
  font-size: var(--fs-100); padding: 8px var(--space-3);
}
.preview-banner strong { color: #ffb020; }

/* ---------- Header ---------- */
.site-header {
  position: sticky; top: 0; z-index: 100; background: rgba(251,251,253,0.9);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--color-ink-100);
}
.site-header__inner { display: flex; align-items: center; gap: var(--space-4); height: 68px; }
.site-logo { display: inline-flex; align-items: center; gap: 10px; font-size: var(--fs-500); font-weight: 800; letter-spacing: -0.03em; color: var(--color-ink-950); }
/* Wordmark is monochrome by brand rule -- the "ayo" span inherits the
   parent's color instead of an accent color, so it stays one solid
   color per surface (ink-950 in the header, #fff in the footer below). */
.site-logo span { color: inherit; }
/* Real bug fixed (2026-09-12, reported by the Owner): .site-logo is a
   flex container with gap:10px so the badge sits clear of the wordmark.
   The wordmark was written as a bare "orv" text node followed by
   <span>ayo</span>, which makes them TWO flex items -- so the 10px gap
   landed inside the word and the brand rendered as "orv ayo".
   Measured at exactly 10.00px in a real browser before the fix.
   Wrapping the letters in one element makes the wordmark a single flex
   item; the gap now only separates badge from word, which is its job. */
.site-logo__word { display: inline; white-space: nowrap; }
/* The real orvayo-symbol.png asset (assets/brand/source, imported
   2026-08-23) ships with a solid black background, not transparent --
   this chip is a real, deliberate CSS frame (never image editing) so
   its square corners disappear into a matching dark badge instead of
   showing a visible black box on this header's light surface. */
.site-logo__badge {
  display: inline-flex; flex-shrink: 0; background: var(--color-ink-950); border-radius: var(--radius-sm); padding: 5px; line-height: 0;
}
.site-logo__badge img { display: block; width: 32px; height: 32px; border-radius: 4px; }
.site-nav { display: none; }
.site-header__actions { margin-left: auto; display: flex; align-items: center; gap: var(--space-3); }
.lang-switch {
  font-size: var(--fs-100); font-weight: 700; color: var(--color-ink-500); text-decoration: none;
  padding: 0.4rem 0.6rem; border-radius: var(--radius-sm); border: 1px solid var(--color-ink-100);
}
.lang-switch:hover { color: var(--color-ink-900); border-color: var(--color-ink-300); background: var(--color-ink-50); }
.mobile-nav .lang-switch { border: none; padding: var(--space-3) 0; }
.menu-btn {
  display: inline-flex; width: 44px; height: 44px; align-items: center; justify-content: center;
  background: none; border: none; border-radius: var(--radius-sm); color: var(--color-ink-900);
}
/* Real bug found during Website VNext Wave 2 visual QA (directive's
   own 375x812 viewport, narrower than the 390px width every earlier
   round tested at): logo + "Erstgespräch anfragen" CTA + hamburger
   together overflow the header below ~420px, wrapping the CTA's text
   onto two lines and visually overlapping the logo/menu button. The
   CTA stays reachable via the mobile nav drawer's own "Kontakt" link
   -- hiding it here removes the overlap without removing the action. */
/* 420 was measured at the widths that existed when it was written --
   375 and 390. Re-measured 2026-09-14 across the widths phones
   actually are now: at 421px the two buttons reappear and the header
   needs 510px of room (German; 446px in English), so every device
   between 421 and roughly 520 -- iPhone 14/15/16 Pro Max at 430,
   Pixel at 412 in landscape-ish widths, every foldable -- scrolled
   sideways, with the header itself hanging off the right edge. The
   threshold now sits above the widest measured requirement in either
   language rather than just above the narrowest phone that was tested
   once. */
@media (max-width: 559px) {
  .site-header__actions .btn { display: none; }
}
/* Same measurement, the other end. The desktop navigation used to
   switch on at 960px, where it needs 1197px (German) -- so 960 to 1199
   was broken by construction: an iPad in landscape (1024) and every
   1152/1180 laptop got a header wider than the window. Rather than
   push the whole navigation up to 1200 and hand a hamburger to
   ordinary laptops, the mid range gets a tighter nav and drops the
   secondary button, which is what actually makes it fit; the full
   spacing returns at 1280 where there is room for it. */
@media (min-width: 960px) {
  .menu-btn { display: none; }
  .site-nav { display: flex; gap: var(--space-6); margin-left: var(--space-6); }
  .site-nav a { font-size: var(--fs-200); font-weight: 600; color: var(--color-ink-700); }
  .site-nav a:hover { color: var(--color-accent-700); }
}
@media (min-width: 960px) and (max-width: 1279px) {
  .site-nav { gap: var(--space-4); margin-left: var(--space-4); }
  /* Tried and reverted 2026-09-14: `white-space: nowrap` on these,
     so "Ueber Orvayo" and "Erstgespraech anfragen" would stop
     wrapping to a second line at 1024. It measured 973px of content
     in a 960px window and 1123 in 1100 -- the wrapping IS what makes
     the header fit in this range. A slightly taller header is the
     price of not scrolling sideways, and it is the right way round. */
  .site-nav a { font-size: var(--fs-100); }
}
/* The "Kundenbereich"/"Client area" link is the one header action a
   visitor who already has an account goes looking for, and it is also
   in the footer; the primary CTA is the one a first-time visitor
   needs in front of them. Below 1100 there is only room for one. */
@media (min-width: 960px) and (max-width: 1099px) {
  .site-header__actions .btn--outline { display: none; }
}

/* From 1280 the navigation gets its full spacing back (the rule above
   this one), and at that spacing the longest German entry -- "Kleine
   Loesungen", which joined the navigation on 2026-09-18 when the site
   was given one shared header -- broke onto a second line at every
   width, including 1920, because the header container stops growing at
   1220px. Measured in a real browser at 1280/1366/1440/1920: with
   `nowrap` alone the header content is 44px wider than the container
   (and pushes the whole page sideways at 1280); with `nowrap` and this
   gap it is 0px over at all four, every entry on one line. Deliberately
   NOT applied below 1280 -- there the 2026-09-14 measurement stands and
   the wrapping is what makes the header fit at all. */
@media (min-width: 1280px) {
  .site-nav { gap: var(--space-5); }
  .site-nav a { white-space: nowrap; }
}

.mobile-nav { position: fixed; inset: 0; z-index: 150; background: rgba(10,14,20,0.5); display: none; }
.mobile-nav.is-open { display: block; }
/* Real functional bug found live (not just a cosmetic CSP console
   warning): script.js used to set document.body.style.overflow =
   "hidden" directly to lock background scroll while this drawer is
   open -- silently blocked by the CSP, so the page behind the open
   mobile menu genuinely still scrolled. Toggled as a class instead. */
body.no-scroll { overflow: hidden; }
.mobile-nav__panel {
  position: absolute; top: 0; right: 0; bottom: 0; width: min(320px, 86vw); background: #fff;
  padding: var(--space-5) var(--space-4); box-shadow: var(--shadow-lg); overflow-y: auto;
}
.mobile-nav__header { display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--space-5); }
.mobile-nav__close { width: 40px; height: 40px; border: none; background: var(--color-ink-50); border-radius: var(--radius-sm); }
.mobile-nav a { display: block; padding: var(--space-3) 0; font-weight: 700; font-size: var(--fs-300); border-bottom: 1px solid var(--color-ink-100); }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
  padding: 0.9rem 1.7rem; border-radius: var(--radius-pill); font-weight: 700; font-size: var(--fs-200);
  border: 1.5px solid transparent; min-height: 48px; transition: transform var(--motion-fast), background var(--motion-fast), border-color var(--motion-fast);
}
.btn:active { transform: scale(0.97); }
.btn--primary { background: var(--color-accent-600); color: #fff; }
.btn--primary:hover { background: var(--color-accent-700); }
.btn--dark { background: var(--color-ink-950); color: #fff; }
.btn--dark:hover { background: var(--color-ink-800); }
.btn--outline { background: transparent; border-color: var(--color-ink-300); color: var(--color-ink-900); }
.btn--outline:hover { border-color: var(--color-ink-900); background: var(--color-ink-50); }
.btn--outline-on-dark { background: transparent; border-color: rgba(255,255,255,0.3); color: #fff; }
.btn--outline-on-dark:hover { border-color: #fff; background: rgba(255,255,255,0.08); }
.btn--block { width: 100%; }
.btn--sm { padding: 0.6rem 1.2rem; min-height: 38px; font-size: var(--fs-100); }

/* ---------- Hero ---------- */
.hero {
  position: relative; overflow: hidden;
  background: radial-gradient(120% 130% at 80% -10%, #1c2c66 0%, var(--color-ink-950) 55%), var(--color-ink-950);
  color: #fff; padding: var(--space-9) 0 var(--space-8);
}
.hero::before {
  content: ""; position: absolute; inset: 0; opacity: 0.5; pointer-events: none;
  background-image: radial-gradient(rgba(255,255,255,0.06) 1px, transparent 1px); background-size: 24px 24px;
  mask-image: linear-gradient(180deg, rgba(0,0,0,0.9), transparent 70%);
}
.hero__inner { position: relative; display: grid; gap: var(--space-7); align-items: center; }
.hero__inner > * { min-width: 0; }
.hero__eyebrow {
  display: inline-flex; align-items: center; gap: var(--space-2); font-size: var(--fs-100); font-weight: 700;
  color: var(--color-accent-500); text-transform: uppercase; letter-spacing: 0.08em; margin-bottom: var(--space-4);
}
/* Real bug found live via a fresh mobile screenshot (Website VNext 2.0
   pass), not visible from source alone: the fixed --fs-800 (3.5rem)
   had no mobile-specific reduction anywhere, so a real German compound
   word ("Betriebssystem") overflowed a narrow viewport and got broken
   mid-word by the global overflow-wrap safeguard -- exactly the kind
   of break that safeguard exists to prevent layout breakage from, but
   still looks unprofessional on the single most prominent headline on
   the page. clamp() keeps the same real 3.5rem on desktop while
   scaling fluidly down on narrow viewports so real words wrap at real
   word boundaries instead. */
.hero h1 { font-size: clamp(2rem, 6vw, var(--fs-800)); line-height: 1.05; max-width: 16ch; }
.hero p.lede { font-size: var(--fs-400); color: var(--color-ink-300); max-width: 50ch; margin: var(--space-5) 0 var(--space-6); }
.hero__ctas { display: flex; flex-wrap: wrap; gap: var(--space-3); }
.hero__proof { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-6); margin-top: var(--space-7); border-top: 1px solid rgba(255,255,255,0.12); padding-top: var(--space-5); }
.hero__proof-item { min-width: 140px; }
.hero__proof-num { font-size: var(--fs-600); font-weight: 800; color: #fff; }
.hero__proof-label { font-size: var(--fs-100); color: var(--color-ink-300); margin-top: 2px; }

/* ---------- Value grid ---------- */
.value-grid { display: grid; gap: var(--space-5); grid-template-columns: repeat(2, 1fr); }
@media (min-width: 768px) { .value-grid { grid-template-columns: repeat(4, 1fr); } }
.value-card { min-width: 0; padding: var(--space-5); border-radius: var(--radius-md); border: 1px solid var(--color-ink-100); background: #fff; }
.value-card__icon {
  width: 40px; height: 40px; border-radius: var(--radius-sm); background: var(--color-accent-100); color: var(--color-accent-700);
  display: flex; align-items: center; justify-content: center; margin-bottom: var(--space-4);
}
.value-card h3 { font-size: var(--fs-300); margin-bottom: var(--space-2); }
.value-card p { font-size: var(--fs-200); color: var(--color-ink-500); }

/* ---------- Services ---------- */
.service-groups { display: flex; flex-direction: column; gap: var(--space-7); }
.service-group__title {
  font-size: var(--fs-100); font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--color-ink-500); margin-bottom: var(--space-4);
}
/* Flexbox, not grid: a category with a count that isn't a clean
   multiple of the column count (e.g. 5 cards at 3 columns) would
   otherwise leave a dangling empty cell in the last row -- flex-grow
   lets the last row's real cards stretch to fill the row instead. */
.service-grid { display: flex; flex-wrap: wrap; gap: var(--space-5); }
.service-grid > .service-card { flex: 1 1 100%; }
@media (min-width: 860px) { .service-grid > .service-card { flex: 1 1 calc(50% - var(--space-5) / 2); } }
@media (min-width: 1180px) { .service-grid > .service-card { flex: 1 1 calc(33.333% - var(--space-5) * 2 / 3); } }
.service-card {
  min-width: 0; padding: var(--space-6); border-radius: var(--radius-lg); border: 1px solid var(--color-ink-100);
  background: #fff; box-shadow: var(--shadow-sm); transition: box-shadow var(--motion-fast), transform var(--motion-fast);
}
.service-card:hover { box-shadow: var(--shadow-md); transform: translateY(-2px); }
.service-card__badge {
  display: inline-flex; font-size: 11px; font-weight: 700; padding: 4px 10px; border-radius: var(--radius-pill);
  background: var(--color-accent-100); color: var(--color-accent-700); margin-bottom: var(--space-4);
}
.service-card h3 { font-size: var(--fs-400); margin-bottom: var(--space-3); }
.service-card h3 a { color: inherit; }
.service-card h3 a:hover, .service-card h3 a:focus-visible { color: var(--color-accent-700); }
.service-card p { color: var(--color-ink-500); margin-bottom: var(--space-4); overflow-wrap: break-word; }
.service-card h3 { overflow-wrap: break-word; }
.service-card ul { display: flex; flex-direction: column; gap: var(--space-2); }
.service-card li { font-size: var(--fs-200); color: var(--color-ink-700); display: flex; gap: var(--space-2); align-items: flex-start; }
.service-card li::before { content: "✓"; color: var(--color-accent-600); font-weight: 800; flex-shrink: 0; }
.maturity-note { display: block; margin-top: var(--space-4); font-size: var(--fs-100); color: var(--color-ink-500); border-top: 1px solid var(--color-ink-100); padding-top: var(--space-3); }

/* ---------- Industries ---------- */
.industry-cloud { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.industry-chip {
  font-size: var(--fs-200); font-weight: 600; padding: 10px 18px; border-radius: var(--radius-pill);
  border: 1.5px solid var(--color-ink-100); background: #fff; color: var(--color-ink-700);
  display: inline-block; transition: border-color var(--motion-fast), color var(--motion-fast);
}
a.industry-chip:hover, a.industry-chip:focus-visible { border-color: var(--color-accent-600); color: var(--color-accent-700); }
.industry-chip--demo-concept { border-style: dashed; color: var(--color-ink-500); }
.hint { color: var(--color-ink-500); font-size: var(--fs-200); }

/* ---------- Cross-sell / dark CTA band (service detail pages) ---------- */
.cta-band {
  background: radial-gradient(120% 160% at 20% -10%, #1c2c66 0%, var(--color-ink-950) 60%), var(--color-ink-950);
  color: #fff; border-radius: var(--radius-lg); padding: var(--space-7) var(--space-6); text-align: center;
}
.cta-band h2 { color: #fff; }

/* ---------- Process ---------- */
.process-list { display: grid; gap: var(--space-5); grid-template-columns: 1fr; counter-reset: step; }
@media (min-width: 860px) { .process-list { grid-template-columns: repeat(5, 1fr); } }
.process-step { position: relative; min-width: 0; padding-top: var(--space-6); }
.process-step::before {
  counter-increment: step; content: counter(step); position: absolute; top: 0; left: 0;
  width: 40px; height: 40px; border-radius: 50%; background: var(--color-accent-600); color: #fff;
  display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: var(--fs-300);
}
.process-step h3 { font-size: var(--fs-300); margin-bottom: var(--space-2); }
.process-step p { font-size: var(--fs-200); color: var(--color-ink-500); }
/* The process list only ever renders inside the dark "So arbeiten
   wir" section, where ink-500 measured 3.38:1 across all five steps.
   Scoped rather than replaced, the same way .section--dark
   .section-lede already overrides the same token for the same
   reason. */
.section--dark .process-step p { color: var(--color-ink-300); }

/* ---------- Packages ---------- */
.package-grid { display: grid; gap: var(--space-5); grid-template-columns: 1fr; }
@media (min-width: 700px) { .package-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1080px) { .package-grid { grid-template-columns: repeat(3, 1fr); } }
.package-card {
  min-width: 0; border: 1px solid var(--color-ink-100); border-radius: var(--radius-lg); padding: var(--space-6);
  background: #fff; display: flex; flex-direction: column;
}
.package-card h3 { font-size: var(--fs-400); margin-bottom: var(--space-2); }
.package-card .price-note {
  font-size: var(--fs-100); font-weight: 700; color: var(--color-accent-700); background: var(--color-accent-100);
  display: inline-flex; padding: 4px 10px; border-radius: var(--radius-pill); margin-bottom: var(--space-4); width: fit-content;
}
.package-card p.desc { color: var(--color-ink-500); margin-bottom: var(--space-4); }
.package-card ul { display: flex; flex-direction: column; gap: var(--space-2); margin-bottom: var(--space-5); flex: 1; }
.package-card li { font-size: var(--fs-200); display: flex; gap: var(--space-2); align-items: flex-start; }
.package-card li::before { content: "—"; color: var(--color-ink-500); flex-shrink: 0; }

/* ---------- About ---------- */
.about-grid { display: grid; gap: var(--space-7); grid-template-columns: 1fr; }
@media (min-width: 900px) { .about-grid { grid-template-columns: 1.1fr 0.9fr; } }
.about-grid > * { min-width: 0; }
.about-list { display: flex; flex-direction: column; gap: var(--space-4); }
.about-list li { display: flex; gap: var(--space-3); align-items: flex-start; font-size: var(--fs-200); color: var(--color-ink-500); }
.about-list li::before { content: "◆"; color: var(--color-accent-500); font-size: 10px; margin-top: 8px; flex-shrink: 0; }

/* ---------- Contact ---------- */
.contact-grid { display: grid; gap: var(--space-7); grid-template-columns: 1fr; }
@media (min-width: 900px) { .contact-grid { grid-template-columns: 0.9fr 1.1fr; } }
.contact-grid > * { min-width: 0; }
.contact-card {
  min-width: 0; background: #fff; border: 1px solid var(--color-ink-100); border-radius: var(--radius-lg); padding: var(--space-6);
}
.contact-field { margin-bottom: var(--space-4); }
.contact-field label { display: block; font-size: var(--fs-100); font-weight: 700; margin-bottom: var(--space-2); color: var(--color-ink-700); }
.contact-field input, .contact-field textarea {
  width: 100%; border: 1.5px solid var(--color-ink-100); border-radius: var(--radius-sm); padding: 12px 14px; background: var(--color-ink-50);
}
.contact-field textarea { min-height: 120px; resize: vertical; }
/* Real bot honeypot (never shown to a real visitor, including
   keyboard/screen-reader users -- aria-hidden + tabindex="-1" on the
   input handle that; this positions the whole field off-screen rather
   than display:none, since some real bots specifically skip
   display:none fields when deciding what to fill in). */
.contact-field--honeypot { position: absolute; left: -9999px; top: -9999px; }
.contact-field--consent label { display: flex; align-items: flex-start; gap: var(--space-2); font-weight: 400; }
.contact-field--consent input { width: auto; margin-top: 3px; }
/* Real, optional intake fields (Website VNext directive, section
   12.1/12.2) collapsed by default -- keeps the required-fields-only
   default view exactly as lean as it already was, per the directive's
   own "keine Pflicht-Felder-Explosion" guidance, while making the
   richer data the backend already accepts genuinely reachable. */
.contact-more { margin-bottom: var(--space-4); border: 1.5px solid var(--color-ink-100); border-radius: var(--radius-sm); padding: var(--space-3) var(--space-4); }
.contact-more summary { cursor: pointer; font-size: var(--fs-100); font-weight: 700; color: var(--color-ink-700); }
.contact-more .contact-field { margin-top: var(--space-4); margin-bottom: 0; }
.contact-more .contact-field + .contact-field { margin-top: var(--space-4); }
.contact-fieldset { border: 0; padding: 0; margin: 0; }
.contact-fieldset legend { font-size: var(--fs-100); font-weight: 700; margin-bottom: var(--space-2); color: var(--color-ink-700); padding: 0; }
.contact-checkbox-group { display: flex; flex-direction: column; gap: var(--space-2); }
.contact-checkbox-group label { display: flex; align-items: center; gap: var(--space-2); font-weight: 400; font-size: var(--fs-200); color: var(--color-ink-700); }
.contact-checkbox-group input { width: auto; }
.contact-direct { display: flex; flex-direction: column; gap: var(--space-5); }
.contact-direct-item { display: flex; gap: var(--space-3); align-items: flex-start; }
.contact-next {
  margin-top: var(--space-4); padding-top: var(--space-6); border-top: 1px solid var(--color-ink-100);
}
.contact-next h3 { font-size: var(--fs-100); text-transform: uppercase; letter-spacing: 0.06em; color: var(--color-ink-500); margin-bottom: var(--space-4); }
.contact-next__list { display: flex; flex-direction: column; gap: var(--space-4); counter-reset: none; }
.contact-next__list li { display: flex; gap: var(--space-3); align-items: flex-start; font-size: var(--fs-200); color: var(--color-ink-700); }
.contact-next__list li span {
  flex-shrink: 0; width: 26px; height: 26px; border-radius: 50%; background: var(--color-accent-100); color: var(--color-accent-700);
  display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: var(--fs-100);
}
.contact-direct-icon {
  width: 40px; height: 40px; border-radius: var(--radius-sm); background: var(--color-accent-100); color: var(--color-accent-700);
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.contact-direct h3 { font-size: var(--fs-300); margin-bottom: 2px; }
.contact-direct p { color: var(--color-ink-500); font-size: var(--fs-200); }
.contact-direct a { color: var(--color-accent-700); font-weight: 700; }
.form-note { font-size: 11px; color: var(--color-ink-500); margin-top: var(--space-2); }

/* ---------- Footer ---------- */
.site-footer { background: var(--color-ink-950); color: var(--color-ink-300); padding: var(--space-8) 0 var(--space-5); }
/* Real bug found live: the default dark .site-logo color read as
   near-invisible against this footer's own dark background -- used to
   be a one-off inline style="color:#fff;" (silently blocked by the
   CSP, same class of bug as the utilities above). Scoped by context
   instead of a bare color utility, since this is a real, intentional
   "this component sits on a dark ground" override, not a generic
   white-text need. */
.site-footer .site-logo { color: #fff; }
.footer-grid { display: grid; gap: var(--space-6); grid-template-columns: repeat(2, 1fr); }
.footer-col { min-width: 0; }
@media (min-width: 768px) { .footer-grid { grid-template-columns: 1.2fr repeat(4, 1fr); } }
/* ink-500 is a colour for grey text on a WHITE ground. On this
   footer's own ink-950 it measured 3.38:1 -- below the 4.5:1 that
   13px text needs, for the heading of every footer column on all 26
   pages. ink-100 also restores the hierarchy the grey had removed:
   a column heading should read as louder than the links under it,
   not quieter. */
.footer-col h3 { font-size: var(--fs-100); text-transform: uppercase; letter-spacing: 0.06em; color: var(--color-ink-100); margin-bottom: var(--space-3); }
.footer-col li { margin-bottom: var(--space-2); font-size: var(--fs-200); }
.footer-col a:hover { color: #fff; }
.footer-brand p { max-width: 34ch; margin: var(--space-3) 0; }
.footer-bottom {
  border-top: 1px solid var(--color-ink-700); margin-top: var(--space-7); padding-top: var(--space-5);
  /* Same 3.38:1 on the same dark ground -- this is the copyright
     line and the "Preis im Erstgespraech" note. ink-300 is what the
     footer already uses for body text on this background. */
  display: flex; flex-wrap: wrap; gap: var(--space-3); justify-content: space-between; font-size: var(--fs-100); color: var(--color-ink-300);
}

.toast {
  position: fixed; bottom: 24px; left: 50%; transform: translate(-50%, 20px); background: var(--color-ink-950); color: #fff;
  padding: 12px 20px; border-radius: var(--radius-pill); font-size: var(--fs-200); box-shadow: var(--shadow-lg);
  opacity: 0; pointer-events: none; transition: opacity var(--motion-med), transform var(--motion-med); z-index: 250;
}
.toast.is-visible { opacity: 1; transform: translate(-50%, 0); }

/* ---------- FAQ ---------- */
.faq-list { max-width: 760px; margin: 0 auto; display: flex; flex-direction: column; gap: var(--space-3); }
.faq-item { border: 1px solid var(--color-ink-100); border-radius: var(--radius-md); background: #fff; padding: 0 var(--space-5); }
.faq-item summary {
  padding: var(--space-4) 0; font-weight: 700; cursor: pointer; list-style: none;
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after { content: "+"; font-size: var(--fs-500); font-weight: 400; color: var(--color-accent-600); flex-shrink: 0; transition: transform var(--motion-fast); }
.faq-item[open] summary::after { transform: rotate(45deg); }
.faq-item p { padding: 0 0 var(--space-4); color: var(--color-ink-500); max-width: 64ch; }

/* ---------- Lösungen / Use Cases (Website VNext directive, section 10) --
   same real accordion pattern as .faq-item above, richer body content. ---------- */
.use-case-list { max-width: 820px; margin: 0 auto; display: flex; flex-direction: column; gap: var(--space-4); }
/* The catalogue as it stands in the HTML itself, before the script
   replaces it with the real cards -- and permanently for anyone the
   script never reaches: a crawler that does not run JavaScript, a link
   preview, a reader with scripting off. Styled to look like the cards
   it stands in for rather than like a raw bullet list. */
.prerendered-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-4); }
.prerendered-list > li { border: 1px solid var(--color-ink-100); border-radius: var(--radius-lg); background: #fff; padding: var(--space-5) var(--space-6); }
.prerendered-list > li > h2, .prerendered-list > li > h3 { margin: 0 0 var(--space-2); }
/* The industries as they stand in the HTML: a plain row of links,
   which is all GET /api/public/blueprints returns for them anyway.
   Laid out like the chips the script replaces them with. */
.prerendered-links { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--space-2); }
.prerendered-links > li { margin: 0; }
.prerendered-list > li > p { margin: 0 0 var(--space-2); }
.prerendered-list > li > p:last-child { margin-bottom: 0; }
.use-case-card { border: 1px solid var(--color-ink-100); border-radius: var(--radius-lg); background: #fff; padding: 0 var(--space-6); }
.use-case-card summary {
  padding: var(--space-5) 0; cursor: pointer; list-style: none;
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
}
.use-case-card summary::-webkit-details-marker { display: none; }
.use-case-card summary::after { content: "+"; font-size: var(--fs-500); font-weight: 400; color: var(--color-accent-600); flex-shrink: 0; transition: transform var(--motion-fast); }
.use-case-card[open] summary::after { transform: rotate(45deg); }
.use-case-card__summary-main p { margin-top: 4px; }
.use-case-card__body { padding: 0 0 var(--space-6); max-width: 68ch; }
.use-case-card__body p { color: var(--color-ink-500); }
/* Physical product cards (2026-09-15). Only DB-backed listings carry an
   image or a price -- the three editorial products have neither, so
   these rules simply never apply to them. The image is capped rather
   than sized absolutely: a Shopify featured image arrives at whatever
   resolution the Owner uploaded. */
.product-card__image {
  display: block; max-width: 100%; height: auto; border-radius: 10px;
  margin-bottom: var(--space-4); background: var(--color-ink-100);
}
/* Scoped on purpose: a global [hidden] rule would also change ORVAYO AI's
   quick-action bar, whose display:flex currently overrides its own hidden. */
[data-product-order-variant-field][hidden] { display: none; }
.product-card__variants { color: var(--color-ink-700); margin-bottom: var(--space-2); }
.product-card__price { font-weight: 700; color: var(--color-ink-700); margin-bottom: var(--space-2); }
/* Sold out (stock tracked and at zero). Stated, never a count. */
.badge-soldout {
  display: inline-block; margin-top: var(--space-1); font-size: var(--fs-100); font-weight: 700;
  color: var(--color-ink-700); background: var(--color-ink-100); padding: 4px 10px; border-radius: var(--radius-pill);
}
.use-case-card__flow { padding-left: 20px; color: var(--color-ink-500); display: flex; flex-direction: column; gap: var(--space-2); }
.use-case-card__flow li { padding-left: var(--space-2); }
/* Directive section 10's own explicit requirement: never let an
   exemplary scenario read as a real customer reference. */
.badge-exemplary {
  display: inline-block; font-size: var(--fs-100); font-weight: 700; color: var(--color-accent-700);
  background: var(--color-accent-100); padding: 4px 10px; border-radius: var(--radius-pill);
}

/* ---------- ORVAYO AI: hero input bar ---------- */
.hero-ai { margin-top: var(--space-6); }
.hero-ai__form { display: flex; gap: var(--space-2); background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.16); border-radius: var(--radius-pill); padding: 6px 6px 6px 20px; }
.hero-ai__form input {
  flex: 1; min-width: 0; background: transparent; border: 0; color: #fff; font-size: var(--fs-200); padding: 10px 0;
}
.hero-ai__form input::placeholder { color: var(--color-ink-300); }
/* The inner input drops its own outline so the ring does not draw a
   rectangle inside a pill -- but until 2026-09-14 nothing put one back,
   so the most prominent control on the site had no visible focus at
   all. Measured by really pressing Tab: 20 stops on the homepage, 19
   of them showed the global :focus-visible ring and this one showed
   nothing. The ring moves to the pill itself, which is the shape a
   keyboard user is actually looking at. */
.hero-ai__form input:focus { outline: none; }
.hero-ai__form:focus-within { outline: 2px solid var(--color-accent-400); outline-offset: 2px; }
.hero-ai__form button { border-radius: var(--radius-pill); flex-shrink: 0; }
@media (max-width: 480px) {
  /* The pill-shaped single-row form's button never shrinks below its
     text width, so on a narrow phone viewport it and the input
     together overflow the pill and get visually clipped -- stack
     input above button instead of forcing them onto one row. */
  .hero-ai__form { flex-wrap: wrap; border-radius: var(--radius-lg); padding: var(--space-3); }
  .hero-ai__form input { flex: 1 1 100%; padding: var(--space-2) 0; }
  .hero-ai__form button { flex: 1 1 100%; }
}
.hero-ai__suggestions { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-3); }
.hero-ai__suggestion {
  font-size: var(--fs-100); color: var(--color-ink-300); background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.14);
  border-radius: var(--radius-pill); padding: 6px 14px; cursor: pointer;
}
.hero-ai__suggestion:hover { color: #fff; border-color: rgba(255,255,255,0.3); }

/* ---------- ORVAYO AI: floating assistant ---------- */
.ai-widget { position: fixed; right: var(--space-5); bottom: var(--space-5); z-index: 300; }
.ai-widget__toggle {
  width: 60px; height: 60px; border-radius: 50%; background: var(--color-accent-600); color: #fff; border: 0;
  display: flex; align-items: center; justify-content: center; box-shadow: var(--shadow-lg); transition: transform var(--motion-fast), background var(--motion-fast);
}
.ai-widget__toggle:hover { background: var(--color-accent-700); transform: scale(1.05); }
.ai-widget.is-open .ai-widget__toggle { display: none; }
.ai-widget__panel {
  display: none; position: absolute; right: 0; bottom: calc(100% + var(--space-3)); width: min(380px, calc(100vw - 2 * var(--space-5)));
  max-height: min(640px, calc(100vh - 120px)); background: #fff; border-radius: var(--radius-lg); box-shadow: var(--shadow-lg);
  border: 1px solid var(--color-ink-100); overflow: hidden; flex-direction: column;
}
.ai-widget.is-open .ai-widget__panel { display: flex; }
.ai-widget__header {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); padding: var(--space-4) var(--space-5);
  background: var(--color-ink-950); color: #fff; flex-shrink: 0;
}
.ai-widget__header-title { font-weight: 800; font-size: var(--fs-300); }
.ai-widget__header-sub { font-size: var(--fs-100); color: var(--color-ink-500); }
.ai-widget__header-actions { display: flex; gap: var(--space-2); }
.ai-widget__icon-btn { background: transparent; border: 0; color: var(--color-ink-500); padding: 6px; border-radius: var(--radius-sm); }
.ai-widget__icon-btn:hover { color: #fff; background: rgba(255,255,255,0.08); }
.ai-widget__log { flex: 1; overflow-y: auto; padding: var(--space-4) var(--space-5); display: flex; flex-direction: column; gap: var(--space-3); min-height: 200px; }
.ai-bubble { max-width: 88%; padding: 10px 14px; border-radius: var(--radius-md); font-size: var(--fs-200); line-height: 1.5; white-space: pre-line; }
.ai-bubble--assistant { align-self: flex-start; background: var(--color-ink-50); color: var(--color-ink-800); }
.ai-bubble--user { align-self: flex-end; background: var(--color-accent-600); color: #fff; }
.ai-widget__quick-actions { display: flex; flex-wrap: wrap; gap: var(--space-2); padding: 0 var(--space-5) var(--space-4); flex-shrink: 0; }
.ai-quick-action {
  font-size: var(--fs-100); border: 1px solid var(--color-ink-100); background: var(--color-ink-50); border-radius: var(--radius-pill);
  padding: 8px 14px; text-align: left;
}
.ai-quick-action:hover { border-color: var(--color-accent-500); color: var(--color-accent-700); }
/* orvayo-ai.js hides these two with the hidden attribute (no quick replies;
   the consent and summary steps). Their display:flex overrode it: an empty
   16px strip stayed, and the chat input stayed usable beside the contact
   form. Measured in a browser 2026-09-16. Scoped rather than a global
   [hidden] rule, which would change every other element on 24 pages. */
.ai-widget__quick-actions[hidden], .ai-widget__form[hidden] { display: none; }
.ai-widget__form { display: flex; gap: var(--space-2); padding: var(--space-4) var(--space-5); border-top: 1px solid var(--color-ink-100); flex-shrink: 0; }
.ai-widget__form input {
  flex: 1; min-width: 0; border: 1px solid var(--color-ink-100); border-radius: var(--radius-pill); padding: 10px 16px; font-size: var(--fs-200);
}
.ai-widget__form button { border-radius: var(--radius-pill); flex-shrink: 0; }
.ai-widget__handoff { padding: var(--space-4) var(--space-5); border-top: 1px solid var(--color-ink-100); flex-shrink: 0; overflow-y: auto; }
.ai-widget__handoff .contact-field { margin-bottom: var(--space-3); }
.ai-widget__handoff .form-note { min-height: 1.2em; }
.ai-widget__summary { padding: var(--space-4) var(--space-5); border-top: 1px solid var(--color-ink-100); flex-shrink: 0; overflow-y: auto; }
.ai-widget__summary .contact-field { margin-bottom: var(--space-3); }
.ai-widget__summary .contact-field textarea { min-height: 52px; resize: vertical; }
.ai-widget__summary-intro { font-size: var(--fs-100); color: var(--color-ink-500); margin-bottom: var(--space-3); }
.ai-widget__disclaimer { font-size: 11px; color: var(--color-ink-500); padding: 0 var(--space-5) var(--space-4); flex-shrink: 0; }

@media (max-width: 640px) {
  .ai-widget { right: var(--space-3); bottom: var(--space-3); }
  .ai-widget__panel {
    position: fixed; inset: 0; width: 100%; max-height: 100%; border-radius: 0; right: auto; bottom: auto;
  }
  body.orvayo-ai-open { overflow: hidden; }
}

.use-case-card__actions { display: flex; gap: var(--space-3); flex-wrap: wrap; align-items: center; margin-top: var(--space-4); }

/* ---------- Shop Cart (Kleine Lösungen -- real, multi-select
   Leistungsauswahl, no prices anywhere, ends in one real, combined
   Projektanfrage over /api/public/project-intake, never a payment) ---------- */
.shop-cart-toggle {
  border: 1.5px solid var(--color-ink-300); background: transparent; color: var(--color-ink-900); border-radius: var(--radius-pill);
  padding: 8px 16px; font-size: var(--fs-100); font-weight: 700; cursor: pointer;
}
.shop-cart-toggle:hover { border-color: var(--color-accent-500); color: var(--color-accent-700); }
.shop-cart-toggle.is-selected { background: var(--color-accent-600); border-color: var(--color-accent-600); color: #fff; }

.shop-cart-bar {
  position: fixed; left: 50%; bottom: var(--space-5); z-index: 280;
  background: var(--color-ink-950); color: #fff; border-radius: var(--radius-pill); box-shadow: var(--shadow-lg);
  display: flex; align-items: center; gap: var(--space-3); padding: 8px 8px 8px 20px;
  opacity: 0; pointer-events: none; transform: translate(-50%, 20px); transition: opacity var(--motion-med), transform var(--motion-med);
  max-width: calc(100vw - 2 * var(--space-4));
}
.shop-cart-bar.is-visible { opacity: 1; pointer-events: auto; transform: translate(-50%, 0); }
.shop-cart-bar__count { font-size: var(--fs-200); font-weight: 700; white-space: nowrap; }
.shop-cart-bar__clear { background: transparent; border: 0; color: var(--color-ink-300); font-size: var(--fs-100); padding: 8px 6px; cursor: pointer; }
.shop-cart-bar__clear:hover { color: #fff; }

.shop-cart-panel { display: none; position: fixed; inset: 0; z-index: 290; background: rgba(10,14,20,0.5); align-items: flex-end; justify-content: center; }
.shop-cart-panel.is-open { display: flex; }
@media (min-width: 640px) { .shop-cart-panel { align-items: center; } }
.shop-cart-panel__card {
  background: #fff; border-radius: var(--radius-lg); padding: var(--space-6); width: min(560px, calc(100vw - 2 * var(--space-4)));
  max-height: min(88vh, 760px); overflow-y: auto; position: relative;
}
.shop-cart-panel__close { position: absolute; top: var(--space-4); right: var(--space-4); background: transparent; border: 0; color: var(--color-ink-500); padding: 4px; cursor: pointer; }
.shop-cart-panel__close:hover { color: var(--color-ink-900); }
/* Web shop cart (2026-09-16), shown only when the server reports the checkout open. */
[data-cart-toggle][hidden], [data-cart-checkout][hidden] { display: none; }
.cart-toggle {
  position: fixed; left: var(--space-5); bottom: var(--space-5); z-index: 280; border: 0; cursor: pointer;
  background: var(--color-accent-600); color: #fff; font-weight: 700; padding: 12px 18px; border-radius: var(--radius-pill);
  box-shadow: 0 8px 24px rgba(10,14,20,0.18);
}
.cart-toggle:focus-visible { outline: 3px solid var(--color-accent-400); outline-offset: 2px; }
.cart-toggle__count { display: inline-block; min-width: 1.6em; margin-left: 6px; padding: 0 6px; border-radius: var(--radius-pill); background: #fff; color: var(--color-accent-700); }
.cart-line__main { display: grid; gap: 2px; min-width: 0; }
.cart-line__meta { font-size: var(--fs-100); color: var(--color-ink-500); }
.cart-line__unavailable { font-size: var(--fs-100); color: var(--color-warning); font-weight: 700; }
.cart-line__controls { display: flex; align-items: center; gap: var(--space-2); flex-shrink: 0; }
.cart-line__controls input { width: 4.5em; padding: 6px; border: 1px solid var(--color-ink-100); border-radius: var(--radius-sm); }
.cart-line__remove { background: transparent; border: 0; color: var(--color-ink-500); cursor: pointer; text-decoration: underline; }
.cart-subtotal { font-weight: 700; text-align: right; margin-bottom: var(--space-3); }
.cart-address-row { display: grid; grid-template-columns: minmax(6em, 1fr) 2fr; gap: var(--space-3); }
.product-card__cart { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; }
.product-card__cart select { padding: 8px; border: 1px solid var(--color-ink-100); border-radius: var(--radius-sm); }
.shop-cart-panel__items { list-style: none; padding: 0; margin: var(--space-3) 0 var(--space-4); display: flex; flex-direction: column; gap: var(--space-2); }
.shop-cart-panel__items li { display: flex; justify-content: space-between; align-items: center; gap: var(--space-3); font-size: var(--fs-200); border-bottom: 1px solid var(--color-ink-100); padding-bottom: var(--space-2); }
.shop-cart-panel__items button { background: transparent; border: 0; color: var(--color-ink-500); font-size: var(--fs-100); cursor: pointer; }
.shop-cart-panel__items button:hover { color: var(--color-accent-700); }
.shop-cart-panel__empty { color: var(--color-ink-500); font-size: var(--fs-200); }

/* ---------- 404 ---------- */
.not-found { padding: var(--space-9) 0; text-align: center; }
.not-found__inner { max-width: 560px; margin: 0 auto; }
.not-found .section-title { margin: var(--space-4) 0; }
.not-found .section-lede { margin: 0 auto var(--space-6); }
.not-found__actions { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--space-3); }

/* ---------- Demo Center ---------- */
/* Flexbox, not grid: the real demo count rarely divides evenly by the
   column count, so a fixed grid leaves a dangling empty cell (or a
   single orphaned card) in the last row -- flex-grow lets the last
   row's real cards stretch to fill it instead (same fix as .service-grid). */
.demo-grid { display: flex; flex-wrap: wrap; gap: var(--space-5); }
.demo-grid > .demo-card { flex: 1 1 100%; }
@media (min-width: 700px) { .demo-grid > .demo-card { flex: 1 1 calc(50% - var(--space-5) / 2); } }
@media (min-width: 1080px) { .demo-grid > .demo-card { flex: 1 1 calc(33.333% - var(--space-5) * 2 / 3); } }
.demo-card { min-width: 0; border: 1px solid var(--color-ink-100); border-radius: var(--radius-lg); padding: var(--space-6); background: #fff; display: flex; flex-direction: column; }
.demo-card__badge { font-size: var(--fs-100); font-weight: 700; color: var(--color-accent-700); background: var(--color-accent-100); display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; border-radius: var(--radius-pill); margin-bottom: var(--space-4); width: fit-content; }
.demo-card__badge.soon { color: var(--color-ink-500); background: var(--color-ink-50); }
.demo-card__meta { font-size: var(--fs-100); color: var(--color-ink-500); margin-bottom: var(--space-3); }
.demo-card h3 { font-size: var(--fs-400); margin-bottom: var(--space-2); }
.demo-card p.desc { color: var(--color-ink-500); margin-bottom: var(--space-4); flex: 1; }
.section-cta-row { text-align: center; margin-top: var(--space-6); }

.demo-wizard { max-width: 640px; margin: 0 auto; background: #fff; border: 1px solid var(--color-ink-100); border-radius: var(--radius-lg); padding: var(--space-6); }
.demo-wizard__progress { display: flex; gap: 6px; margin-bottom: var(--space-6); }
.demo-wizard__progress span { flex: 1; height: 4px; border-radius: var(--radius-pill); background: var(--color-ink-100); }
.demo-wizard__progress span.is-done { background: var(--color-accent-600); }
.demo-wizard__step { display: none; }
.demo-wizard__step.is-active { display: block; }
.demo-wizard__step h2 { font-size: var(--fs-500); margin-bottom: var(--space-2); }
.demo-wizard__step p.hint { color: var(--color-ink-500); margin-bottom: var(--space-5); }
.demo-wizard__choices { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-bottom: var(--space-4); }
.demo-choice { border: 1px solid var(--color-ink-100); border-radius: var(--radius-pill); padding: 10px 18px; font-size: var(--fs-200); background: #fff; }
.demo-choice.is-selected { border-color: var(--color-accent-600); background: var(--color-accent-100); color: var(--color-accent-700); font-weight: 700; }
.demo-wizard__actions { display: flex; justify-content: space-between; gap: var(--space-3); margin-top: var(--space-6); }
.demo-summary dl { display: grid; grid-template-columns: minmax(140px, 220px) 1fr; gap: var(--space-2) var(--space-4); margin-bottom: var(--space-5); }
.demo-summary dt { font-weight: 700; color: var(--color-ink-700); font-size: var(--fs-200); }
.demo-summary dd { margin: 0; color: var(--color-ink-500); font-size: var(--fs-200); }
.demo-note { font-size: var(--fs-100); color: var(--color-ink-500); background: var(--color-ink-50); border-radius: var(--radius-sm); padding: var(--space-3) var(--space-4); margin-bottom: var(--space-5); }
.pi-blueprint { margin-top: var(--space-6); padding: var(--space-5); border: 1px solid var(--color-ink-100); border-radius: var(--radius-lg); background: var(--color-ink-50); }
.pi-blueprint h3 { margin-top: 0; }
.pi-blueprint h4 { font-size: var(--fs-200); margin: var(--space-4) 0 var(--space-1); color: var(--color-ink-700); }
.pi-blueprint p, .pi-blueprint ul { margin: 0 0 var(--space-2); font-size: var(--fs-200); color: var(--color-ink-500); }
.pi-blueprint ul { padding-left: var(--space-5); }
.pi-blueprint__note { font-style: italic; margin-top: var(--space-4); }
.contact-alt-path { margin-top: var(--space-4); }

/* Directive Phase 121: browser print styling for the Project
   Blueprint -- a visitor can Ctrl/Cmd+P to save it as a PDF locally.
   No server-side PDF generation, no sensitive data added -- prints
   exactly what's already on screen. */
@media print {
  .site-header, .mobile-nav, .site-footer, .ai-widget, .toast,
  .demo-wizard__progress, .demo-wizard__actions, [data-pi-summary] { display: none !important; }
  .pi-blueprint { border: none; background: none; padding: 0; }
}

/* Order lookup (2026-09-16). */
.order-status[hidden] { display: none; }
.order-status__form { display: grid; grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr)); gap: .75rem 1rem; align-items: end; max-width: 48rem; }
.order-status__result dl { display: grid; grid-template-columns: max-content 1fr; gap: .35rem 1rem; margin: 1rem 0 0; max-width: 40rem; }
.order-status__result dt { font-weight: 600; }
.order-status__result dd { margin: 0; overflow-wrap: anywhere; }
.order-status__form .contact-field { margin-bottom: 0; }

/* Price and photo before the card is opened (2026-09-17): comparing
   products should not mean opening every one. */
.use-case-card summary { justify-content: flex-start; }
.use-case-card summary::after { margin-left: auto; }
.product-card__thumb { width: 56px; height: 56px; object-fit: cover; border-radius: 8px; flex-shrink: 0; background: var(--color-ink-100); }
.product-card__summary-price { font-weight: 700; color: var(--color-ink-700); }
@media (max-width: 480px) { .product-card__thumb { width: 44px; height: 44px; } }

/* Links in an ORVAYO AI answer (2026-09-17): product cards, order lookup. */
.ai-bubble__links { list-style: none; margin: 8px 0 0; padding: 0; display: flex; flex-direction: column; gap: 4px; white-space: normal; }
.ai-bubble__links a { color: var(--color-accent-700); font-weight: 600; text-decoration: underline; text-underline-offset: 2px; }

/* Discount code in the cart (2026-09-17). */
.cart-discount { display: flex; flex-wrap: wrap; gap: 8px; align-items: flex-end; margin: 12px 0 4px; }
.cart-discount label { flex-basis: 100%; font-size: var(--fs-200); font-weight: 600; }
.cart-discount input { flex: 1 1 10rem; min-width: 0; padding: 10px 12px; border: 1px solid var(--color-ink-200, #d6dee8); border-radius: var(--radius-md); font: inherit; text-transform: uppercase; }
