/* MDRLB V2 — shared visual system.
   Restores the proven V1 (v10.php) dark "conversion shell" on top of the V2
   Renderer markup: a cinematic first screen (background + two-column hero +
   selected-offer card + offer stage) followed by the V2 SEO article.
   Plain CSS only — no framework, no CDN, no webfont. */

:root {
  --c1: #60ff88;
  --c2: #1de39a;
  --c3: #0b2c1d;
  --surface: #07130d;
  --bg: #050708;
  --ink: #f7fbf8;
  --muted: #a9b4ae;
  --hair: rgba(255, 255, 255, .10);
  --wrap: 1240px;
  --read: 880px;
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

html, body {
  margin: 0;
  min-height: 100%;
  max-width: 100%;
  background: var(--bg);
  color: var(--ink);
  font-family: Inter, "Segoe UI", Roboto, Arial, Helvetica, sans-serif;
  line-height: 1.55;
  overflow-x: hidden;
}

img { max-width: 100%; height: auto; }
a { color: var(--c1); }
a, button { font: inherit; }

a:focus-visible,
button:focus-visible {
  outline: 3px solid var(--c1);
  outline-offset: 2px;
  border-radius: 4px;
}

/* ------------------------------------------------------------------ shell */

.page {
  position: relative;
  min-height: 100vh;
  overflow: hidden;
  overflow-x: clip;
  max-width: 100%;
  isolation: isolate;
  background:
    linear-gradient(90deg,
      rgba(2, 6, 12, .93) 0%,
      rgba(3, 8, 14, .84) 40%,
      rgba(3, 7, 12, .50) 72%,
      rgba(2, 4, 8, .70) 100%),
    url("/assets/bg/casino-slots.jpg") center / cover fixed no-repeat;
}

.page::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(circle at 72% 26%,
      color-mix(in srgb, var(--c1) 20%, transparent), transparent 32%),
    linear-gradient(180deg, rgba(2, 5, 10, .05), rgba(2, 5, 10, .62));
}

.page::after {
  content: "";
  position: absolute;
  right: -10%;
  bottom: -30%;
  width: 54%;
  height: 54%;
  z-index: -1;
  pointer-events: none;
  background: url("/assets/bg/roulette.webp") center / cover no-repeat;
  border-radius: 50%;
  opacity: .16;
  filter: saturate(1.15) contrast(1.05);
  transform: rotate(-7deg);
  -webkit-mask-image: radial-gradient(circle, #000 40%, transparent 73%);
  mask-image: radial-gradient(circle, #000 40%, transparent 73%);
}

/* --------------------------------------------------------------- top bar */

.top {
  position: relative;
  z-index: 2;
  width: min(var(--wrap), calc(100% - 48px));
  margin: auto;
  min-height: 84px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.brand { display: flex; align-items: center; gap: 12px; min-width: 0; }

.brand-logo {
  display: block;
  max-width: 150px;
  max-height: 42px;
  width: auto;
  object-fit: contain;
  filter: drop-shadow(0 4px 12px rgba(0, 0, 0, .45));
}

.mark {
  width: 42px;
  height: 42px;
  border-radius: 13px;
  display: grid;
  place-items: center;
  font-weight: 900;
  color: #061009;
  background: linear-gradient(135deg, var(--c1), var(--c2));
  box-shadow: 0 0 30px color-mix(in srgb, var(--c1) 18%, transparent);
}

.brandtext { font-size: 13px; letter-spacing: .15em; font-weight: 800; }

.age {
  flex: none;
  font-size: 12px;
  font-weight: 800;
  color: var(--c1);
  border: 1px solid color-mix(in srgb, var(--c1) 28%, transparent);
  padding: 8px 12px;
  border-radius: 999px;
}

/* ----------------------------------------------------------------- hero */

.hero {
  position: relative;
  z-index: 2;
  width: min(var(--wrap), calc(100% - 48px));
  max-width: 100%;
  margin: auto;
  display: grid;
  grid-template-columns: minmax(0, 1.02fr) minmax(460px, .98fr);
  align-items: center;
  gap: 40px;
  min-height: clamp(520px, calc(100vh - 84px), 820px);
  padding: 30px 0 44px;
}

.copy { max-width: 700px; min-width: 0; }
.copy > * { min-width: 0; }

/* Only the no-valid-primary safety fallback: no primary means no secondary
   "Другие варианты" selector either (Rule B), so there is nothing for a
   right column — the hero collapses to one column instead of reserving an
   empty one. The primary card itself always lives inline in .copy (below),
   never in its own column, so its presence alone never forces two columns.
   Any page with a resolved primary AND eligible orbit offers gets the real
   two-column hero: .copy left, .alt-offers (the selector) right — see
   below. */
.hero--solo {
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
  min-height: auto;
  padding-bottom: 16px;
}
.hero--solo .copy { max-width: min(820px, 100%); }

.eyebrow {
  margin: 0 0 16px;
  font-size: 11px;
  letter-spacing: .18em;
  font-weight: 800;
  text-transform: uppercase;
  color: var(--c1);
}

.hero h1 {
  margin: 0;
  font-size: clamp(40px, 4.7vw, 68px);
  line-height: 1.02;
  letter-spacing: -.035em;
  font-weight: 900;
  overflow-wrap: anywhere;
  word-break: break-word;
  hyphens: auto;
  -webkit-hyphens: auto;
}

.lead {
  max-width: min(60ch, 100%);
  margin: 22px 0 0;
  color: var(--muted);
  font-size: 17px;
  line-height: 1.6;
  overflow-wrap: anywhere;
}

/* ---------------------------------------------------- selected-offer card */

.offer-card {
  margin-top: 28px;
  max-width: 520px;
  border-radius: 22px;
  padding: 18px 20px;
  background: linear-gradient(180deg, rgba(9, 11, 14, .70), rgba(4, 6, 9, .55));
  border: 1px solid color-mix(in srgb, var(--c1) 26%, var(--hair));
  box-shadow: 0 22px 60px rgba(0, 0, 0, .32), inset 0 1px rgba(255, 255, 255, .05);
  -webkit-backdrop-filter: blur(9px);
  backdrop-filter: blur(9px);
}

.offer-card__label {
  margin: 0 0 12px;
  font-size: 11px;
  letter-spacing: .14em;
  text-transform: uppercase;
  font-weight: 800;
  color: #8b978f;
}

.offer-head {
  display: flex;
  align-items: center;
  gap: 16px;
  min-height: 76px;
}

.offer-logo {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: flex-start;
  min-width: 64px;
}

.offer-head.has-logo .offer-logo { min-width: 190px; }

.offer-logo img {
  display: block;
  max-width: 210px;
  max-height: 74px;
  width: auto;
  object-fit: contain;
  filter: drop-shadow(0 5px 14px rgba(0, 0, 0, .4));
}

.offer-name {
  font-size: clamp(24px, 3.4vw, 32px);
  line-height: 1;
  font-weight: 900;
  letter-spacing: -.02em;
  color: #fff;
  overflow-wrap: anywhere;
}

/* With a logo present, keep the real destination brand as a small visible
   caption (never image-only) — the big wordmark treatment is only for the
   logo-less fallback. */
.offer-head.has-logo .offer-name {
  font-size: 13px;
  font-weight: 800;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: #aeb8b1;
}

.actions {
  display: flex;
  flex-wrap: nowrap;
  gap: 10px;
  margin-top: 18px;
}

/* The primary CTA ("Забрать бонус — {Brand}") and the secondary switch
   ("Показать другой приз") always stay side by side on one row, for any
   brand-name length (APEX Casino, Play Fortuna, Joy Casino, Casino X,
   1xSlots, GAMA, R7, RamenBet, …).

     * the switch takes its natural width and never grows/shrinks or steals
       the row (flex: 0 0 auto + nowrap);
     * the CTA takes all remaining space (flex: 1 1 auto);
     * a word is never broken inside — overflow-wrap/word-break: normal,
       hyphens: none.
   Desktop single-line sizing is in the min-width:761px block below; the
   max-width:760px rule further down stacks the whole block for mobile. */
.actions > .cta {
  flex: 1 1 auto;
  min-width: 0;
  line-height: 1.15;
}

.actions > .switch {
  flex: 0 0 auto;
  min-width: 0;
  white-space: nowrap;
}

.actions > .cta,
.actions > .switch {
  padding-left: 16px;
  padding-right: 16px;
  overflow-wrap: normal;
  word-break: normal;
  hyphens: none;
}

/* Desktop: BOTH buttons are one single line each, whole — including the
   full "Забрать бонус — {Brand}" string, no wrap between prefix and brand.
   The widest real label ("Забрать бонус — APEX Casino" in an Arial-metrics
   fallback font) plus the switch plus the gap need ~433px; every desktop
   offer-card is wider than that — the hero card is 480px inner and the
   narrowest "Другие варианты" card is ~446px inner (its column bottoms out
   at the 460px grid track just above the 1080px breakpoint) — so a 12px
   label with 14px side padding clears all of them with headroom, without
   enlarging any card. */
@media (min-width: 761px) {
  .actions > .cta,
  .actions > .switch {
    font-size: 12px;
    padding-left: 14px;
    padding-right: 14px;
    white-space: nowrap;
    line-height: 1.1;
  }
}

.cta, .switch {
  min-height: 52px;
  border-radius: 14px;
  padding: 14px 24px;
  font-weight: 800;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  text-decoration: none;
}

.cta {
  background: linear-gradient(90deg, var(--c1), var(--c2));
  color: #061009;
  border: none;
  min-width: 200px;
}

.switch {
  background: transparent;
  color: #fff;
  border: 1px solid color-mix(in srgb, var(--c1) 34%, transparent);
  min-width: 170px;
}

/* ---------------------------------------------------------------- stage */

.stage {
  position: relative;
  min-width: 0;
  height: 700px;
  align-self: center;
}

.machine {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 520px;
  height: 520px;
  transform: translate(-50%, -50%);
  border-radius: 42px;
  border: 1px solid var(--hair);
  background:
    linear-gradient(color-mix(in srgb, var(--c1) 13%, transparent) 1px, transparent 1px),
    linear-gradient(90deg, color-mix(in srgb, var(--c2) 11%, transparent) 1px, transparent 1px),
    radial-gradient(circle at 50% 50%, color-mix(in srgb, var(--c1) 22%, transparent), #08100c 40%);
  background-size: 34px 34px, 34px 34px, auto;
  box-shadow: inset 0 0 80px rgba(0, 0, 0, .25), 0 30px 90px rgba(0, 0, 0, .34);
}

.machine::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 136px;
  height: 136px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(circle, var(--c1), var(--c2) 36%, #101714 38% 58%, transparent 60%);
  box-shadow: 0 0 42px color-mix(in srgb, var(--c1) 26%, transparent);
}

.ball {
  position: absolute;
  width: 218px;
  height: 218px;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, .38);
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  text-decoration: none;
  color: #fff;
  isolation: isolate;
  overflow: hidden;
  background: radial-gradient(circle at 35% 28%, var(--accent, var(--c1)), #0b1110 72%);
  box-shadow:
    inset -27px -34px 54px rgba(0, 0, 0, .58),
    inset 18px 14px 28px rgba(255, 255, 255, .18),
    0 30px 64px rgba(0, 0, 0, .56),
    0 0 34px color-mix(in srgb, var(--c1) 18%, transparent);
  transition: transform .25s ease, filter .25s ease, box-shadow .25s ease;
  animation: floatBall 5.6s ease-in-out infinite;
  animation-delay: calc(var(--i, 0) * -1.12s);
}

.ball::before {
  content: "";
  position: absolute;
  z-index: 2;
  left: 15%;
  top: 9%;
  width: 49%;
  height: 31%;
  border-radius: 50%;
  background: linear-gradient(180deg, rgba(255, 255, 255, .82), rgba(255, 255, 255, .17) 38%, rgba(255, 255, 255, 0));
  filter: blur(2px);
  transform: rotate(-20deg);
  opacity: .78;
  pointer-events: none;
}

.ball::after {
  content: "";
  position: absolute;
  z-index: 1;
  inset: 6%;
  border-radius: 50%;
  background:
    radial-gradient(circle at 72% 78%, rgba(255, 255, 255, .08), transparent 30%),
    linear-gradient(135deg, rgba(255, 255, 255, .08), transparent 36%);
  border: 1px solid rgba(255, 255, 255, .08);
  pointer-events: none;
}

.ball:hover,
.ball:focus-visible,
.ball.active {
  transform: scale(1.075);
  filter: brightness(1.1) saturate(1.08);
  box-shadow:
    inset -27px -34px 54px rgba(0, 0, 0, .54),
    inset 18px 14px 30px rgba(255, 255, 255, .2),
    0 34px 72px rgba(0, 0, 0, .6),
    0 0 46px color-mix(in srgb, var(--c1) 30%, transparent);
}

.ball.active { border-color: color-mix(in srgb, var(--c1) 65%, #fff); }

.ball-logo {
  position: relative;
  z-index: 3;
  display: block;
  width: 86%;
  height: 62%;
  object-fit: contain;
  filter: drop-shadow(0 4px 12px rgba(0, 0, 0, .5)) brightness(1.06);
  pointer-events: none;
}

.ball-name {
  position: relative;
  z-index: 3;
  display: block;
  max-width: 150px;
  padding: 0 8px;
  font-size: 22px;
  font-weight: 900;
  line-height: 1.05;
  letter-spacing: -.02em;
  text-shadow: 0 2px 12px rgba(0, 0, 0, .5);
}

.ball-logo + .ball-name {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Source-specific contrast fix for the one dark-artwork local logo.
   assets/logos/stake.webp is a near-black "Stake" wordmark; on the dark V2
   shell (brand header, selected-offer card, selector ball) it is otherwise
   invisible — and .offer-head.has-logo hides the text fallback. Force it to a
   white silhouette (transparency preserved -> a wordmark, not a rectangle),
   matching V1's .logo-stake treatment. The [src$=] selector matches only this
   asset, which no other brand or offer uses, so no other logo is affected. */
img[src$="/assets/logos/stake.webp"] {
  filter: brightness(0) invert(1) drop-shadow(0 3px 10px rgba(0, 0, 0, .6)) !important;
}

.b0 { right: -1%; top: 4%; }
.b1 { right: -8%; top: 37%; }
.b2 { right: 7%; bottom: -1%; }
.b3 { left: 0; bottom: 2%; }
.b4 { left: -7%; top: 23%; }

@keyframes floatBall {
  0%, 100% { translate: 0 0; rotate: -.8deg; }
  50% { translate: 7px -23px; rotate: .8deg; }
}

/* -------------------------------------------------------- hub brand grid */

.hero--hub { align-items: start; }

.brand-grid {
  position: relative;
  z-index: 2;
  width: min(var(--wrap), calc(100% - 48px));
  margin: 8px auto 64px;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 14px;
}

.brand-card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: 76px;
  padding: 16px 18px;
  border-radius: 16px;
  text-decoration: none;
  color: #fff;
  background: linear-gradient(180deg, rgba(12, 14, 18, .72), rgba(5, 7, 10, .6));
  border: 1px solid var(--hair);
  transition: transform .16s ease, box-shadow .16s ease, border-color .16s ease;
}

.brand-card:hover,
.brand-card:focus-visible {
  transform: translateY(-2px);
  border-color: color-mix(in srgb, var(--c1) 40%, transparent);
  box-shadow: 0 16px 40px rgba(0, 0, 0, .4);
}

.brand-card__text {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
  flex: 1 1 auto;
}
/* Single line, truncated with ellipsis if a name would otherwise wrap next to
   the logo — keeps every card the SAME height (a wrapped name in one grid
   row would stretch every card sharing that row) rather than growing some
   cards taller than others. Truncation is rare at the desktop grid's minimum
   column width (the logo is sized to its own natural width below, not a
   fixed reservation) but stays as a safety net for narrow mobile cards. */
.brand-card__name {
  font-size: 19px;
  font-weight: 800;
  letter-spacing: -.01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.brand-card__go { font-size: 11px; letter-spacing: .12em; text-transform: uppercase; color: var(--c1); font-weight: 800; }

/* Reuses each brand's existing local header-mark asset (self::BRAND_SHELL in
   Renderer.php) — no new asset. flex: 0 0 auto (not a fixed flex-basis) sizes
   this to the LOGO's own natural width at max-height, capped at 120px — an
   icon-shaped logo (e.g. R7, GAMA) takes only what it needs, so the text
   column (which has priority via .brand-card__text's flex:1) is never
   squeezed by logos that don't need the full 120px, while a wide wordmark
   still stays under the cap and never overpowers the brand name. */
.brand-card__logo {
  flex: 0 0 auto;
  max-width: 120px;
  min-width: 0;
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
}
.brand-card__logo img {
  display: block;
  max-width: 100%;
  max-height: 44px;
  width: auto;
  height: auto;
  object-fit: contain;
  filter: drop-shadow(0 3px 8px rgba(0, 0, 0, .35));
}

/* ----------------------------------------------------------- SEO article */

.article {
  position: relative;
  z-index: 2;
  width: min(calc(var(--read) + 88px), calc(100% - 32px));
  margin: 8px auto 0;
  padding: 40px 44px 60px;
  border-radius: 24px 24px 0 0;
  background: linear-gradient(180deg, rgba(6, 9, 13, .52), rgba(6, 9, 13, .82) 220px);
  border: 1px solid var(--hair);
  border-bottom: 0;
}

.article nav {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 4px;
  align-items: baseline;
  font-size: 14px;
  color: var(--muted);
  padding-bottom: 22px;
  margin-bottom: 30px;
  border-bottom: 1px solid var(--hair);
}

.article nav a { color: var(--c1); text-decoration: none; }
.article nav a:hover { text-decoration: underline; }

.article section { margin: 0 0 34px; }

.article h2 {
  margin: 0 0 12px;
  font-size: clamp(21px, 2.4vw, 27px);
  line-height: 1.25;
  letter-spacing: -.01em;
  font-weight: 800;
}

.article p {
  margin: 0;
  color: #d7ded9;
  font-size: 16.5px;
  line-height: 1.75;
}

/* ------------------------------------------- secondary "Другие варианты"
   The hero's RIGHT column (product requirement, revised after live visual
   QA: visible in the first viewport, never below the article any more) — a
   compact selected-offer card and a plain wrapped row of the same selector
   balls (no big machine/orbit, which would waste the space it now
   occupies). Same selector JS drives it as before. */
.alt-offers {
  min-width: 0;
  align-self: center;
}
.alt-offers__title {
  margin: 0 0 18px;
  font-size: clamp(18px, 2.1vw, 23px);
  line-height: 1.25;
  font-weight: 800;
  letter-spacing: -.01em;
}
.alt-offers .offer-card {
  margin: 0 0 24px;
  max-width: 500px;
}
.alt-offers .stage {
  position: static;
  height: auto;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
}
.alt-offers .machine { display: none; }
.alt-offers .ball,
.alt-offers .b0, .alt-offers .b1, .alt-offers .b2, .alt-offers .b3, .alt-offers .b4 {
  position: static !important;
  inset: auto !important;
  transform: none;
  width: 132px;
  height: 132px;
  margin: 0;
}
.alt-offers .ball:hover,
.alt-offers .ball:focus-visible { transform: scale(1.04); }
.alt-offers .ball.active { transform: scale(1.05); }
.alt-offers .ball-logo { width: 82%; height: 60%; }
.alt-offers .ball-name { font-size: 14px; max-width: 96px; }

@media (max-width: 760px) {
  /* Stacks 4th in source order — after the primary card, before .article
     (see the mobile .hero rules below) — so a plain top margin is enough;
     no divider/border needed since it was never "below" anything else. */
  .alt-offers { margin-top: 28px; }
  .alt-offers .offer-card { max-width: none; }
  .alt-offers .stage { justify-content: center; }
  .alt-offers .ball,
  .alt-offers .b0, .alt-offers .b1, .alt-offers .b2, .alt-offers .b3, .alt-offers .b4 {
    width: 120px;
    height: 120px;
  }
}

/* --------------------------------------------------------------- footer */

.site-footer {
  position: relative;
  z-index: 2;
  border-top: 1px solid var(--hair);
  background: #04070a;
}

.site-footer p {
  width: min(var(--wrap), calc(100% - 48px));
  margin: 0 auto;
  padding: 22px 0;
  font-size: 12px;
  color: #6a756f;
  text-align: center;
}

/* ------------------------------------------------------------------ 404 */

.page--notfound .notfound {
  position: relative;
  z-index: 2;
  width: min(var(--read), calc(100% - 40px));
  margin: auto;
  min-height: calc(100vh - 180px);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 8px;
  padding: 60px 0;
}

.page--notfound h1 { margin: 0; font-size: clamp(64px, 12vw, 120px); font-weight: 900; letter-spacing: -.05em; }
.page--notfound .cta { margin-top: 18px; }

/* ------------------------------------------------------------ responsive */

@media (max-width: 1080px) {
  .hero {
    grid-template-columns: 1fr;
    gap: 26px;
    align-items: start;
    min-height: 0;
  }
  .copy { max-width: none; }
  .stage { height: 560px; }
  .machine { width: 420px; height: 420px; }
  .ball { width: 184px; height: 184px; }
  .b0 { right: 2%; }  .b1 { right: -4%; }  .b2 { right: 8%; }
  .b3 { left: 2%; }   .b4 { left: -4%; }
}

@media (max-width: 760px) {
  .page {
    background-attachment: scroll;
    min-height: 100svh;
  }

  /* the roulette flourish is a desktop-only decoration — drop it entirely on
     small screens so the browser never fetches roulette.webp on mobile */
  .page::after {
    content: none;
    display: none;
    background-image: none;
  }

  /* hard width containment: auto width + fixed side margins beats any
     calc()/min()/grid-track edge case that could exceed the viewport */
  .top,
  .hero,
  .brand-grid,
  .article {
    width: auto;
    max-width: 100%;
    margin-left: 14px;
    margin-right: 14px;
  }
  .alt-offers, .alt-offers__grid { max-width: 100%; min-width: 0; }
  .site-footer p { width: auto; max-width: 100%; }

  .top { min-height: 62px; }
  .brand-logo { max-width: 118px; max-height: 32px; }

  /* single column, plain block flow — no grid min-track overflow */
  .hero {
    display: block;
    min-height: 0;
    padding: 14px 0 36px;
  }
  .hero > * { max-width: 100%; min-width: 0; }
  .hero > .copy,
  .hero > .stage,
  .hero > .alt-offers { width: 100%; }

  .hero h1 { font-size: clamp(30px, 8.4vw, 42px); line-height: 1.06; }
  .lead { font-size: 15px; margin-top: 16px; }

  /* Stacking order on mobile (source order, per .hero markup below): SEO
     logo/title -> lead -> primary offer card (inline in .copy) ->
     "Другие варианты" (.alt-offers) -> .article. */
  .offer-card { width: 100%; max-width: 100%; margin-top: 22px; padding: 16px; }
  .offer-head.has-logo .offer-logo { min-width: 150px; }
  .offer-logo img { max-height: 60px; }
  .actions { display: grid; grid-template-columns: 1fr; }
  .cta, .switch { width: 100%; min-width: 0; }

  /* balls become a clean, centred 2-col grid — no absolute positioning */
  .stage {
    height: auto;
    margin-top: 22px;
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 12px;
    justify-items: center;
    align-items: start;
    padding: 0;
  }
  .machine { display: none; }
  .ball,
  .b0, .b1, .b2, .b3, .b4 {
    position: static !important;
    inset: auto !important;
    margin: 0;
    transform: none;
    width: 100%;
    max-width: 150px;
    height: auto;
    aspect-ratio: 1 / 1;
  }
  .b4 { grid-column: 1 / -1; }
  .ball:hover, .ball:focus-visible { transform: none; }
  .ball.active { transform: scale(1.04); }
  .ball-name { font-size: clamp(15px, 4.4vw, 19px); max-width: 108px; }

  .article { padding: 26px 16px 44px; border-radius: 18px 18px 0 0; }
  .article nav { overflow-wrap: anywhere; }
  .brand-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }

  /* Compact cards at 2-column mobile width: smaller padding/min-height and a
     noticeably smaller logo cap ("where space allows") so text stays fully
     readable and nothing overflows; height barely changes from the
     logo-less card. */
  .brand-card { min-height: 68px; padding: 12px 14px; gap: 8px; }
  .brand-card__name { font-size: 16px; }
  .brand-card__logo { max-width: 56px; }
  .brand-card__logo img { max-height: 28px; }
}

@media (max-width: 400px) {
  .hero h1 { font-size: clamp(27px, 8.6vw, 34px); }
  .ball, .b0, .b1, .b2, .b3, .b4 { max-width: 138px; }
  .ball-name { font-size: 15px; max-width: 92px; }
}

@media (max-width: 330px) {
  .brand-grid { grid-template-columns: 1fr; }
  .stage { grid-template-columns: 1fr; }
  .b4 { grid-column: auto; }
}

@media (prefers-reduced-motion: reduce) {
  .ball { animation: none; }
  .ball:hover, .ball:focus-visible, .ball.active { transform: none; }
  .brand-card { transition: none; }
}
