/* ==========================================================================
   AbbasiMarkets — Design System
   One font family (Inter) throughout, one defined palette, reusable
   components. Edit tokens in :root to re-theme the whole site.
   ========================================================================== */

:root {
  /* Color tokens */
  --color-ink: #14181d;           /* primary text */
  --color-ink-soft: #4b5563;      /* secondary text */
  --color-bg: #f6f7f5;            /* main background */
  --color-surface: #ffffff;       /* card / header background */
  --color-border: #e2e5e1;
  --color-primary: #1e3a5f;       /* brand navy */
  --color-primary-dark: #14283f;
  --color-accent: #7a8699;        /* silver / graphite — CTA */
  --color-accent-dark: #5f6773;
  --color-accent-soft: #c9ced6;
  --color-accent-bg: #eef0f3;
  --color-success: #2f7a4f;
  --color-danger: #b3261e;

  /* Type */
  --font-base: "Inter", "Inter Fallback", -apple-system, BlinkMacSystemFont,
    "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-serif: "Newsreader", Georgia, "Times New Roman", serif;

  --step-xs: 0.8125rem;   /* 13px */
  --step-sm: 0.9375rem;   /* 15px */
  --step-base: 1rem;      /* 16px */
  --step-md: 1.125rem;    /* 18px */
  --step-lg: 1.375rem;    /* 22px */
  --step-xl: 1.75rem;     /* 28px */
  --step-2xl: 2.25rem;    /* 36px */
  --step-3xl: 3rem;       /* 48px */

  /* Semantic state colors. Every "tinted surface" (a badge fill, a status
     pill background, a notice banner) below is expressed as a soft
     rgba() derived from these three base colors, rather than each
     component hand-picking its own unrelated red/green/amber — that drift
     (e.g. a badge using #fee2e2 while a status pill for the same meaning
     used rgba(217,83,79,.15)) was audited and is being retired here. */
  --color-warning: #a16b00;       /* small bold labels on a warning tint */
  --color-warning-ink: #6b4a05;   /* body copy on a warning tint (more contrast) */
  --color-danger-bg: rgba(179, 38, 30, 0.1);
  --color-danger-border: rgba(179, 38, 30, 0.35);
  --color-success-bg: rgba(47, 122, 79, 0.12);
  --color-warning-bg: rgba(161, 107, 0, 0.16);
  --color-warning-border: rgba(161, 107, 0, 0.4);

  /* Spacing scale. Nothing in this file was pulled from a scale before —
     margins/gaps/padding were each chosen by eye per component, which is
     part of why similar components (status pills, card padding) ended up
     with slightly different numbers for no reason. New/touched rules
     should reference this; existing rules are migrated incrementally
     rather than all at once (a wholesale renumbering of ~100 existing
     values is its own visual-regression risk for no visible benefit). */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-7: 32px;
  --space-8: 40px;
  --space-9: 48px;
  --space-10: 56px;
  --space-11: 64px;

  /* Layout */
  --container-max: 1240px;
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-pill: 999px;
  --shadow-card: 0 1px 2px rgba(20, 24, 29, 0.06), 0 1px 1px rgba(20, 24, 29, 0.04);
  --shadow-card-hover: 0 8px 20px rgba(20, 24, 29, 0.08);
}

/* Fallback metric-matched face to avoid layout shift while Inter loads */
@font-face {
  font-family: "Inter Fallback";
  src: local("Arial");
  size-adjust: 107%;
  ascent-override: 90%;
  descent-override: 22%;
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  font-family: var(--font-base);
  font-size: var(--step-base);
  line-height: 1.55;
  color: var(--color-ink);
  background: var(--color-bg);
  -webkit-font-smoothing: antialiased;
}
img { max-width: 100%; display: block; }

a { color: inherit; text-decoration: none; }

.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; }
a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible, [tabindex]:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

h1, h2, h3, h4 { font-family: var(--font-serif); font-weight: 600; line-height: 1.2; margin: 0 0 0.5em; letter-spacing: -0.01em; }
h1 { font-size: var(--step-3xl); }
h2 { font-size: var(--step-2xl); }
h3 { font-size: var(--step-lg); }
h4 { font-size: var(--step-md); }
p { margin: 0 0 1em; color: var(--color-ink-soft); }

.container { max-width: var(--container-max); margin: 0 auto; padding: 0 20px; }
/* padding-top/bottom only (never the `padding: Xpx 0` shorthand) — that
   shorthand also sets padding-left/right to 0, which silently cancels the
   side padding .container just set on any element carrying both classes
   (e.g. <section class="section container">). On desktop this was
   invisible (the container is centered with huge margin outside it either
   way); on a phone, where the container IS the full viewport width, it
   made every section's text and images run flush to the screen edges. */
.section { padding-top: 56px; padding-bottom: 56px; }
.section-head { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; margin-bottom: 28px; flex-wrap: wrap; }
.eyebrow { font-family: var(--font-base); font-size: var(--step-xs); font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--color-primary); margin-bottom: 8px; display: block; }

/* Buttons */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; border-radius: var(--radius-sm); font-weight: 600; font-size: var(--step-sm); padding: 12px 22px; border: 1px solid transparent; cursor: pointer; transition: transform 0.12s ease, box-shadow 0.12s ease, background-color 0.12s ease; }
.btn:hover { transform: translateY(-1px); }
.btn-primary { background: var(--color-primary); color: #fff; }
.btn-primary:hover { background: var(--color-primary-dark); }
.btn-accent { background: var(--color-accent); color: #fff; }
.btn-accent:hover { background: var(--color-accent-dark); }
.btn-outline { background: transparent; color: var(--color-primary); border-color: var(--color-primary); }
.btn-outline:hover { background: rgba(30, 58, 95, 0.06); }
.btn-block { width: 100%; }
.btn[disabled] { opacity: 0.5; cursor: not-allowed; transform: none; }

/* Shared "text input" look — previously defined independently six times
   (form-row inputs/textarea, the split checkout fields, the qty stepper,
   the variant picker, the promo code field/select, the toolbar's search+sort)
   with one copy already drifted to 9px vertical padding instead of 10px.
   One rule now, with each selector below trimmed to only its own extras. */
.form-row input, .form-row textarea, .form-row--split input,
.add-to-cart-qty, .variant-select, .checkout-promo-row input,
.checkout-promo-select, .toolbar select, .toolbar input[type="search"] {
  font: inherit; padding: 10px 12px; border: 1px solid var(--color-border);
  border-radius: var(--radius-sm); background: var(--color-surface); color: var(--color-ink);
}

/* Header — three stacked rows sharing one .container width (see
   scripts/partials.js's header()): a slim utility bar, the main shopping
   row, and a dedicated primary-nav row. Replaces the previous single-row
   header that packed logo + nav + search + eBay pill + social + language +
   cart into one line and had to hide most of it below 1240px just to avoid
   horizontal overflow. */
.site-header { position: sticky; top: 0; z-index: 40; background: var(--color-surface); }

/* Row 1 — utility bar: small type, muted on a dark ground, so it never
   competes with the shopping row below it. */
.site-topbar { background: var(--color-primary); }
.site-topbar__inner { display: flex; align-items: center; justify-content: space-between; gap: 20px; padding: 7px 20px; font-size: var(--step-xs); }
.site-topbar__tagline { color: rgba(255, 255, 255, 0.88); font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.site-topbar__actions { display: flex; align-items: center; gap: 20px; flex-shrink: 0; }
.site-topbar__link { color: rgba(255, 255, 255, 0.88); font-weight: 500; white-space: nowrap; }
.site-topbar__link:hover, .site-topbar__link:focus-visible { color: #fff; text-decoration: underline; }
.site-topbar .social-icons__link { width: 26px; height: 26px; border-color: rgba(255, 255, 255, 0.32); color: rgba(255, 255, 255, 0.85); }
.site-topbar .social-icons__link svg { width: 13px; height: 13px; }
.site-topbar .social-icons__link:hover, .site-topbar .social-icons__link:focus-visible { background: #fff; border-color: #fff; color: var(--color-primary); }
.site-topbar .lang-switcher { color: rgba(255, 255, 255, 0.88); }
.site-topbar .lang-switcher__select {
  color: #fff; border-color: rgba(255, 255, 255, 0.4);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6' fill='none' stroke='%23ffffff' stroke-width='1.6'%3E%3Cpath d='M1 1l4 4 4-4'/%3E%3C/svg%3E");
}
.site-topbar .lang-switcher__select:hover, .site-topbar .lang-switcher__select:focus-visible { border-color: #fff; }

/* Row 2 — main shopping row: logo (left), a large centered search bar with
   a sensible max width, and the account-actions cluster (right). Generous
   gaps between the three groups is the point — see the brief this was
   built from — rather than lining everything up edge to edge. There's no
   account/wishlist entry point here because none exists on the site yet
   (guest checkout only); this cluster only surfaces what's actually live. */
.site-header-main { border-bottom: 1px solid var(--color-border); }
.header-main-inner { display: flex; align-items: center; gap: 32px; padding: 18px 20px; }
.logo { display: flex; align-items: center; flex-shrink: 0; }
.logo img { height: 48px; width: auto; }
.header-main-inner .search-form {
  display: flex; align-items: center; background: var(--color-bg); border: 1px solid var(--color-border);
  border-radius: var(--radius-pill); padding: 8px 8px 8px 18px; flex: 1 1 auto; min-width: 0; max-width: 640px; margin: 0 auto;
}
.header-main-inner .search-form input { border: none; background: transparent; font: inherit; font-size: var(--step-base); width: 100%; min-width: 0; outline: none; }
.header-main-inner .search-form button { border: none; background: var(--color-ink); color: #fff; border-radius: var(--radius-pill); width: 34px; height: 34px; flex-shrink: 0; display: grid; place-items: center; cursor: pointer; }
.header-main-actions { flex: 0 0 auto; margin-left: auto; display: flex; align-items: center; gap: 20px; }
.pill-link { font-size: var(--step-xs); font-weight: 600; border: 1px solid var(--color-border); border-radius: var(--radius-pill); padding: 8px 14px; white-space: nowrap; flex-shrink: 0; }
.pill-link:hover { border-color: var(--color-primary); color: var(--color-primary); }
.cart-link { position: relative; display: inline-flex; align-items: center; justify-content: center; width: 40px; height: 40px; border-radius: var(--radius-pill); color: var(--color-ink); flex-shrink: 0; }
.cart-link:hover { background: var(--color-bg); color: var(--color-primary); }
.cart-link__count { position: absolute; top: -2px; right: -4px; min-width: 16px; height: 16px; padding: 0 4px; border-radius: var(--radius-pill); background: var(--color-accent); color: #fff; font-size: 10px; font-weight: 700; line-height: 16px; text-align: center; }
.mobile-nav a .cart-link__count { position: static; display: inline-block; margin-left: 8px; }
.menu-toggle { display: none; background: none; border: none; cursor: pointer; padding: 6px; color: var(--color-ink); }
.mobile-nav { display: none; flex-direction: column; border-top: 1px solid var(--color-border); background: var(--color-surface); }
.mobile-nav a { padding: 14px 20px; border-bottom: 1px solid var(--color-border); font-weight: 500; }
body.nav-open .mobile-nav { display: flex; }

/* Row 3 — primary navigation: its own row, on a faint tinted background so
   it visually separates from the shopping row above it (and, on the
   homepage, from the promotional sale-ticker bar that follows it — see
   scripts/build.js). flex-shrink:0 + nowrap keeps each short label
   (Home/Shop/About Us/...) on one line rather than letting flex's default
   min-width:auto wrap a two-word label like "About Us" mid-phrase under
   space pressure — confirmed via a live screenshot in the previous
   single-row layout where that's exactly what was happening. */
.site-nav-row { background: var(--color-bg); border-bottom: 1px solid var(--color-border); }
.main-nav__inner { display: flex; gap: 28px; padding: 11px 20px; }
.main-nav a { font-size: var(--step-sm); font-weight: 500; color: var(--color-ink); padding: 3px 2px; border-bottom: 2px solid transparent; white-space: nowrap; flex-shrink: 0; }
.main-nav a:hover, .main-nav a[aria-current="page"] { border-bottom-color: var(--color-accent); }

/* Small, icon-only social row — sits in the utility bar (desktop) and as its
   own row in the mobile-nav panel. Deliberately compact/monochrome instead
   of a big text-pill button, so it reads as the usual "social links in the
   corner" pattern used across most professional sites. */
.social-icons { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
.social-icons__link {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; border-radius: var(--radius-pill);
  border: 1px solid var(--color-border); color: var(--color-ink-soft);
  transition: background-color 0.12s ease, border-color 0.12s ease, color 0.12s ease, transform 0.12s ease;
}
.social-icons__link svg { width: 16px; height: 16px; }
.social-icons__link:hover, .social-icons__link:focus-visible {
  background: var(--color-primary); border-color: var(--color-primary); color: #fff; transform: translateY(-1px);
}
.mobile-nav__social { padding: 14px 20px; border-bottom: 1px solid var(--color-border); }
.mobile-nav__social .social-icons { flex-wrap: wrap; }
/* .mobile-nav a (above) sets padding/border-bottom for the plain text nav
   links — as a descendant selector it also (unintentionally) reaches these
   nested icon-button anchors and, combined with them being flex items whose
   default min-width:auto keeps room for that padding, was inflating each
   button and squashing its icon to 0 width. Reset both back to the button's
   own sizing here, at higher specificity, so the icons render at their
   intended 32px circle. */
.mobile-nav__social .social-icons__link { padding: 0; border-bottom: none; }

/* Language switcher — a native <select> so keyboard nav, screen readers and
   the mobile picker UI all come for free (see scripts/partials.js). One
   instance lives in the utility bar, a second in the mobile nav panel;
   only one is ever visible at a time via the breakpoint below. */
.lang-switcher { display: inline-flex; align-items: center; gap: 6px; position: relative; color: var(--color-ink-soft); flex: 0 0 auto; }
/* Decorative only (aria-hidden in the markup) — the accessible language name
   is the <select>'s own text, kept in every screen reader and no-JS view.
   A subtle border keeps light flags (France/Italy have a white stripe)
   visible against the utility bar's own background. */
.lang-switcher__flag {
  flex: 0 0 auto; width: 20px; height: 14px; display: block;
  border-radius: 2px; box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.12); object-fit: cover;
}
.lang-switcher__select {
  appearance: none; -webkit-appearance: none;
  font: inherit; font-size: var(--step-xs); font-weight: 600; color: var(--color-ink);
  background: transparent; border: 1px solid var(--color-border); border-radius: var(--radius-pill);
  padding: 7px 26px 7px 10px; cursor: pointer; max-width: 7.5em;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6' fill='none' stroke='%234b5563' stroke-width='1.6'%3E%3Cpath d='M1 1l4 4 4-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 10px center;
}
.lang-switcher__select:hover { border-color: var(--color-primary); }
.lang-switcher__select:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; }
.mobile-nav__lang { padding: 14px 20px; }
.mobile-nav__lang .lang-switcher__select { max-width: none; width: 100%; }

/* Below 900px the utility bar and the nav row hide — their links/switcher/
   social row stay reachable inside the mobile-nav panel (mobile-nav__social,
   mobile-nav__lang, and the Contact nav item cover the topbar's Help link)
   — and the shopping row itself rearranges into a proper compact mobile
   header: [Menu] [Logo] [Cart] on one line, with a full-width search bar on
   the line beneath it. 900px (not the header's own overflow point, which is
   narrower) is chosen deliberately generous so a 5-item nav row never
   crowds a tablet-width screen either. */
@media (max-width: 900px) {
  .site-topbar, .site-nav-row { display: none; }
  .header-main-inner {
    display: grid;
    grid-template-columns: auto 1fr auto;
    grid-template-areas: "toggle logo actions" "search search search";
    align-items: center;
    column-gap: 14px;
    row-gap: 12px;
    padding: 14px 16px;
  }
  /* 44px is the commonly recommended minimum touch-target size (WCAG 2.5.5 /
     Apple HIG); the icon itself stays 22px, extra padding just grows the
     tappable area around it. */
  .menu-toggle { display: inline-flex; align-items: center; justify-content: center; min-width: 44px; min-height: 44px; padding: 0; grid-area: toggle; }
  .logo { grid-area: logo; justify-self: center; }
  .logo img { height: 40px; }
  .header-main-actions { grid-area: actions; margin-left: 0; gap: 10px; }
  /* The eBay pill moves into the mobile-nav panel at this width (see
     nav.ebayPillMobile in scripts/partials.js) rather than doubling up here
     — the compact mobile header only needs Menu / Logo / Search / Cart. */
  .header-main-actions .pill-link { display: none; }
  .header-main-inner .search-form { grid-area: search; max-width: none; width: 100%; margin: 0; }
}

/* Keep every text-editable form control at (or above) 16px on mobile/tablet
   (matches the 1240px breakpoint above, so any width using the hamburger
   nav also gets this — covers touch tablets in that range, not just phones).
   Below 16px, iOS Safari zooms the whole page in when the field is focused
   (there is no way to opt out of this behavior other than avoiding small
   font sizes) — jarring on a phone and easy to reintroduce by accident as
   new form fields get added later, so this is a blanket safety net rather
   than a fix for just the fields flagged today. Desktop keeps the smaller,
   denser sizing from the tokens above; only mobile/tablet is affected. */
@media (max-width: 1240px) {
  input[type="text"],
  input[type="email"],
  input[type="search"],
  input[type="tel"],
  input[type="number"],
  input[type="password"],
  input[type="url"],
  textarea,
  select,
  .lang-switcher__select {
    font-size: 16px;
  }
}

/* Layout safety for longer translations (German/French routinely run 20-35%
   longer than English; Chinese runs shorter). Nothing here truncates or
   shrinks text to force a fit — it lets buttons/cards wrap or grow.
   .main-nav a and .pill-link are deliberately NOT included here (see their
   own rules above) — nav labels and the eBay pill stay on one line. */
.btn { white-space: normal; text-align: center; }
.category-tile h3, .product-card__name, .footer-col h4 { overflow-wrap: break-word; hyphens: auto; }
.hero-showcase__tile span { overflow-wrap: break-word; }

/* Breadcrumbs */
.breadcrumbs { font-size: var(--step-xs); color: var(--color-ink-soft); padding: 16px 0 0; }
.breadcrumbs a:hover { color: var(--color-primary); }
.breadcrumbs .sep { margin: 0 6px; color: var(--color-border); }

/* Sale ticker (homepage, auto-removed by assets/js/promo-banner.js at its
   data-expires deadline). Deliberately a slim, single-line scrolling strip
   (not a big hero block) — a compact marquee of the offer text on the left,
   a live countdown + CTA fixed on the right. */
.sale-ticker {
  background: linear-gradient(100deg, #16283f 0%, var(--color-primary) 55%, #1c3454 100%);
  color: #fff;
  border-bottom: 1px solid rgba(255, 217, 138, 0.22);
}
.sale-ticker__inner {
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 9px 20px;
}
.sale-ticker__marquee {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 28px, #000 calc(100% - 28px), transparent);
  mask-image: linear-gradient(90deg, transparent, #000 28px, #000 calc(100% - 28px), transparent);
}
.sale-ticker__track {
  display: flex;
  width: max-content;
  animation: sale-ticker-scroll 26s linear infinite;
}
.sale-ticker__item {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  white-space: nowrap;
  font-size: var(--step-xs);
  font-weight: 500;
  padding-right: 48px;
  color: #e7ecf6;
}
.sale-ticker__item strong { color: #ffd98a; font-weight: 700; }
.sale-ticker__sep { opacity: 0.35; margin: 0 10px; }
@keyframes sale-ticker-scroll {
  from { transform: translateX(0); }
  to { transform: translateX(-33.3333%); }
}
@media (prefers-reduced-motion: reduce) {
  .sale-ticker__track { animation: none; }
}
.sale-ticker__end { display: flex; align-items: center; gap: 12px; flex-shrink: 0; }
.sale-ticker__timer {
  display: inline-flex;
  align-items: baseline;
  gap: 3px;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  font-size: var(--step-xs);
  color: #ffd98a;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.16);
  padding: 5px 11px;
  border-radius: var(--radius-pill);
  white-space: nowrap;
}
.sale-ticker__unit-label { font-size: 9px; text-transform: uppercase; color: #aebbd0; font-weight: 600; margin-right: 3px; }
.sale-ticker__colon { opacity: 0.35; margin: 0 1px; }
/* Layered on the shared .btn base (display/align/cursor/transition-timing)
   in its markup now, same as every other button on the site — this rule
   only needs to override what's genuinely different about it: the gold
   gradient (for contrast against the dark ticker bar the site's other
   button colors would disappear into) and its pill shape/compact size. */
.sale-ticker__cta {
  background: linear-gradient(135deg, #ffe3a6, #f2af3c);
  color: #182c47;
  font-weight: 700;
  font-size: var(--step-xs);
  padding: 8px 18px;
  border-radius: var(--radius-pill);
  white-space: nowrap;
  box-shadow: 0 4px 14px rgba(242, 175, 60, 0.32);
  transition: transform 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
}
.sale-ticker__cta:hover {
  background: linear-gradient(135deg, #ffecbe, #f7bd54);
  transform: translateY(-1px);
  box-shadow: 0 6px 18px rgba(242, 175, 60, 0.4);
}
@media (max-width: 780px) {
  .sale-ticker__inner { padding: 8px 14px; gap: 12px; }
  .sale-ticker__unit-label { display: none; }
  .sale-ticker__timer { padding: 5px 9px; }
  .sale-ticker__cta { padding: 7px 14px; }
}
@media (max-width: 560px) {
  .sale-ticker__timer { display: none; }
}

/* Hero */
.hero { background: var(--color-surface); border-bottom: 1px solid var(--color-border); }
.hero-inner { display: grid; grid-template-columns: 1.1fr 0.9fr; gap: 40px; align-items: center; padding-top: 64px; padding-bottom: 64px; }
.hero h1 { max-width: 11ch; }
.hero .lede { font-size: var(--step-md); max-width: 46ch; }
.hero-ctas { display: flex; gap: 12px; margin-top: 8px; flex-wrap: wrap; }
.hero-showcase__grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
/* min-width: 0 for the same reason as .product-card above: this grid
   item's <img width="200" height="200"> would otherwise inflate this
   column's minimum size past an even share, unevenly stretching the grid
   and, at worst, past the screen's actual width. */
.hero-showcase__tile { position: relative; aspect-ratio: 1/1; border-radius: var(--radius-sm); overflow: hidden; border: 1px solid var(--color-border); display: block; background: var(--color-bg); min-width: 0; }
.hero-showcase__tile img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .2s ease; }
.hero-showcase__tile:hover img { transform: scale(1.06); }
.hero-showcase__tile span { position: absolute; left: 0; right: 0; bottom: 0; padding: 6px 8px; font-size: 12px; font-weight: 600; color: #fff; background: linear-gradient(0deg, rgba(0,0,0,.65), rgba(0,0,0,0)); }
.hero-showcase__tagline { margin: 14px 2px 0; font-size: var(--step-sm); color: var(--color-ink-soft); text-align: center; }
@media (max-width: 780px) {
  .hero-showcase__grid { grid-template-columns: repeat(4, 1fr); }
}
@media (max-width: 780px) {
  .hero-inner { grid-template-columns: 1fr; padding-top: 40px; padding-bottom: 40px; }
  .hero h1 { max-width: none; font-size: var(--step-2xl); }
}

/* Product grid & cards — modeled on abbasimarkets' own eBay shop front
   page: a flat, borderless grid (no card background/border/shadow — the
   image and text sit directly on the page like eBay's own listing tiles),
   dense enough that many products are visible and scannable at once. The
   whole tile is one click-through to the product page (see
   .product-card__link's ::after below — a real, keyboard-reachable link
   on the title stretched to cover the full card, not an invalid nested
   <a>); "Buy on eBay" stays a small, independently-clickable link so the
   fast path to actually buying is still one tap away without a big button
   competing with it visually. */
.product-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 24px 20px; }
@media (max-width: 1080px) { .product-grid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 780px) { .product-grid { grid-template-columns: repeat(2, 1fr); gap: 20px 14px; } }
/* min-width: 0 overrides the grid item's default min-width: auto — without
   it, the <img>'s own width="400" height="400" attributes (needed so the
   layout doesn't jump as each image loads) get used as a minimum-content
   size for this whole column, even though the CSS below shrinks the image
   itself with object-fit — and that stretched three "1fr" columns into
   uneven widths, some wider than a phone screen, so the browser quietly
   zoomed the whole page out to fit rather than truly overflowing (which is
   why it didn't show up as a normal horizontal-scroll bug). */
.product-card { position: relative; display: flex; flex-direction: column; min-width: 0; }
.product-card__media { position: relative; aspect-ratio: 1/1; background: #eef1f4; overflow: hidden; border-radius: var(--radius-sm); transition: box-shadow 0.2s ease; }
.product-card__media img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.2s ease; }
.product-card:hover .product-card__media img { transform: scale(1.04); }
.product-card:hover .product-card__media { box-shadow: var(--shadow-card-hover); }
.no-image-state { width: 100%; height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; color: var(--color-ink-soft); background: #eef1f4; }
.no-image-state span { font-size: var(--step-xs); }
/* .product-card__badges is the positioned wrapper (top-left corner overlay,
   stacks multiple badges vertically) shared by both grid cards
   (.product-card__media) and the product detail page's main image
   (.gallery-main) — see scripts/components.js's badgesFor(), the single
   place that decides which badges render, used by both. Previously a
   product page's own badge markup didn't exist at all (Featured only ever
   showed on grid cards), and a product on sale had no badge anywhere on
   the site outside the homepage ticker; both now go through this one
   component instead of being reimplemented per page. */
.product-card__badges { position: absolute; top: 10px; left: 10px; z-index: 2; display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }
.badge { font-size: 11px; font-weight: 700; letter-spacing: 0.02em; text-transform: uppercase; padding: var(--space-1) var(--space-3); border-radius: var(--radius-pill); background: var(--color-ink); color: #fff; }
.badge.badge-new { background: var(--color-success); }
.badge.badge-featured { background: var(--color-accent); }
.badge.badge-demo { background: var(--color-danger); }
.badge.badge-sale { background: var(--color-danger); }
.product-card__body { padding-top: 10px; display: flex; flex-direction: column; gap: 4px; flex: 1; }
.product-card__category { font-size: 11px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--color-ink-soft); font-weight: 600; }
/* Clamped to 2 lines everywhere — eBay-sourced titles are often long and
   unclamped they made cards in the same row wildly different heights
   (this is exactly how eBay's own listing grid keeps its tiles even). */
.product-card__name {
  font-size: var(--step-sm); font-weight: 500; margin: 0; color: var(--color-ink);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
/* The stretched-link: covers the whole card (its nearest positioned
   ancestor is .product-card) so clicking anywhere — image, blank space,
   title — opens the product page, exactly like tapping an eBay tile. */
.product-card__link::after { content: ""; position: absolute; inset: 0; z-index: 1; }
.product-card__link:hover { text-decoration: underline; }
.product-card__price { font-family: var(--font-serif); font-size: var(--step-md); font-weight: 700; color: var(--color-primary); margin-top: 2px; }
.product-card__buy {
  position: relative; z-index: 2; align-self: flex-start;
  font-size: 12px; font-weight: 600; color: var(--color-ink-soft);
}
.product-card__buy:hover { color: var(--color-primary); text-decoration: underline; }
/* Sits inside the same stretched-link card as .product-card__buy above, so
   it needs the identical position:relative + z-index:2 treatment — without
   it, .product-card__link::after (z-index 1, covers the whole card) would
   swallow every click meant for this button and navigate to the product
   page instead of adding to the cart. Compact/full-width rather than the
   .btn default size — a grid tile has much less room than a detail page. */
.product-card__add-to-cart { position: relative; z-index: 2; width: 100%; padding: 9px 14px; font-size: var(--step-xs); margin-top: 2px; }
.product-card__add-to-cart.is-added { background: var(--color-success); border-color: var(--color-success); }

/* 3 columns on phones, matching the density of eBay's own mobile grid.
   Moved to AFTER every base rule it overrides (.product-card__body,
   __category, __name, __price, __buy, .badge — all defined above, in the
   same file, but this block used to sit BEFORE them) — same selector,
   same specificity, so plain source order decided the winner, and the
   later base rule was silently winning every time. None of these
   "smaller on phones" overrides had ever actually applied. Found via a
   real breakpoint verification pass, not by inspection. */
@media (max-width: 480px) {
  .product-grid { grid-template-columns: repeat(3, 1fr); gap: 16px 8px; }
  .product-card__body { padding-top: 6px; gap: 2px; }
  .product-card__category { font-size: 9px; }
  .product-card__name { font-size: 12px; }
  .product-card__price { font-size: 13px; }
  .product-card__buy { font-size: 10px; }
  .product-card__add-to-cart { font-size: 10px; padding: 7px 8px; }
  .product-card__badges { top: 6px; left: 6px; gap: 4px; }
  .badge { font-size: 9px; padding: 3px 6px; }
}

/* Category tiles */
.category-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
@media (max-width: 780px) { .category-grid { grid-template-columns: 1fr 1fr; } }
.category-tile { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); padding: 22px; display: flex; flex-direction: column; gap: 6px; box-shadow: var(--shadow-card); transition: border-color .15s ease, background-color .15s ease, box-shadow .15s ease; }
.category-tile:hover { border-color: var(--color-accent); background: var(--color-accent-bg); box-shadow: var(--shadow-card-hover); }
.category-tile .count { font-size: var(--step-xs); color: var(--color-ink-soft); }

/* Feature strip */
.feature-strip { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; }
@media (max-width: 780px) { .feature-strip { grid-template-columns: 1fr; } }
.feature-item { display: flex; gap: 14px; }
.feature-item .icon { flex: none; width: 40px; height: 40px; border-radius: 10px; background: rgba(30, 58, 95, 0.08); display: grid; place-items: center; color: var(--color-primary); }
.feature-item h4 { margin-bottom: 4px; }
.feature-item p { margin: 0; font-size: var(--step-sm); }

/* Trust / eBay section */
.trust-section { background: var(--color-primary); color: #fff; border-radius: var(--radius-md); padding: 44px; display: grid; grid-template-columns: 1.2fr 1fr; gap: 32px; align-items: center; }
.trust-section p, .trust-section .stat-label { color: rgba(255,255,255,0.78); }
.trust-section h2 { color: #fff; }
.trust-stats { display: flex; gap: 28px; flex-wrap: wrap; }
.trust-stat .num { font-family: var(--font-serif); font-size: var(--step-xl); font-weight: 600; }
.trust-stat .stat-label { font-size: var(--step-xs); }
.trust-steps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 14px; }
.trust-steps li { display: flex; gap: 12px; align-items: flex-start; font-size: var(--step-sm); color: rgba(255,255,255,0.92); }
.trust-steps .n { flex: none; width: 24px; height: 24px; border-radius: var(--radius-pill); background: rgba(255,255,255,0.16); display: grid; place-items: center; font-size: 12px; font-weight: 700; }
.trust-note { font-size: var(--step-xs); color: rgba(255,255,255,0.6); margin-top: 18px; }
@media (max-width: 820px) { .trust-section { grid-template-columns: 1fr; padding: 28px; } }

/* Shop page toolbar */
.shop-layout { display: grid; grid-template-columns: 220px 1fr; gap: 28px; align-items: flex-start; }
@media (max-width: 880px) { .shop-layout { grid-template-columns: 1fr; } }
/* Grid items default to min-width: auto — they refuse to shrink narrower
   than their own content's natural width, content be damned. The toolbar's
   search box + sort dropdown don't fit side by side on a phone screen, but
   instead of the flex-wrap below kicking in like it's supposed to, that
   default was forcing THIS column (and with it, the whole page) wider than
   the phone's actual screen — the browser then quietly zoomed the entire
   page out to make it fit, which is what made the padding fix's own
   `window.innerWidth` read wider than the real device width. min-width: 0
   here lets the column (and .toolbar below) actually shrink to the
   screen, so flex-wrap can do its job. */
.shop-layout > * { min-width: 0; }
.filters { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); padding: 18px; position: sticky; top: 84px; box-shadow: var(--shadow-card); }
/* Sticky only makes sense in the two-column desktop layout (filters card
   pinned beside a taller product grid as you scroll). Once the layout
   collapses to one column on mobile, "sticky" instead makes the filters
   card float in place and get scrolled OVER BY the product grid below it —
   overlapping and hiding the first row of products. Plain, normal-flow
   positioning on mobile fixes that. */
@media (max-width: 880px) { .filters { position: static; } }
.filters h4 { margin-bottom: 12px; }
.filter-group { margin-bottom: 18px; }
.filter-group label { display: flex; align-items: center; gap: 8px; font-size: var(--step-sm); padding: 4px 0; cursor: pointer; }
.filter-group input[type="checkbox"] { accent-color: var(--color-primary); }
.toolbar { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 18px; flex-wrap: wrap; }
.toolbar select, .toolbar input[type="search"] { font-size: var(--step-sm); min-width: 0; flex: 1 1 160px; }
.result-count { font-size: var(--step-xs); color: var(--color-ink-soft); }
.empty-state { text-align: center; padding: 64px 20px; color: var(--color-ink-soft); }

/* Product detail */
.product-detail { display: grid; grid-template-columns: 1fr 1fr; gap: 44px; align-items: flex-start; }
@media (max-width: 880px) { .product-detail { grid-template-columns: 1fr; gap: 24px; } }
.gallery-main { position: relative; aspect-ratio: 1/1; background: #eef1f4; border-radius: var(--radius-md); overflow: hidden; border: 1px solid var(--color-border); }
.gallery-main img { width: 100%; height: 100%; object-fit: cover; }
.gallery-thumbs { display: flex; gap: 10px; margin-top: 12px; }
.gallery-thumbs button { padding: 0; border-radius: var(--radius-sm); overflow: hidden; width: 68px; height: 68px; border: 2px solid var(--color-border); background: #eef1f4; cursor: pointer; flex: none; }
.gallery-thumbs button img { width: 100%; height: 100%; object-fit: cover; display: block; }
.gallery-thumbs button[aria-current="true"] { border-color: var(--color-primary); }
.gallery-thumbs button:hover { border-color: var(--color-primary); }
.product-price { font-family: var(--font-serif); font-size: var(--step-xl); font-weight: 600; color: var(--color-primary); }
/* Shared base for both inline info badges below the title (as opposed to
   .badge above, the corner-overlay kind) — same shape/pill/spacing family,
   previously duplicated as two separate rules with no shared selector. */
.condition-badge, .out-of-stock-badge { display: inline-flex; align-items: center; gap: 4px; font-size: var(--step-xs); font-weight: 600; border-radius: var(--radius-pill); padding: var(--space-1) var(--space-3); }
.condition-badge { color: var(--color-ink-soft); background: var(--color-accent-bg); border: 1px solid var(--color-accent-soft); margin: 6px 0 0; }
.out-of-stock-badge { font-weight: 700; color: var(--color-danger); background: var(--color-danger-bg); border: 1px solid var(--color-danger-border); margin: 10px 0 0; }
.add-to-cart-btn[disabled], .buy-now-btn[disabled], .add-to-cart-qty[disabled] { opacity: .55; cursor: not-allowed; }
.delivery-info { margin: 10px 0 4px; }
.delivery-info__badge { display: flex; align-items: center; gap: 6px; color: var(--color-success); font-weight: 600; font-size: var(--step-sm); margin: 0; }
.delivery-info__badge svg { flex: none; }
.delivery-info__estimate { color: var(--color-ink-soft); font-size: var(--step-xs); margin: 4px 0 0; }
.delivery-info__estimate a { color: inherit; text-decoration: underline; }
.quantity-discount { margin: 12px 0; border: 1px solid var(--color-border); border-radius: var(--radius-sm); padding: 12px 14px; background: var(--color-surface); box-shadow: var(--shadow-card); }
.quantity-discount__heading { font-weight: 600; font-size: var(--step-sm); margin: 0 0 8px; }
.quantity-discount__table { width: 100%; border-collapse: collapse; font-size: var(--step-xs); }
.quantity-discount__table td { padding: 4px 0; color: var(--color-ink-soft); }
.quantity-discount__pct { text-align: right; font-weight: 600; }
.quantity-discount__row--active td { color: var(--color-primary); font-weight: 700; }
.quantity-discount__preview { margin: 8px 0 0; font-size: var(--step-xs); color: var(--color-success); font-weight: 600; }
.spec-table { width: 100%; border-collapse: collapse; margin-top: 10px; }
.spec-table th, .spec-table td { text-align: left; padding: 10px 0; border-bottom: 1px solid var(--color-border); font-size: var(--step-sm); }
.spec-table th { color: var(--color-ink-soft); font-weight: 500; width: 40%; }
.demo-banner { background: var(--color-warning-bg); border: 1px solid var(--color-warning-border); color: var(--color-warning-ink); border-radius: var(--radius-sm); padding: 10px 14px; font-size: var(--step-xs); margin-bottom: 16px; }
.legal-disclaimer { background: var(--color-accent-bg); border: 1px solid var(--color-accent-soft); color: var(--color-ink-soft); border-radius: var(--radius-sm); padding: 10px 14px; font-size: var(--step-xs); margin: 14px 0 20px; }
.form-error { display: block; color: var(--color-danger); font-size: var(--step-xs); margin-top: 4px; min-height: 1.2em; }
.form-error:empty { min-height: 0; margin-top: 0; }
/* Required-field marker — previously nothing on the site distinguished a
   required field from an optional one except the few labels that spelled
   out "(optional)" in their own text (checkout's Phone/Apartment fields).
   Screen-reader users still get the real signal from the input's own
   `required` attribute; this is the sighted-user equivalent, plus the
   .form-legend note below spells out what it means in each language. */
.required-mark { color: var(--color-danger); margin-left: 2px; }
.form-legend { font-size: var(--step-xs); color: var(--color-ink-soft); margin: -8px 0 16px; }
.form-status { font-size: var(--step-sm); margin: 8px 0; }
[aria-invalid="true"] { border-color: var(--color-danger) !important; }

/* Cookie consent banner (assets/js/cookie-consent.js) */
.cookie-banner { position: fixed; left: 0; right: 0; bottom: 0; z-index: 90; background: var(--color-surface); border-top: 1px solid var(--color-border); box-shadow: var(--shadow-card-hover); padding: 16px 20px; }
.cookie-banner__inner { max-width: 1100px; margin: 0 auto; display: flex; align-items: center; gap: 20px; flex-wrap: wrap; }
.cookie-banner__message { flex: 1 1 360px; font-size: var(--step-sm); color: var(--color-ink-soft); margin: 0; }
.cookie-banner__message a { color: var(--color-primary); text-decoration: underline; }
.cookie-banner__actions { display: flex; gap: 10px; flex: 0 0 auto; }
.cookie-banner[hidden] { display: none; }
@media (max-width: 560px) { .cookie-banner__actions { width: 100%; } .cookie-banner__actions .btn { flex: 1 1 0; } }
.footer-cookie-settings { background: none; border: none; padding: 0; font: inherit; color: inherit; cursor: pointer; text-decoration: none; }
.footer-cookie-settings:hover { text-decoration: underline; }

/* Footer */
.site-footer { background: var(--color-surface); border-top: 3px solid var(--color-accent); margin-top: 64px; }
.footer-grid { display: grid; grid-template-columns: 1.4fr repeat(4, 1fr); gap: 28px; padding-top: 48px; padding-bottom: 28px; }
@media (max-width: 880px) { .footer-grid { grid-template-columns: 1fr 1fr; } }
.footer-col h4 { font-size: var(--step-sm); margin-bottom: 12px; }
.footer-col ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.footer-col a { font-size: var(--step-sm); color: var(--color-ink-soft); }
.footer-col a:hover { color: var(--color-primary); }
.footer-bottom { border-top: 1px solid var(--color-border); padding-top: 18px; padding-bottom: 18px; font-size: var(--step-xs); color: var(--color-ink-soft); display: flex; justify-content: space-between; flex-wrap: wrap; gap: 8px; }

/* Contact page */
.contact-methods { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 14px; margin-top: 20px; }
.contact-method { display: flex; align-items: center; gap: 14px; padding: 16px; border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-surface); box-shadow: var(--shadow-card); transition: border-color .15s ease, transform .15s ease, box-shadow .15s ease; }
.contact-method:hover { border-color: var(--color-primary); transform: translateY(-1px); box-shadow: var(--shadow-card-hover); }
.contact-method__icon { flex: none; width: 40px; height: 40px; border-radius: 50%; background: var(--color-bg); display: grid; place-items: center; color: var(--color-primary); }
.contact-method__icon svg { width: 20px; height: 20px; }
.contact-method span:last-child { font-size: var(--step-sm); line-height: 1.35; color: var(--color-ink); }
.contact-form { margin-top: 20px; display: flex; flex-direction: column; gap: 14px; max-width: 520px; }
.form-row { display: flex; flex-direction: column; gap: 6px; }
.form-row label { font-size: var(--step-xs); font-weight: 600; color: var(--color-ink-soft); }
.contact-form .btn { align-self: flex-start; }

/* Product page — Add to Cart / Buy It Now. Buy It Now is the visually
   primary action (solid accent, full-width) since it's the fastest path to
   a completed purchase; Add to Cart is secondary (outline) for shoppers
   who want to keep browsing first — same hierarchy eBay's own listing
   pages use. The eBay-shop link (.btn-secondary-link below) is demoted
   further still, since it's now a fallback rather than the main CTA. */
.add-to-cart-row { display: flex; gap: 10px; margin: 16px 0 8px; }
.add-to-cart-qty { width: 64px; text-align: center; }
.add-to-cart-btn { flex: 1; }
.buy-now-btn { font-weight: 700; }
.add-to-cart-confirm { color: var(--color-success); font-size: var(--step-sm); font-weight: 600; margin: 0 0 8px; }
/* A quiet fallback link rather than a full button — sits below the Add to
   Cart / Buy It Now pair for shoppers who specifically want to use eBay's
   own checkout instead (e.g. to spend eBay balance/vouchers). */
.btn-secondary-link { border: none; background: none; padding: 4px 0; font-size: var(--step-xs); color: var(--color-ink-soft); width: auto; display: inline-block; }
.btn-secondary-link:hover { color: var(--color-primary); background: none; }

/* Cart page */
.cart-list { margin-top: 20px; display: flex; flex-direction: column; gap: 14px; }
.cart-row { display: grid; grid-template-columns: 72px 1fr auto auto auto; align-items: center; gap: 16px; padding: 14px; border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-surface); box-shadow: var(--shadow-card); }
.cart-row__image { width: 72px; height: 72px; border-radius: var(--radius-sm); overflow: hidden; background: var(--color-bg); display: block; }
.cart-row__image img { width: 100%; height: 100%; object-fit: cover; }
.cart-row__info { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.cart-row__name { font-weight: 600; color: var(--color-ink); }
.cart-row__variant { color: var(--color-ink-soft); font-size: var(--step-xs); }
.cart-row__price { color: var(--color-ink-soft); font-size: var(--step-sm); }
.cart-row__price-original { text-decoration: line-through; opacity: 0.65; margin-right: 2px; }
.cart-row__bulk-badge, .checkout-line__name .cart-row__bulk-badge { display: inline-block; color: var(--color-success); font-weight: 600; font-size: var(--step-2xs, 0.7rem); background: var(--color-accent-bg); border-radius: var(--radius-pill); padding: 1px 8px; margin-left: 4px; white-space: nowrap; }
.variant-select { width: 100%; max-width: 340px; }
.cart-row__qty { display: flex; align-items: center; gap: 6px; }
.cart-qty-btn { width: 28px; height: 28px; border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-bg); cursor: pointer; font-size: 16px; line-height: 1; }
.cart-qty-input { width: 46px; text-align: center; font: inherit; padding: 6px; border: 1px solid var(--color-border); border-radius: var(--radius-sm); }
.cart-row__total { font-weight: 700; white-space: nowrap; }
.cart-row__remove { color: var(--color-ink-soft); background: none; border: none; cursor: pointer; padding: 6px; }
.cart-row__remove:hover { color: var(--color-danger); }
.cart-summary { margin-top: 24px; padding: 20px; border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-surface); max-width: 380px; margin-left: auto; }
.cart-summary__row { display: flex; justify-content: space-between; align-items: center; font-size: var(--step-md); margin-bottom: 6px; }
.cart-summary__note { font-size: var(--step-xs); color: var(--color-ink-soft); margin-bottom: 16px; }
@media (max-width: 640px) {
  .cart-row { grid-template-columns: 56px 1fr; grid-template-areas: "img info" "img qty" "img total"; }
  .cart-row__image { grid-area: img; width: 56px; height: 56px; }
  .cart-row__info { grid-area: info; }
  .cart-row__qty { grid-area: qty; }
  .cart-row__total { grid-area: total; }
  .cart-row__remove { grid-column: 2; justify-self: end; }
  .cart-summary { max-width: none; }
}

/* Checkout page */
.checkout-error { background: var(--color-danger-bg); color: var(--color-danger); border: 1px solid var(--color-danger); border-radius: var(--radius-sm); padding: 12px 16px; margin: 16px 0; font-size: var(--step-sm); }
.checkout-layout { display: grid; grid-template-columns: 1.2fr 1fr; gap: 32px; margin-top: 20px; align-items: start; }
/* Same min-width:0 grid-item trap as .shop-layout above: without it, the
   two-column checkout form (see .form-row--split below) sets its parent
   grid item's automatic minimum size to its own max-content width, which
   forced this whole column — and the page — wider than a phone screen. */
.checkout-layout > * { min-width: 0; }
.checkout-layout form#checkout-form { display: flex; flex-direction: column; gap: 14px; }
.form-row--split { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
/* Same min-width:0 grid-item trap as .shop-layout/.checkout-layout above,
   one level deeper: this row's own two columns were sizing themselves to
   their input's max-content width instead of the 1fr track they're meant
   to share, which is what was still forcing this row (and the page) wider
   than a phone screen even after .checkout-layout > * was fixed. */
.form-row--split > * { min-width: 0; }
.form-row--split .form-row, .form-row--split > div { display: flex; flex-direction: column; gap: 6px; }
.form-row--split label { font-size: var(--step-xs); font-weight: 600; color: var(--color-ink-soft); }
.checkout-summary-panel { padding: 20px; border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-surface); position: sticky; top: 90px; box-shadow: var(--shadow-card); }
.checkout-line, .track-line { display: flex; justify-content: space-between; gap: 12px; padding: 8px 0; border-bottom: 1px solid var(--color-border); font-size: var(--step-sm); }
.checkout-line__qty { color: var(--color-ink-soft); }
.checkout-line--total, .track-line--total { border-bottom: none; border-top: 2px solid var(--color-ink); margin-top: 6px; padding-top: 12px; font-weight: 700; font-size: var(--step-md); }
.checkout-line--discount, .track-line--discount { color: var(--color-success); font-weight: 600; }
.checkout-promo-row { display: flex; gap: 8px; margin: 14px 0; }
.checkout-promo-row input { flex: 1; }
.checkout-promo-row .btn { flex: 0 0 auto; }
.checkout-promo-select { flex: 1; cursor: pointer; }
.checkout-promo-select:disabled { opacity: 0.6; cursor: wait; }
.checkout-promo-message { font-size: var(--step-xs); font-weight: 600; color: var(--color-success); margin: -8px 0 14px; }
.checkout-promo-message--error { color: var(--color-danger); }
.payment-method-tabs { display: flex; gap: 10px; margin: 14px 0; }
.payment-method-tab { flex: 1; display: flex; align-items: center; justify-content: center; gap: 8px; padding: 12px; border: 1px solid var(--color-border); border-radius: var(--radius-sm); cursor: pointer; font-size: var(--step-sm); font-weight: 600; }
.payment-method-tab input { accent-color: var(--color-primary); }
.payment-method-tab:has(input:checked) { border-color: var(--color-primary); background: rgba(30, 58, 95, 0.06); }
.stripe-card-element { padding: 12px; border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-surface); margin-bottom: 10px; }
.stripe-card-error { color: var(--color-danger); font-size: var(--step-xs); min-height: 16px; margin-bottom: 10px; }
/* Phase 3: checkout processing state. Previously neither payment path gave
   any visible feedback during its own network round-trip — PayPal's
   createOrder/onApprove calls (assets/js/checkout.js) happen before/after
   PayPal's own popup UI and were otherwise silent, and the Stripe submit
   button just went inert (disabled, same label) with nothing indicating
   work was happening. .spinner is deliberately generic (not payment-
   specific) so it can also serve any other future async wait on the site. */
.spinner {
  display: inline-block;
  width: 15px;
  height: 15px;
  border: 2px solid rgba(255, 255, 255, 0.35);
  border-top-color: currentColor;
  border-radius: 50%;
  animation: am-spin 0.7s linear infinite;
  vertical-align: -3px;
}
@keyframes am-spin {
  to { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
  .spinner { animation: none; }
}
.checkout-processing {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--color-ink-soft);
  font-size: var(--step-sm);
  font-weight: 600;
  margin: 10px 0;
}
.checkout-processing .spinner { border-color: rgba(30, 58, 95, 0.25); border-top-color: var(--color-primary); }
#stripe-submit .spinner { margin-right: 2px; }
.checkout-legal-note { font-size: var(--step-xs); color: var(--color-ink-soft); margin-top: 18px; }
@media (max-width: 800px) {
  .checkout-layout { grid-template-columns: 1fr; }
  .checkout-summary-panel { position: static; }
}

/* Order confirmation */
.order-confirmation__icon { color: var(--color-success); margin-bottom: 12px; }
.order-confirmation__number { font-size: var(--step-lg); margin: 18px 0; }
.order-confirmation__email-note { color: var(--color-ink-soft); font-size: var(--step-sm); margin-top: 8px; }
/* Reuses .track-result's card styling (below) so the receipt reads as the
   same component as the /track/ page's order lookup, not a one-off. */
.order-confirmation__details { margin-top: 28px; padding: 20px; border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-surface); text-align: left; box-shadow: var(--shadow-card); }

/* Track order */
.track-result { margin-top: 24px; padding: 20px; border: 1px solid var(--color-border); border-radius: var(--radius-sm); background: var(--color-surface); text-align: left; box-shadow: var(--shadow-card); }
.track-status { display: inline-block; padding: var(--space-1) var(--space-3); border-radius: var(--radius-pill); font-weight: 700; font-size: var(--step-xs); text-transform: uppercase; letter-spacing: .03em; }
.track-status--paid { background: var(--color-success-bg); color: var(--color-success); }
.track-status--pending { background: var(--color-warning-bg); color: var(--color-warning); }
.track-status--capture_failed { background: var(--color-danger-bg); color: var(--color-danger); }
.track-items { margin-top: 12px; }

/* ==========================================================================
   Utility & one-off classes — replaces ~32 inline style="..." attributes
   that used to live directly in scripts/build.js's template strings (five
   different ad hoc content-width values, several repeated spacing bumps,
   and a few page-specific tweaks). Same exact values as before in every
   case — this is a code-hygiene move, not a visual change — but now
   there's one place to see (and later rationalize) this site's spacing,
   instead of it being scattered across a 1000+ line JS file.
   ========================================================================== */
/* Page/section content-width caps (one per page type, unchanged values) */
.container--600 { max-width: 600px; }
.container--700 { max-width: 700px; }
.container--820 { max-width: 820px; }
.container--900 { max-width: 900px; }
.container--1000 { max-width: 1000px; }
/* Generic single-property spacing bumps, reused across otherwise-unrelated
   elements (a heading here, a button there) that all needed the same nudge. */
.u-pt-16 { padding-top: 16px; }
.u-p-16 { padding: 16px; }
.u-mt-10 { margin-top: 10px; }
.u-mt-14 { margin-top: 14px; }
.u-mt-20 { margin-top: 20px; }
.u-mt-24 { margin-top: 24px; }
.u-mt-32 { margin-top: 32px; }
.u-ml-10 { margin-left: 10px; }
.u-my-12 { margin: 12px 0; }
.u-my-16 { margin: 16px 0; }
.u-text-center { text-align: center; }
/* Named, purpose-specific classes */
.page-title { font-size: var(--step-2xl); }
.eyebrow--on-dark { color: #fff; }
.variant-select-label { display: block; font-weight: 600; margin-bottom: 6px; }
.spec-table--padded { padding: 16px; }
.error-page { text-align: center; padding: 100px 20px; }
/* The shared closing "have this reviewed by a professional" footnote on
   every legal page (Impressum, Datenschutz, AGB, Widerruf/Returns) — was
   four identical inline style="..." attributes before this. */
.legal-footnote { margin-top: 24px; color: var(--color-ink-soft); font-size: var(--step-sm); }

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