/* ===========================================================================
   SIM MASTER — sections that belong to INNER pages, not the homepage.

   sections.css is deliberately "homepage sections, in page order". Anything
   a subpage introduces lives here instead, so neither file becomes a junk
   drawer. Subpages link both.

   Everything below reuses the existing design language rather than inventing
   a second one: the same .eyebrow / .lede / .btn primitives, the same
   red-tinted --line-* hairlines, the same [data-reveal] entrance system, and
   --space-section for vertical rhythm (see CLAUDE.md 0.1.3).
   =========================================================================== */

/* ---- Page hero ---------------------------------------------------------
   A compact masthead for inner pages — deliberately NOT the homepage hero,
   which is a full-bleed image the height of the viewport. This one is type
   only, so a subpage gets to its content immediately.
   ------------------------------------------------------------------------ */

.page-hero {
  position: relative;
  isolation: isolate;
  padding-block: calc(var(--space-section) * 0.85) var(--space-section);
  background:
    radial-gradient(ellipse 70% 60% at 12% 0%, rgba(0, 35, 41, 0.85), transparent 62%),
    var(--surface-base);
  border-bottom: 1px solid var(--line-faint);
  overflow: hidden;
}

  /*
    NO max-width here. This element also carries .shell, which is
    `max-width: var(--shell-max); margin-inline: auto` — so any narrower
    max-width does not merely cap the text, it REPLACES the shell width and
    the smaller box is then re-centred by that `auto`, pushing its left edge
    inward (256px at 1920 with the old 52rem). Every section below uses the
    full shell, so the hero read as indented while they read as flush left.
    The homepage never had this because .hero__inner leaves the shell alone
    and caps its TEXT instead (.hero__body { max-width: 42ch }) — same
    approach used here and on .corp-hero__title. Cap text, never the shell.
  */
  .page-hero__inner {
    position: relative;
    z-index: 1;
    display: grid;
    justify-items: start;
    gap: var(--space-sm);
  }

  .page-hero__title {
    margin: 0;
    max-width: 20ch;
    font-size: var(--fs-h1);
    font-weight: 800;
    line-height: var(--lh-tight);
    letter-spacing: var(--tracking-display);
    text-transform: uppercase;
  }

  .page-hero__lede {
    margin: 0;
    max-width: 46ch;
  }

  /*
    A faint technical wheel-face schematic bleeding off the right edge — the
    same "blueprint" register as .grid-backdrop, just a real diagram instead
    of a dot grid. It is its OWN pseudo-element rather than a second layer on
    `.grid-backdrop` deliberately: that class is shared by every hero-style
    section sitewide (homepage, .corp-hero...), so painting onto it here
    would leak the wheel onto pages this was never meant for. `z-index: 0`
    keeps it below `.page-hero__inner` (z-index: 1) inside the section's own
    stacking context (`isolation: isolate` on `.page-hero`).

    The source asset is a near-invisible watermark tuned for a LIGHT ground
    (alpha peaks at 28/255) — recoloured to --text-secondary's white and its
    alpha roughly tripled so it survives being composited onto this dark one;
    see assets/schematics/ for the one-off processing script's own notes.

    Hidden below 64rem: at phone/tablet widths there is no room beside the
    title for it to read as anything but noise, and skipping the
    `background-image` there means that viewport never pays for the asset.

    WHICH drawing appears is chosen by `data-hero-mark` on <body>, so the four
    .page-hero pages do not all wear the same picture: the wheel stays on
    /usluge/ (it is a wheel-face, and that page is about the rigs), while
    /cenovnik/, /rezervacije/ and /kontakt/ get a tyre, a lap timer and a
    pedal box. The wheel is the DEFAULT rather than its own attribute value,
    so a page that forgets the attribute still gets a drawing.

    The three new marks are SVG, not WebP derivatives. The wheel is a raster
    because it arrived as one (owner-supplied product art); these are drawn in
    tools/build_hero_schematics.py, and hairline line art is exactly what SVG
    is for — one file instead of a 1x/2x pair, no resampling of 2px strokes,
    ~10-30 KB each. Nothing here cares about the format; it is one URL.
  */
  .page-hero::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    display: none;
    pointer-events: none;
    background-repeat: no-repeat;
    background-position: 102% 50%;
    background-size: min(46rem, 58%) auto;
    opacity: 0.55;
    -webkit-mask-image: linear-gradient(to left, #000 45%, transparent 92%);
            mask-image: linear-gradient(to left, #000 45%, transparent 92%);
  }

  /*
    Below 64rem the mark is shown too (owner request) — but heavily dimmed and
    pushed further off the right edge so it never competes with the heading.
    Scoped off `.article-page`, whose masthead reuses this same pseudo-element
    for the article's lead photo and must keep its own treatment. Kept in its
    own max-width query so it cannot outrank the >=64rem block by specificity.
  */
  @media (max-width: 63.9375rem) {
    body:not(.article-page) .page-hero::after {
      display: block;
      opacity: 0.24;
      background-position: 78% 38%;
      background-size: min(34rem, 128%) auto;
      -webkit-mask-image: linear-gradient(to left, #000 35%, rgba(0, 0, 0, 0.55) 80%, transparent 100%);
              mask-image: linear-gradient(to left, #000 35%, rgba(0, 0, 0, 0.55) 80%, transparent 100%);
      background-image: url("../img/sema-volan-900.webp");
    }

    body[data-hero-mark="tyre"] .page-hero::after {
      background-image: url("../img/sema-guma.svg");
    }

    body[data-hero-mark="stopwatch"] .page-hero::after {
      background-image: url("../img/sema-stoperica.svg");
    }

    body[data-hero-mark="pedals"] .page-hero::after {
      background-image: url("../img/sema-pedale.svg");
    }
  }

  @media (min-width: 64rem) {
    .page-hero::after {
      display: block;
      background-image: url("../img/sema-volan-900.webp");
      background-image: image-set(
        url("../img/sema-volan-900.webp") 1x,
        url("../img/sema-volan-1600.webp") 2x
      );
    }

    /*
      Sized by HEIGHT, not width, unlike the default wheel mark. Both the
      tyre and the stopwatch are drawn zoomed past their own 1600x800 sheet
      (see tools/build_hero_schematics.py's own notes on why), so their top
      and bottom edges are a hard crop baked into the SVG itself. Sized by
      the shared width rule (min(46rem, 58%) -> 736px wide, 368px tall) that
      box comes out SHORTER than the hero (~423-460px depending on page copy
      length), so the crop edge lands in mid-air with empty ground below it
      and reads as a visible cut. At 102% of the hero's own height the crop
      falls outside the section instead, where `overflow: hidden` and the
      bottom border hide it. Do not "simplify" either of these back to the
      shared width rule.
    */
    [data-hero-mark="tyre"] .page-hero::after,
    [data-hero-mark="stopwatch"] .page-hero::after {
      background-size: auto 102%;
    }

    [data-hero-mark="tyre"] .page-hero::after {
      background-image: url("../img/sema-guma.svg");
    }

    [data-hero-mark="stopwatch"] .page-hero::after {
      background-image: url("../img/sema-stoperica.svg");
    }

    [data-hero-mark="pedals"] .page-hero::after {
      background-image: url("../img/sema-pedale.svg");
    }
  }

/* ---- Pricing grid ------------------------------------------------------ */

.pricing {
  background: var(--color-black);
}

  .pricing__head {
    margin-bottom: var(--space-2xl);
  }

  .pricing__title {
    margin-top: var(--space-sm);
    font-size: var(--fs-h2);
    font-weight: 800;
    line-height: var(--lh-snug);
    text-transform: uppercase;
  }

  ul.pricing__grid {
    display: grid;
    gap: var(--space-lg);
    margin: 0;
    padding: 0;
    list-style: none;
  }

  @media (min-width: 44rem) {
    ul.pricing__grid {
      grid-template-columns: repeat(2, minmax(0, 1fr));
    }
  }

  @media (min-width: 68rem) {
    ul.pricing__grid {
      grid-template-columns: repeat(3, minmax(0, 1fr));
    }
  }

  /* ------------------------------------------------------------ the card */

  .price-card__inner {
    display: flex;
    flex-direction: column;
    height: 100%;
    background: linear-gradient(175deg, var(--surface-panel), var(--surface-void) 70%);
    border: 1px solid var(--line-faint);
    border-radius: var(--radius-md);
    overflow: hidden;
    transition: border-color var(--dur-base) var(--ease-out);
  }

  .price-card__inner:hover {
    border-color: var(--line-strong);
  }

  .price-card__media {
    position: relative;
    display: grid;
    place-items: center;
    /*
      Square with `contain`, matching the rig rows on the homepage — the rig
      photos are portrait or near-square, so a landscape frame would leave
      wide empty gutters either side of each one.
    */
    aspect-ratio: 1 / 1;
    padding: var(--space-sm);
    overflow: hidden;
    background: var(--surface-void);
  }

  .price-card__media img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    filter: drop-shadow(0 1.5rem 2rem rgba(0, 0, 0, 0.6));
    transition: transform var(--dur-slow) var(--ease-out);
  }

  .price-card__inner:hover .price-card__media img {
    transform: scale(1.03);
  }

  .price-card__body {
    display: flex;
    flex-direction: column;
    gap: var(--space-sm);
    flex: 1;
    padding: var(--space-lg);
  }

  .price-card__name {
    margin: 0;
    font-size: var(--fs-h4);
    font-weight: 700;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--text-warm);
  }

  ul.price-card__specs {
    display: grid;
    gap: 0.5rem;
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: var(--fs-body-sm);
    color: var(--text-secondary);
  }

  /* Small red tick-marks rather than bullets — same accent role as the rig
     spec dots on the homepage. */
  ul.price-card__specs li {
    position: relative;
    padding-left: 1rem;
  }

  ul.price-card__specs li::before {
    content: "";
    position: absolute;
    top: 0.55em;
    left: 0;
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: var(--action);
  }

/* ---- Rate rows ---------------------------------------------------------
   Shared by the pricing cards and the rental block, so a 30 min rate and a
   48 h rate are typeset identically wherever they appear.
   ------------------------------------------------------------------------ */

/* Shared layout only — no background/positioning here. The card-only footer
   band is scoped below. (The rental blocks on /cenovnik/ and
   /iznajmljivanje-simulatora/ used to borrow this class outside a card to
   show 24h/48h rates; the owner had those prices removed — the rental is now
   inquiry-only — so that use is gone.) */
.price-card__rates {
  display: grid;
  gap: var(--space-xs);
  margin: auto 0 0;
}

  /*
    IN A CARD the rate block is a FOOTER BAND, not a last line of text: it
    bleeds out to the card's edges with negative margins that cancel
    .price-card__body's `padding: var(--space-lg)`, so the price sits on its
    own darker ground under a red hairline. Before this it shared the body's
    background and read as one more spec line — the owner's note was that the
    prices "look like they are just part of the text".

    Scoped to .price-card__body on purpose. Applying it to the bare class
    would drag those negative margins onto .rental__rates, which is not
    inside a padded card and would bleed out of its column.

    Keep the negative margins in step with .price-card__body's padding.
  */
  .price-card__body .price-card__rates {
    margin-inline: calc(var(--space-lg) * -1);
    margin-bottom: calc(var(--space-lg) * -1);
    padding: var(--space-md) var(--space-lg);
    background: var(--surface-void);
    border-top: 1px solid var(--line-strong);
  }

  .price-rate {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-sm);
  }

  .price-rate__term {
    font-family: var(--font-mono);
    font-size: var(--fs-mono-label);
    /* NOT --tracking-mono (0.18em) and NOT uppercase: these labels are two or
       three characters ("1h", "30min"), so that tracking spaced "1h" out into
       what read as "1 H", and the uppercase turned the unit into a capital.
       The owner asked specifically for a lowercase, unspaced "1h". */
    letter-spacing: 0.04em;
    color: var(--text-muted);
  }

  .price-rate__value {
    display: flex;
    align-items: baseline;
    gap: 0.35rem;
    margin: 0;
    font-family: var(--font-numeric);
    font-size: clamp(2rem, 1.5rem + 1.4vw, 2.6rem);
    font-weight: 700;
    line-height: 1;
    /* Pure white, a step brighter than the --text-primary body copy around
       it — the number is the thing being looked up on this page. */
    color: var(--color-white);
    /* Rates line up column-wise even when digit counts differ. */
    font-variant-numeric: tabular-nums;
  }

  .price-rate__cur {
    font-family: var(--font-mono);
    font-size: var(--fs-mono-label);
    font-weight: 500;
    letter-spacing: var(--tracking-mono);
    color: var(--text-accent);
  }


/* ---- Promo strip ------------------------------------------------------- */

/*
  The free-Monster line is a genuine offer, so it is styled as a CALLOUT, not
  a footnote. It was small mono label text in --text-secondary on flat
  --surface-void, which read as a caption under the price cards and got
  skipped. It now gets the site's red accent treatment: a red-tinted ground,
  a --line-strong border, a solid accent bar down the left edge, and the copy
  at display size in pure white.

  Deliberately RED, not Monster's brand green: the palette is the site's
  (§8/§9), and introducing a second accent colour for one strip would import
  a competing visual system. The logo carries the brand identity on its own.
*/
.pricing__promo {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-md);
  margin: var(--space-2xl) 0 0;
  padding: var(--space-lg) var(--space-xl);
  overflow: hidden;
  background:
    radial-gradient(ellipse 70% 140% at 0% 50%, rgba(232, 19, 14, 0.20), transparent 70%),
    linear-gradient(100deg, var(--surface-raised), var(--surface-void) 65%);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-md);
  font-family: var(--font-display);
  font-size: var(--fs-h4);
  font-weight: 700;
  line-height: var(--lh-snug);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--color-white);
}

  /* Solid accent bar down the leading edge — same device as the community
     CTA panel's left rule, so the two read as one system. */
  .pricing__promo::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    width: 4px;
    height: 100%;
    background: var(--action);
  }

  .pricing__promo img {
    height: 2.75rem;
    width: auto;
    flex-shrink: 0;
  }

  .pricing__promo span {
    flex: 1;
    min-width: 12ch;
  }

  @media (max-width: 40rem) {
    .pricing__promo {
      padding: var(--space-md) var(--space-lg);
      font-size: var(--fs-body-lg);
    }

    .pricing__promo img {
      height: 2.25rem;
    }
  }

/* ---- Rental ------------------------------------------------------------ */

.rental {
  background: var(--surface-base);
  border-top: 1px solid var(--line-faint);
}

  .rental__inner {
    display: grid;
    gap: var(--space-2xl);
    align-items: start;
  }

  @media (min-width: 62rem) {
    .rental__inner {
      grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
      gap: var(--space-3xl);
    }
  }

  /* Mirrored rental block (the kids simulator on /iznajmljivanje-simulatora/):
     photo left, copy right. DOM order stays copy-then-media, so the phone
     stack still reads heading -> text -> picture like every other block. */
  @media (min-width: 62rem) {
    .rental__inner--flip {
      grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
    }

    .rental__inner--flip .rental__copy {
      order: 2;
    }
  }

  .rental__title {
    margin: var(--space-sm) 0 var(--space-md);
    font-size: var(--fs-h2);
    font-weight: 800;
    line-height: var(--lh-snug);
    text-transform: uppercase;
  }

  .rental__lede {
    margin: 0 0 var(--space-lg);
    max-width: 48ch;
  }

  /* Flex-wrap, not a fixed 3-track grid: this block now carries one or two
     columns (the rental's rates were removed at the owner's request), and a
     fixed grid left an empty track hanging off the right. Wrapping keeps
     whatever columns there are packed to the left. */
  .rental__cols {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-lg) var(--space-2xl);
    margin-bottom: var(--space-lg);
  }

  .rental__col {
    flex: 0 1 12rem;
  }

  .rental__col-label {
    margin: 0 0 var(--space-2xs);
    font-family: var(--font-mono);
    font-size: var(--fs-mono-label);
    letter-spacing: var(--tracking-mono);
    text-transform: uppercase;
    color: var(--text-accent);
  }

  .rental__col ul,
  .rental__games ul {
    display: grid;
    gap: 0.45rem;
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: var(--fs-body-sm);
    color: var(--text-secondary);
  }

  .rental__games {
    margin-bottom: var(--space-xl);
  }

  /* Game titles as chips: a flat list of six reads as a wall, and these are
     proper nouns worth spacing out. */
  ul.rental__game-list {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2xs);
  }

  ul.rental__game-list li {
    padding: 0.3rem 0.65rem;
    border: 1px solid var(--line-faint);
    border-radius: var(--radius-sm);
    font-size: var(--fs-caption);
    color: var(--text-secondary);
  }

  .rental__cta {
    margin-top: var(--space-2xs);
  }

  /* Inquiry note under the Instagram-DM CTAs on /iznajmljivanje-simulatora/ */
  .ig-note {
    margin: var(--space-sm) 0 0;
    max-width: 46ch;
    font-size: var(--fs-body-sm);
    color: var(--text-secondary);
  }

  .final__inner .ig-note {
    margin-inline: auto;
  }

  .ig-note a {
    color: var(--action-text);
    text-decoration: underline;
    text-underline-offset: 2px;
  }

  .ig-note a:hover {
    color: var(--color-white);
  }

  .rental__media {
    border: 1px solid var(--line-soft);
    border-radius: var(--radius-md);
    overflow: hidden;
    box-shadow: var(--shadow-lg);
  }

  .rental__media img {
    display: block;
    width: 100%;
    height: auto;
  }

@media (prefers-reduced-motion: reduce) {
  .price-card__inner:hover .price-card__media img {
    transform: none;
  }
}

/* ---- Booking (/rezervacije/) -------------------------------------------
   Form on the left, a short "good to know" rail on the right. The rail is
   deliberately NOT a second form: it carries the facts a visitor needs while
   filling this one in (Monday closed, opening hours, capacity) plus a phone
   fallback, so nobody has to leave the page to check them.
   ------------------------------------------------------------------------ */

.booking {
  background: var(--color-black);
}

  .booking__inner {
    display: grid;
    gap: var(--space-2xl);
    align-items: start;
  }

  @media (min-width: 62rem) {
    .booking__inner {
      grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
      gap: var(--space-3xl);
    }

    /* Sticks while the form is scrolled — the rail is short, the form is not. */
    .booking__aside {
      position: sticky;
      top: calc(var(--header-h) + var(--space-lg));
    }
  }

  .booking__head {
    margin-bottom: var(--space-xl);
  }

  .booking__title {
    margin-top: var(--space-sm);
    font-size: var(--fs-h2);
    font-weight: 800;
    line-height: var(--lh-snug);
    text-transform: uppercase;
  }

  .booking__aside {
    display: grid;
    gap: var(--space-md);
  }

  .booking__card {
    display: grid;
    gap: var(--space-sm);
    padding: var(--space-lg);
    background: linear-gradient(175deg, var(--surface-panel), var(--surface-void) 70%);
    border: 1px solid var(--line-faint);
    border-radius: var(--radius-md);
  }

  .booking__card-label {
    margin: 0;
    font-family: var(--font-mono);
    font-size: var(--fs-mono-label);
    letter-spacing: var(--tracking-mono);
    text-transform: uppercase;
    color: var(--text-accent);
  }

  ul.booking__facts {
    display: grid;
    gap: 0.6rem;
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: var(--fs-body-sm);
    color: var(--text-secondary);
  }

  ul.booking__facts li {
    position: relative;
    padding-left: 1rem;
  }

  ul.booking__facts li::before {
    content: "";
    position: absolute;
    top: 0.55em;
    left: 0;
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: var(--action);
  }

  .booking__phone {
    font-family: var(--font-display);
    font-size: var(--fs-h4);
    font-weight: 700;
    letter-spacing: 0.02em;
    color: var(--text-primary);
    text-decoration: none;
    font-variant-numeric: tabular-nums;
    transition: color var(--dur-fast) var(--ease-out);
  }

  .booking__phone:hover {
    color: var(--action-text);
  }

  .booking__ig {
    font-weight: 600;
    color: var(--text-primary);
    text-decoration: none;
    overflow-wrap: anywhere;
    transition: color var(--dur-fast) var(--ease-out);
  }

  .booking__ig:hover {
    color: var(--action-text);
  }

  .booking__prices {
    justify-self: start;
  }

/* ---- Contact (/kontakt/) -----------------------------------------------
   The page reuses the /rezervacije/ shell wholesale (.booking + the aside
   rail + css/forms.css); only the rail's two extra content shapes are new:
   a stacked list of contact links, and a short paragraph above a link-arrow.
   ------------------------------------------------------------------------ */

  ul.contact__links {
    display: grid;
    gap: 0.35rem;
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: var(--fs-body-sm);
  }

  .contact__links a {
    color: var(--text-secondary);
    text-decoration: none;
    overflow-wrap: anywhere;
    transition: color var(--dur-fast) var(--ease-out);
  }

  .contact__links a:hover {
    color: var(--action-text);
  }

  .contact__note {
    margin: 0;
    font-size: var(--fs-body-sm);
    color: var(--text-secondary);
  }

/* ---- Simulators (/usluge/) ---------------------------------------------
   One large alternating block per simulator, then optional deep-dive spec
   cards underneath it. Same alternating logic as the homepage rig rows: the
   swap is presentational only (`order`), so reading order stays media-then-
   copy on every screen and in every assistive tech.
   ------------------------------------------------------------------------ */

.capacity {
  background: var(--surface-base);
  border-bottom: 1px solid var(--line-faint);
}

  /* No max-width — this carries .shell; see the note on .page-hero__inner.
     .capacity__body already caps itself at 52ch, so the old 54rem here only
     ever re-centred the shell and indented the block. */
  .capacity__inner {
    display: grid;
    justify-items: start;
    gap: var(--space-sm);
  }

  .capacity__title {
    margin: 0;
    font-size: var(--fs-h2);
    font-weight: 800;
    line-height: var(--lh-snug);
    text-transform: uppercase;
  }

  .capacity__body {
    margin: 0;
    max-width: 52ch;
  }

/*
  Alternating background so consecutive simulator blocks read as separate
  chapters rather than one long scroll.

  Driven by explicit .sim--alt / .sim--flip classes from the builder, NOT by
  :nth-of-type. The <section> siblings inside <main> also include page-hero,
  capacity, wheels, games and final, so nth-of-type parity does not line up
  with the simulator list's own index.
*/
.sim {
  background: var(--color-black);
}

.sim--alt {
  background: var(--surface-base);
}

  .sim__inner {
    display: grid;
    gap: var(--space-xl);
    align-items: center;
  }

  @media (min-width: 62rem) {
    .sim__inner {
      grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
      gap: var(--space-3xl);
    }

    /* Flipped blocks put the copy first visually; DOM order is unchanged. */
    .sim--flip .sim__copy {
      order: -1;
    }
  }

  .sim__media {
    position: relative;
    display: grid;
    place-items: center;
    /*
      Square with `contain`, matching the homepage rig rows — the source
      photos are portrait or near-square, so a landscape frame would leave
      wide empty gutters either side of every one of them.
    */
    aspect-ratio: 1 / 1;
    padding: var(--space-sm);
    overflow: hidden;
    border-radius: var(--radius-md);
    border: 1px solid var(--line-faint);
    background: var(--surface-void);
  }

  .sim__media img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    filter: drop-shadow(0 1.5rem 2rem rgba(0, 0, 0, 0.6));
  }

  /*
    The Motion clip is 9:16 and is pinned to one inset box shared with its
    poster, so the two are always pixel-identical and the poster can never
    peek out from behind the clip. See CLAUDE.md §0.1.8 for the four traps
    this arrangement avoids — do not "simplify" it back to auto sizing.
  */
  .sim__media--video {
    aspect-ratio: 480 / 660;
    width: 72.73%;
    justify-self: center;
    padding: 0;
    --video-border: 0.4rem;
  }

  .sim__media--video .motion__poster,
  .sim__media--video .motion__video {
    position: absolute;
    top: var(--video-border);
    left: var(--video-border);
    display: block;
    width: calc(100% - var(--video-border) * 2);
    height: calc(100% - var(--video-border) * 2);
    object-fit: cover;
    object-position: 50% 100%;
    border-radius: var(--radius-sm);
    filter: none;
  }

  .sim__title {
    margin: var(--space-sm) 0 var(--space-md);
    font-size: var(--fs-h2);
    font-weight: 800;
    line-height: var(--lh-snug);
    text-transform: uppercase;
  }

  .sim__lede {
    margin: 0 0 var(--space-md);
    max-width: 52ch;
  }

  .sim__body {
    margin: 0 0 var(--space-lg);
    max-width: 54ch;
    font-size: var(--fs-body-sm);
    color: var(--text-secondary);
  }

  .sim__specs {
    padding-top: var(--space-md);
    border-top: 1px solid var(--line-faint);
  }

  .sim__specs-label {
    margin: 0 0 var(--space-sm);
    font-family: var(--font-mono);
    font-size: var(--fs-mono-label);
    letter-spacing: var(--tracking-mono);
    text-transform: uppercase;
    color: var(--text-muted);
  }

  .sim__specs ul {
    display: grid;
    gap: 0.65rem;
    margin: 0;
    padding: 0;
    list-style: none;
  }

  .sim__specs li {
    display: grid;
    grid-template-columns: 2.25rem 1fr;
    align-items: start;
    gap: var(--space-2xs);
    font-size: var(--fs-body-sm);
    line-height: 1.45;
    color: var(--text-primary);
  }

  /* ------------------------------------------------------ deep-dive cards */

  .sim__details {
    display: grid;
    gap: var(--space-md);
    margin-top: var(--space-2xl);
  }

  @media (min-width: 48rem) {
    .sim__details {
      grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
    }
  }

  .spec-card {
    display: grid;
    gap: var(--space-2xs);
    padding: var(--space-lg);
    background: linear-gradient(175deg, var(--surface-panel), var(--surface-void) 70%);
    border: 1px solid var(--line-faint);
    border-radius: var(--radius-md);
    transition: border-color var(--dur-base) var(--ease-out);
  }

  .spec-card:hover {
    border-color: var(--line-strong);
  }

  .spec-card__name {
    margin: 0;
    font-size: var(--fs-h4);
    font-weight: 700;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--text-warm);
  }

  .spec-card__text {
    margin: 0;
    font-size: var(--fs-body-sm);
    color: var(--text-secondary);
  }

/* ---- Corporate events (/korporativna-desavanja/) -----------------------
   Editorial, image-led page: a full-bleed hero, alternating photo/text
   blocks, and two full-width photo bands used as chapter breaks. Deliberately
   NOT a card grid — the original page told its story through big imagery and
   this rebuild keeps that.
   ------------------------------------------------------------------------ */

.corp-hero {
  position: relative;
  isolation: isolate;
  display: flex;
  align-items: flex-end;
  min-height: min(42rem, calc(100svh - var(--header-h)));
  /* Height-aware like the homepage hero: the --space-* tokens only track
     viewport WIDTH, so on a short-but-wide screen they push the CTA off the
     bottom. See CLAUDE.md §0.1.8. */
  padding-block: min(var(--space-3xl), 14vh) min(var(--space-2xl), 9vh);
  overflow: hidden;
  background: var(--surface-void);
}

  .corp-hero__media {
    position: absolute;
    inset: 0;
    z-index: -1;
  }

  .corp-hero__photo {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: 50% 45%;
  }

  .corp-hero__grade {
    position: absolute;
    inset: 0;
    background:
      linear-gradient(to top, var(--surface-void) 4%, rgba(0, 12, 15, 0.82) 38%, rgba(0, 12, 15, 0.45) 70%),
      linear-gradient(100deg, rgba(0, 12, 15, 0.9) 6%, rgba(0, 20, 24, 0.5) 48%, transparent 82%);
  }

  .corp-hero__inner {
    position: relative;
    display: grid;
    justify-items: start;
    gap: var(--space-sm);
    /* No max-width — see the note on .page-hero__inner. This element carries
       .shell, so capping it here re-centres a narrower box and indents the
       hero relative to every section below. The title's wrap is capped on
       the title itself instead. */
  }

  .corp-hero__title {
    margin: 0;
    /* The wrap cap the inner box used to provide. On the title it constrains
       line length without moving the left edge. Do NOT go much below this —
       at this font-size a long word ("IZNAJMLJIVANJE") breaks mid-word. */
    max-width: 52rem;
    font-size: min(var(--fs-display), 15.5vh);
    font-weight: 800;
    line-height: var(--lh-tight);
    letter-spacing: var(--tracking-display);
    text-transform: uppercase;
    /* Saira Condensed's kerning table tucks "LJ" and "AJ" tighter than the
       rest — the J curls back under the preceding letter. On an all-caps
       tracked-out heading that reads as uneven spacing ("IZNAJMLJIVANJE").
       Turn pair-kerning off so the uniform letter-spacing above is the only
       thing setting the gaps. */
    font-kerning: none;
    font-feature-settings: "kern" 0;
  }

  /*
    NO max-width. The owner wants each page's standfirst on a single line
    (asked for it on Corporate Events, then Home Rental). It used to carry a
    34ch cap that broke every one of these ~50-60-char strings across two
    lines; uncapped it is bounded only by .shell, so it is one line on
    desktop/tablet and still wraps naturally on a phone. /sim-market/'s
    string is short enough that this changes nothing there; /sim-racing-srbija/
    keeps its own centred `.srs-page .corp-hero__sub` rule.
  */
  .corp-hero__sub {
    margin: 0;
    /* Not 34ch, but still clamped to the column: .corp-hero__inner is a grid
       and a grid item's default min-width:auto lets a long unbroken line
       push past the track (a few px of horizontal scroll at ~560px wide).
       max-width:100% lets it wrap at the column edge instead. */
    max-width: 100%;
    font-family: var(--font-display);
    font-size: var(--fs-h4);
    font-weight: 600;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--text-primary);
  }

  .corp-hero__cta {
    margin-top: var(--space-sm);
  }

  /* Sim Machine's own logo, sat above the title on /sim-market/ — that page
     fronts a partner brand, so its mark leads rather than Sim Master's. */
  .corp-hero__badge {
    display: block;
    width: auto;
    height: clamp(2.75rem, 1.5rem + 3vw, 4rem);
    margin-bottom: var(--space-2xs);
  }

  /* Two buttons side by side; wraps rather than shrinking them on narrow
     screens. Also used by .market__actions further down the same page. */
  .corp-hero__actions,
  .market__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-sm);
    margin-top: var(--space-sm);
  }

  .market__actions {
    margin-top: var(--space-xl);
  }

/* ---- alternating photo/text blocks ------------------------------------- */

.corp {
  background: var(--color-black);
}

.corp--alt {
  background: var(--surface-base);
}

  .corp__inner {
    display: grid;
    gap: var(--space-2xl);
    align-items: center;
  }

  @media (min-width: 62rem) {
    .corp__inner {
      grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
      gap: var(--space-3xl);
    }

    /* Visual swap only — DOM order stays copy-then-image, so mobile always
       reads heading, text, then picture. */
    .corp__inner--flip .corp__copy {
      order: 2;
    }
  }

  .corp__title {
    margin: var(--space-sm) 0 var(--space-md);
    font-size: var(--fs-h2);
    font-weight: 800;
    line-height: var(--lh-snug);
    text-transform: uppercase;
  }

  .corp__sub {
    margin: 0 0 var(--space-lg);
    max-width: 40ch;
    color: var(--text-primary);
  }

  .corp__body {
    display: grid;
    gap: var(--space-md);
    max-width: 56ch;
  }

  .corp__body p {
    margin: 0;
    color: var(--text-secondary);
  }

  ul.corp__scenarios {
    display: grid;
    gap: 0.6rem;
    margin: 0;
    padding: 0;
    list-style: none;
  }

  ul.corp__scenarios li {
    position: relative;
    padding-left: 1.1rem;
    color: var(--text-primary);
  }

  ul.corp__scenarios li::before {
    content: "";
    position: absolute;
    top: 0.6em;
    left: 0;
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: var(--action);
  }

/* ---- partner wordmark above a section head ------------------------------
   Same job the Heineken mark does on .corp-band (0.1.16): the partner's own
   logo leads the chapter, because the chapter is about their programme. It
   sits ABOVE the eyebrow rather than replacing it, so "Bezbednost / Safety"
   and the section title both survive.

   The Coca-Cola render is WHITE — see tools/derive_safe_driving.py for the
   measurements. Nothing here recolours it; the file itself is white, so no
   filter can be knocked out of step with the artwork.
   ------------------------------------------------------------------------ */

  .corp__partner-logo {
    display: block;
    height: clamp(1.15rem, 1.05rem + 1.3vw, 2rem);
    width: auto;
    margin-bottom: var(--space-sm);
  }

/* ---- photo frames ------------------------------------------------------ */

  .corp__frame {
    position: relative;
    margin: 0;
    overflow: hidden;
    border: 1px solid var(--line-soft);
    border-radius: var(--radius-md);
    background: var(--surface-void);
    box-shadow: var(--shadow-lg);
  }

  .corp__frame img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
  }

  .corp__frame--single {
    aspect-ratio: 4 / 3;
  }

  /*
    Two overlapping frames. On mobile they stack as ordinary blocks — the
    offset only applies once there is width to spare, otherwise the trailing
    frame would cover the leading one.
  */
  .corp__stack {
    display: grid;
    gap: var(--space-md);
  }

  .corp__stack .corp__frame {
    aspect-ratio: 4 / 3;
  }

  @media (min-width: 48rem) {
    .corp__stack {
      grid-template-columns: repeat(6, 1fr);
      gap: 0;
    }

    .corp__stack .corp__frame--lead {
      grid-column: 1 / 6;
      grid-row: 1;
    }

    .corp__stack .corp__frame--trail {
      grid-column: 3 / -1;
      grid-row: 1;
      margin-top: 28%;
      aspect-ratio: 1 / 1;
      z-index: 1;
    }
  }

  /* Monster: a square photo beside the tall Monster-liveried rig. */
  .corp__collage {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-md);
    align-items: start;
  }

  .corp__collage .corp__frame--square {
    aspect-ratio: 1 / 1;
  }

  .corp__collage .corp__frame--tall {
    aspect-ratio: 3 / 4;
  }

  @media (min-width: 48rem) {
    .corp__collage .corp__frame--square {
      margin-top: 12%;
    }

    .corp__collage .corp__frame--tall {
      aspect-ratio: 480 / 852;
    }
  }

  /* /iznajmljivanje-simulatora/ "U kompletu" — three close-ups instead of two:
     wheel and pedals stacked in column one, the taller shifter frame beside
     them spanning both rows. Rules come after the block above so they win the
     equal-specificity ties (margin-top, aspect-ratio). */
  .corp__collage--trio {
    align-items: stretch;
  }

  .corp__collage--trio .corp__frame--square {
    grid-column: 1;
    margin-top: 0;
    aspect-ratio: 1 / 1;
  }

  .corp__collage--trio .corp__frame--tall {
    grid-column: 2;
    grid-row: 1 / span 2;
    aspect-ratio: auto;
  }

/* ---- embedded film -----------------------------------------------------
   The Safe Driving video. It occupies the MEDIA COLUMN of the section's
   copy/media row — the owner asked for it beside the copy, not beneath it,
   and the photo that used to sit there was removed (it showed a different
   event). This is the only media that block has now.

   Deliberately NOT the .rig__media--video treatment used for the Motion Rig
   clip: that one is a short silent loop that autoplays on scroll. This is 77
   seconds of narrative footage with real audio, so it carries native
   `controls` and `preload="none"` — the 13 MB file is not touched until the
   visitor presses play; only the poster loads.
   ------------------------------------------------------------------------ */

  .corp__film {
    margin: 0;
  }

  /*
    The Coca-Cola wordmark leads the film rather than the section head (owner's
    request): it sits inside .corp__film, so above 62rem — where .corp__film is
    sticky — it rides down and stays visible with the video while the copy
    column scrolls past. Bigger than the old .corp__partner-logo above the
    eyebrow. The file itself is white (tools/derive_safe_driving.py); no filter.
  */
  .corp__film-logo {
    display: block;
    width: clamp(9.5rem, 7rem + 6vw, 13rem);
    height: auto;
    margin: 0 auto var(--space-md);
  }

  /*
    The copy column is ~957px tall at 1440px; a 16:9 player in the other
    column is ~294px. Left alone it sits marooned in the middle of a tall
    empty track, so above the two-column breakpoint it sticks: `align-self:
    start` gives it a track it can move within (the default `stretch`/`center`
    would pin it), and it then rides down beside the copy as you read.

    `top` clears the sticky header. --header-h is the header's own token, so
    the two cannot drift apart.

    Below 62rem the section is a single stacked column — there is no adjacent
    copy to ride beside, so sticky is not applied at all.
  */
  @media (min-width: 62rem) {
    .corp__inner .corp__film {
      position: sticky;
      top: calc(var(--header-h) + var(--space-lg));
      align-self: start;
    }
  }

  .corp__film-player {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 16 / 9;
    /* `contain`, not `cover`: the frame already matches the footage's own
       ratio, so there is nothing to crop, and a letterbox is preferable to
       silently trimming heads if that ever stops being true. */
    object-fit: contain;
    background: var(--surface-void);
    border: 1px solid var(--line-soft);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-lg);
  }

  .corp__film-caption {
    margin-top: var(--space-sm);
    font-family: var(--font-mono);
    font-size: var(--fs-mono-label);
    letter-spacing: var(--tracking-mono);
    text-transform: uppercase;
    color: var(--text-muted);
  }

  .corp__film-fallback {
    margin: 0;
    padding: var(--space-lg);
    color: var(--text-secondary);
  }

/* ---- full-width photo band (chapter break) ----------------------------- */

.corp-band {
  position: relative;
  isolation: isolate;
  display: grid;
  place-items: center;
  min-height: min(30rem, 70svh);
  padding-block: var(--space-3xl);
  overflow: hidden;
  text-align: center;
  background: var(--surface-void);
}

  .corp-band__media {
    position: absolute;
    inset: 0;
    z-index: -1;
  }

  .corp-band__photo {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: 50% 40%;
  }

  .corp-band__grade {
    position: absolute;
    inset: 0;
    background:
      linear-gradient(to bottom, rgba(4, 9, 11, 0.72) 0%, rgba(0, 20, 24, 0.55) 45%, rgba(4, 9, 11, 0.82) 100%),
      radial-gradient(ellipse 60% 70% at 50% 50%, rgba(245, 20, 15, 0.16), transparent 68%);
  }

  .corp-band__inner {
    position: relative;
    display: grid;
    justify-items: center;
    gap: var(--space-sm);
  }

  /* The partner's own mark leads the band, above the title — the section is
     about their project, so their brand goes first. Sits on the photo, so it
     gets the same light chip the endorsing logos use rather than relying on
     the grade behind it. */
  .corp-band__logo {
    display: block;
    /* The clamp's own floor (1.75rem) was still ~43% of the card's width on
       a 375px phone — the wordmark was competing with the heading instead
       of sitting quietly above it. A lower, fixed floor on narrow screens
       fixes that without touching the fluid desktop size. */
    height: clamp(1.25rem, 1.2rem + 1.6vw, 2.5rem);
    width: auto;
    margin-bottom: var(--space-2xs);
  }

  @media (max-width: 30rem) {
    .corp-band__logo {
      height: 1.25rem;
    }
  }

  .corp-band__body {
    margin: 0;
    max-width: 62ch;
    color: var(--text-primary);
  }

  .corp-band__title {
    margin: 0;
    max-width: 18ch;
    font-size: var(--fs-h1);
    font-weight: 800;
    line-height: var(--lh-tight);
    letter-spacing: var(--tracking-display);
    text-transform: uppercase;
  }

/* ---- Home rental (/iznajmljivanje-simulatora/) --------------------------
   Reuses .corp-hero / .corp / .rental / .games / .spec-card wholesale (see
   the Corporate Events and Price List blocks above). Two components are new
   to the site: .uses ("Perfect for") and .steps ("How it works").
   ------------------------------------------------------------------------ */

/* ---- perfect for -------------------------------------------------------- */

  /* Left-aligned, matching every other section head on the site
     (.games__head, .pricing__head). Centred heads read as a different
     component and broke the page's left rag. */
  .uses__head {
    display: grid;
    gap: var(--space-sm);
    margin-bottom: var(--space-2xl);
  }

  .uses__title {
    margin: 0;
    font-size: var(--fs-h2);
    font-weight: 800;
    line-height: var(--lh-snug);
    text-transform: uppercase;
  }

  /* auto-FIT, not auto-fill: the section holds three cards, and auto-fill
     keeps laying down empty tracks to fill the row, so the last one sat as a
     conspicuous hole on the right. auto-fit collapses those empty tracks, so
     however many cards there are, they always span the full column. */
  .uses__grid {
    display: grid;
    gap: var(--space-md);
    margin: 0;
    padding: 0;
    list-style: none;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
  }

  .use {
    display: grid;
    gap: var(--space-xs);
  }

  .use__frame {
    margin: 0 0 var(--space-xs);
    aspect-ratio: 4 / 3;
    overflow: hidden;
    border: 1px solid var(--line-faint);
    border-radius: var(--radius-md);
    background: var(--surface-inset);
    transition: border-color var(--dur-base) var(--ease-out);
  }

  .use:hover .use__frame {
    border-color: var(--line-strong);
  }

  .use__photo {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    filter: saturate(0.92) brightness(0.9);
    transition: transform var(--dur-slow) var(--ease-out), filter var(--dur-base) var(--ease-out);
  }

  .use:hover .use__photo {
    transform: scale(1.05);
    filter: saturate(1.05) brightness(1);
  }

  .use__name {
    margin: 0;
    font-size: 1.05rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    color: var(--text-warm);
  }

  .use__desc {
    margin: 0;
    font-size: var(--fs-body-sm);
    color: var(--text-secondary);
  }

/* ---- how it works -------------------------------------------------------- */

  .steps {
    background: linear-gradient(to bottom, var(--surface-void), var(--surface-base));
  }

  .steps__head {
    display: grid;
    gap: var(--space-sm);
    margin-bottom: var(--space-2xl);
  }

  .steps__title {
    margin: 0;
    font-size: var(--fs-h2);
    font-weight: 800;
    line-height: var(--lh-snug);
    text-transform: uppercase;
  }

  .steps__grid {
    display: grid;
    gap: var(--space-lg);
    margin: 0;
    padding: 0;
    list-style: none;
    counter-reset: step;
  }

  @media (min-width: 48rem) {
    .steps__grid {
      grid-template-columns: repeat(4, 1fr);
      gap: var(--space-md);
    }
  }

  .step {
    position: relative;
    padding: var(--space-lg) var(--space-md) var(--space-md);
    border: 1px solid var(--line-faint);
    border-radius: var(--radius-md);
    background: linear-gradient(175deg, var(--surface-panel), var(--surface-void) 70%);
  }

  .step__num {
    display: block;
    margin-bottom: var(--space-sm);
    font-family: var(--font-numeric);
    font-size: 2.75rem;
    font-weight: 700;
    line-height: 1;
    color: var(--action-text);
    font-variant-numeric: tabular-nums;
  }

  .step__name {
    margin: 0 0 0.35rem;
    font-size: 1.05rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    color: var(--text-warm);
  }

  .step__desc {
    margin: 0;
    font-size: var(--fs-body-sm);
    color: var(--text-secondary);
  }

  /* A thin connecting line between steps on desktop reinforces "process". */
  @media (min-width: 48rem) {
    .step:not(:last-child)::after {
      content: "";
      position: absolute;
      top: calc(var(--space-lg) + 1.375rem);
      left: 100%;
      width: var(--space-md);
      height: 1px;
      background: var(--line-soft);
    }
  }

/* ---- Sim Racing Srbija (/sim-racing-srbija/) -----------------------------
   Reuses .corp-hero / .corp / .corp-band wholesale (see the Corporate Events
   block above) for hero, the two intro blocks and the community CTA band.
   Three components are new to this page: .community-cta (the CTA band's
   longer copy + partner-logo row), .drivers (GT3/GT4 masonry galleries) and
   the .news__grid--srs variation (first card runs wide, for the "not six
   identical boxes" editorial brief).
   ------------------------------------------------------------------------ */

/* ---- community CTA band -------------------------------------------------- */

  /* The shared .corp-band__title is capped at 18ch for a short phrase
     (Heineken's own use, 0.1.16); this page's heading is a full sentence, so
     it needs real width and a step down in size to avoid overwhelming the
     band. */
  /*
    Left-aligned, not centred like the Heineken band this component was
    originally built for. The owner supplied a reference: a big left-set
    heading with a framed callout panel under it carrying the supporting
    copy and the endorsing logos. Structure follows that reference; COLOUR
    follows this site (red accent), not the reference's yellow.
  */
  .community-cta {
    text-align: left;
    place-items: center start;
  }

  .community-cta .corp-band__inner {
    justify-items: start;
    gap: var(--space-lg);
  }

  /* From the tablet breakpoint up, the heading and callout are held to the
     RIGHT half of the band (owner's request) so the FIA trophy — left of
     centre in the photo — is never covered. Their inner text stays
     left-aligned. Below this width the band is a single stacked column, so
     it keeps the default start alignment. */
  @media (min-width: 62rem) {
    .community-cta {
      place-items: center end;
    }

    .community-cta .corp-band__inner {
      justify-items: end;
    }
  }

  .community-cta .corp-band__title {
    max-width: 20ch;
    font-size: var(--fs-h2);
  }

/* ---- the framed callout panel -------------------------------------------- */

  .community-cta__panel {
    position: relative;
    /* Kept tight (~34rem) so, sitting in the right half of the band, it
       leaves the trophy on the left of the photo fully clear. */
    max-width: 34rem;
    padding: var(--space-xl);
    /* Sits over a busy photo, so it needs its own ground to stay readable. */
    background: rgba(4, 9, 11, 0.74);
    border: 1px solid rgba(244, 247, 248, 0.10);
  }

  @supports (backdrop-filter: blur(6px)) {
    .community-cta__panel {
      background: rgba(4, 9, 11, 0.58);
      backdrop-filter: blur(8px);
    }
  }

  /* The two corner brackets from the reference — drawn as pseudo-elements so
     they need no extra markup. Opposite corners only (top-left, bottom-right),
     which is what gives the frame its deliberate, unclosed look. */
  .community-cta__panel::before,
  .community-cta__panel::after {
    content: "";
    position: absolute;
    width: 2.75rem;
    height: 2.75rem;
    border: 2px solid var(--action);
    pointer-events: none;
  }

  .community-cta__panel::before {
    top: -1px;
    left: -1px;
    border-right: 0;
    border-bottom: 0;
  }

  .community-cta__panel::after {
    right: -1px;
    bottom: -1px;
    border-left: 0;
    border-top: 0;
  }

  .community-cta__body {
    margin: 0;
    max-width: 52ch;
    /* Accent rule down the left of the copy, as in the reference. */
    padding-left: var(--space-md);
    border-left: 2px solid var(--action);
    color: var(--text-primary);
  }

  .community-cta__foot {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-lg);
    margin-top: var(--space-xl);
  }

  .partners-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-lg);
    margin: 0;
    padding: 0;
    list-style: none;
  }

  /*
    A DARK chip, not a light one, and not a colour filter either.

    Three different logo treatments have to coexist here: AMSS and SAMKS
    print their detail onto their own opaque coloured badge, while SAMS
    Beograd is a WHITE-ON-TRANSPARENT silhouette (0.1.8). A light chip made
    that third one disappear completely — verified by compositing it against
    both grounds. A dark chip shows all three: the white mark reads against
    it, and the two that carry their own background are unaffected.

    A brightness(0)/invert filter is still wrong here for the other two — it
    would flatten their badge to a single block and erase the detail.
  */
  .partners-row__item {
    padding: 0.45rem 0.75rem;
    background: rgba(4, 9, 11, 0.55);
    border: 1px solid rgba(244, 247, 248, 0.12);
    border-radius: var(--radius-sm);
  }

  .partners-row__item img {
    display: block;
    /* The AMSS/FIA marks in the band panel — bumped from 2rem, they were
       too small to read against the busy trophy photo behind the panel. */
    height: 2.75rem;
    width: auto;
  }

  @media (max-width: 40rem) {
    .community-cta__panel {
      padding: var(--space-lg);
    }

    .community-cta__foot {
      align-items: flex-start;
      flex-direction: column;
    }
  }

/* ---- "pridruži se" — copy + icon row left, endorsing logos right ---------
   The invitation that used to be the community band's own paragraph, split
   out into its own section at the owner's request (2026-08-30). The band
   above now speaks only about AMSS/FIA, so the Discord button left with it —
   the icon row here is the page's single social entry point.
   ------------------------------------------------------------------------ */

  .join__inner {
    display: grid;
    gap: var(--space-2xl);
    align-items: center;
  }

  @media (min-width: 62rem) {
    .join__inner {
      /* Copy left, logos right — "the right half of the screen". */
      grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
      gap: var(--space-3xl);
    }
  }

  .join__title {
    margin: var(--space-sm) 0 var(--space-md);
    max-width: 20ch;
    font-size: var(--fs-h2);
    font-weight: 800;
    line-height: var(--lh-snug);
    text-transform: uppercase;
  }

  .join__body {
    margin: 0;
    max-width: 52ch;
    /* The same accent rule the community callout uses, so the two blocks
       read as one thought continued rather than two unrelated panels. */
    padding-left: var(--space-md);
    border-left: 2px solid var(--action);
    color: var(--text-primary);
  }

/* ---- the icon row ------------------------------------------------------- */

  .join__social {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-sm);
    margin: var(--space-xl) 0 0;
    padding: 0;
    list-style: none;
  }

  /* 44px minimum, so the icon-only target still clears WCAG 2.2 target size
     on touch — the glyph itself is only 22px. */
  .social-icon {
    display: grid;
    place-items: center;
    width: 2.75rem;
    height: 2.75rem;
    color: var(--text-secondary);
    background: var(--surface-void);
    border: 1px solid var(--line-soft);
    border-radius: var(--radius-sm);
    transition:
      color var(--dur-base) var(--ease-out),
      border-color var(--dur-base) var(--ease-out),
      transform var(--dur-base) var(--ease-out);
  }

  .social-icon:hover,
  .social-icon:focus-visible {
    color: var(--color-white);
    border-color: var(--action);
    transform: translateY(-2px);
  }

/* ---- the six-logo panel -------------------------------------------------- */

  /*
    Inherits .partners-row's dark chips — required, not cosmetic: SAMS
    Beograd and the Sim Master mark are both white-on-transparent and vanish
    on a light ground (§0.1.21). Overrides the flex row with a grid so six
    marks of very different widths still line up in even columns.
  */
  .join__logos {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-md);
  }

  @media (min-width: 34rem) {
    .join__logos {
      grid-template-columns: repeat(3, minmax(0, 1fr));
    }
  }

  .join__logo {
    display: grid;
    place-items: center;
    padding: var(--space-lg) var(--space-md);
  }

  /* 3.5rem = the derivatives' native 1x height, so no upscaling — and a big
     step up from the 2rem the row would otherwise inherit from
     .partners-row__item img, which the owner reported as unreadable. */
  .join__logo img {
    height: 3.5rem;
    width: auto;
    max-width: 100%;
    object-fit: contain;
  }

  @media (prefers-reduced-motion: reduce) {
    .social-icon:hover,
    .social-icon:focus-visible {
      transform: none;
    }
  }

/* ---- driver profile galleries (GT3 / GT4) --------------------------------- */

  .drivers__head {
    margin-bottom: var(--space-lg);
  }

  .drivers__title {
    margin-top: var(--space-sm);
    font-size: var(--fs-h2);
    font-weight: 800;
    line-height: var(--lh-snug);
    text-transform: uppercase;
  }

  .drivers__class-label {
    margin: var(--space-2xl) 0 var(--space-md);
    padding-bottom: var(--space-2xs);
    border-bottom: 1px solid var(--line-soft);
    font-size: var(--fs-h4);
    font-weight: 700;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--text-warm);
  }

  /* First class label needs no extra top gap — it follows the section
     header, not another gallery. */
  .drivers__head + .drivers__class-label {
    margin-top: var(--space-md);
  }

  .drivers__class-label--gt4 {
    color: var(--action-text);
  }

  .drivers__empty {
    margin: 0 0 var(--space-lg);
    color: var(--text-muted);
  }

  /*
    Masonry via CSS columns, not a grid — driver profile graphics are
    owner-supplied artwork of UNKNOWN, varying aspect ratios (a full card
    with baked-in stats, not a uniform photo), so a fixed-aspect grid cell
    would either crop real information out of the graphic or letterbox it
    awkwardly. Columns let each card keep its own natural proportions while
    still flowing into a tidy multi-column wall.
  */
  /*
    The GT3/GT4 galleries are an endless CAROUSEL, not a static grid: the
    markup reuses the partners marquee (.marquee / .marquee__track /
    .marquee__run, 0.1.8), which duplicates the run and animates the track to
    translateX(-50%) so it turns continuously with no visible start or end.
    Everything below only sizes the cards; the motion, the edge fade and the
    reduced-motion fallback all come from .marquee in sections.css.
  */
  /*
    The cards are the owner's own artwork on a WHITE ground and ship exactly
    as supplied. So the panel underneath is what changes: a soft light
    surface that gives the white cards something to sit on instead of
    floating on the dark page.
  */
  .drivers__panel {
    position: relative;
    margin: 0 0 var(--space-xl);
    padding: var(--space-lg) 0;
    background:
      linear-gradient(180deg, rgba(244, 247, 248, 0.10), rgba(244, 247, 248, 0.04));
    border: 1px solid rgba(244, 247, 248, 0.10);
    border-radius: var(--radius-md);
  }

/* ---- the scroll carousel ------------------------------------------------- */

  .carousel {
    position: relative;
    display: flex;
    align-items: center;
    gap: var(--space-2xs);
  }

  .carousel__viewport {
    flex: 1;
    min-width: 0;
    overflow-x: auto;
    overflow-y: hidden;
    /* NOT `scroll-behavior: smooth` — the drift in js/carousel.js writes
       scrollLeft every frame, and a smooth scroller would try to animate to
       each of those and stutter. The buttons opt into smoothing per call
       with scrollBy({behavior:"smooth"}) instead. */
    scrollbar-width: none;
    -ms-overflow-style: none;
    /* Cards fade out at both edges rather than being hard-cut, same idea as
       the logo marquee. */
    mask-image: linear-gradient(to right, transparent, #000 4rem, #000 calc(100% - 4rem), transparent);
    -webkit-mask-image: linear-gradient(to right, transparent, #000 4rem, #000 calc(100% - 4rem), transparent);
  }

  .carousel__viewport::-webkit-scrollbar {
    display: none;
  }

  ul.carousel__run {
    display: flex;
    align-items: stretch;
    gap: var(--space-md);
    margin: 0;
    padding: 0 var(--space-md) 0 0;
    list-style: none;
  }

  .carousel__viewport {
    display: flex;
  }

  .carousel__btn {
    flex: 0 0 auto;
    display: grid;
    place-items: center;
    width: 2.75rem;
    height: 2.75rem;
    padding: 0;
    background: var(--surface-void);
    border: 1px solid var(--line-soft);
    border-radius: 50%;
    color: var(--text-primary);
    cursor: pointer;
    transition:
      background-color var(--dur-base) var(--ease-out),
      border-color var(--dur-base) var(--ease-out),
      color var(--dur-base) var(--ease-out),
      transform var(--dur-base) var(--ease-out);
  }

  .carousel__btn:hover {
    background: var(--action);
    border-color: var(--action);
    color: var(--color-white);
    transform: scale(1.08);
  }

  .carousel__btn:active {
    transform: scale(0.96);
  }

  .carousel__btn:focus-visible {
    outline: 2px solid var(--focus-ring);
    outline-offset: 3px;
  }

  .driver-card {
    flex: 0 0 auto;
    /* Wide landscape info-graphics with baked-in stat text — they need real
       width to stay legible, capped so a phone still shows a whole card. */
    width: min(34rem, 80vw);
    margin: 0;
    border: 1px solid var(--line-faint);
    border-radius: var(--radius-md);
    overflow: hidden;
    background: var(--surface-raised);
    box-shadow: 0 0.75rem 2rem rgba(0, 0, 0, 0.55);
    transition: transform var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out);
  }

  .driver-card:hover {
    transform: translateY(-4px);
    box-shadow: 0 1.25rem 2.75rem rgba(0, 0, 0, 0.7);
  }

  .driver-card img {
    display: block;
    width: 100%;
    height: auto;
    /*
      ALWAYS full colour. These used to carry .marquee__item, which meant
      they inherited the logo strip's `filter: grayscale(1) ...; opacity:
      .55` and only came to colour on hover — so every driver's photo sat
      washed out at rest. The class is gone now, but this stays explicit so
      reintroducing a marquee class here can never grey the cards again.
    */
    filter: none;
    opacity: 1;
  }

  /* On a phone the 80vw card ran taller than the viewport with its neighbours
     peeking in — shrink it so a whole card (image + baked-in stats) sits on
     screen at once. */
  @media (max-width: 40rem) {
    .driver-card {
      width: min(18rem, 62vw);
    }

    /* The 4rem edge fade eats a chunk of each side of a phone-width card,
       making it look permanently clipped — pull it in and drop the buttons'
       gap so a whole card clears both fades. */
    .carousel__viewport {
      mask-image: linear-gradient(to right, transparent, #000 1.25rem, #000 calc(100% - 1.25rem), transparent);
      -webkit-mask-image: linear-gradient(to right, transparent, #000 1.25rem, #000 calc(100% - 1.25rem), transparent);
    }

    .carousel {
      gap: 0;
    }

    .carousel__btn {
      width: 2.25rem;
      height: 2.25rem;
    }
  }

/* ---- championship news editorial variation -------------------------------- */

  /*
    Same .post / .post__card component as the homepage's news teaser, with
    one change: the first card runs the full width of the grid above the
    tablet breakpoint, so the page reads as an edited front page (lead story
    + grid) rather than six identical boxes.
  */
  @media (min-width: 40rem) {
    .news__grid--srs li.news-post:first-child {
      grid-column: 1 / -1;
    }

    .news__grid--srs li.news-post:first-child .post__card {
      flex-direction: row;
    }

    .news__grid--srs li.news-post:first-child .post__media {
      flex: 0 0 42%;
      aspect-ratio: auto;
      height: 100%;
    }

    .news__grid--srs li.news-post:first-child .post__body {
      justify-content: center;
    }

    .news__grid--srs li.news-post:first-child .post__title {
      font-size: var(--fs-h3);
    }
  }

/* ---- Teams band (/sim-racing-srbija/) ------------------------------------
   Borrows the homepage sponsor marquee's STRUCTURE and motion — .marquee /
   .marquee__track / .marquee__run / .marquee__item — for the endless drift,
   edge fade and no-tile-box look. Only the section wrapper is defined here;
   adding any per-item background would break the "same as the sponsors" ask.

   Logos are the real championship-teams marks, owner-supplied — see
   TEAM_LOGOS in the content module (derived by tools/derive_team_logos.py).
   Rendered without captions, like the sponsor strip: each img's alt carries
   the team name for assistive tech.
   ------------------------------------------------------------------------ */

.teams {
  background: var(--surface-base);
  border-top: 1px solid var(--line-faint);
}

  /* The sponsor strip desaturates its logos at rest and only brings them to
     full colour on hover. The owner wants the TEAM logos always full colour
     and no hover treatment — so cancel the inherited filter/opacity in both
     states, on this page only. */
  .teams .marquee__item img,
  .teams .marquee__item:hover img {
    filter: none;
    opacity: 1;
  }

  .teams__head {
    display: grid;
    gap: var(--space-sm);
    margin-bottom: var(--space-2xl);
  }

  .teams__body {
    margin: 0;
    max-width: 52ch;
  }

/* ---- Sim Racing Srbija: section rhythm and headings ----------------------
   The page read as flat next to the homepage: every section shared one
   background and the headings were plain type. These rules give it the
   homepage's variety — alternating grounds so adjacent sections separate,
   and a heading treatment with a real accent instead of bare text.
   Scoped to .srs-page so nothing here leaks onto the other subpages.
   ------------------------------------------------------------------------ */

/* Distinct grounds, alternating down the page. Each section already differs
   in content; this makes the boundaries readable at a glance too. */
  /*
    These two sections stack directly on top of each other and were reading
    as one continuous block. They now differ on THREE axes at once — base
    tone, the corner the glow sits in, and its hue — because a single subtle
    change was not enough to separate them at a glance.
  */
  /* "Vesti" / "Profili vozača" nav anchors land ON their section rather than
     ~230px above it. The global scroll offset (scroll-padding-top plus the
     :target scroll-margin-top) stacked to almost twice the header height,
     leaving the previous section in view. A negative margin cancels the
     surplus so the section top sits flush under the sticky header. */
  .srs-page #vesti,
  .srs-page #profili-vozaca,
  .srs-page #pridruzi-se {
    scroll-margin-top: calc(var(--space-lg) * -1);
  }

  .srs-page .corp {
    background:
      radial-gradient(ellipse 70% 55% at 85% 0%, rgba(0, 45, 53, 0.7), transparent 62%),
      var(--color-black);
  }

  .srs-page .corp--alt {
    background:
      radial-gradient(ellipse 75% 60% at 8% 100%, rgba(232, 19, 14, 0.10), transparent 62%),
      linear-gradient(180deg, var(--surface-raised), var(--surface-base));
  }

  /* A red hairline where the two meet, so the boundary is explicit. */
  .srs-page .corp--alt {
    border-top: 1px solid var(--line-soft);
  }

  .srs-page .drivers {
    background:
      radial-gradient(ellipse 80% 45% at 50% 0%, rgba(232, 19, 14, 0.10), transparent 60%),
      var(--color-black);
  }

  /* Follows the photo band, so it takes the teal ground rather than a red
     glow — the band's own panel already carries the red accent, and two red
     washes in a row would read as one section. */
  .srs-page .join {
    background:
      radial-gradient(ellipse 70% 55% at 85% 100%, rgba(0, 45, 53, 0.7), transparent 62%),
      var(--color-black);
  }

  /* A hairline between stacked sections so each one reads as its own band. */
  .srs-page .corp,
  .srs-page .corp--alt,
  .srs-page .join,
  .srs-page .drivers,
  .srs-page .news {
    border-top: 1px solid var(--line-faint);
  }

  /* Hero copy is centred on this page at the owner's request — the other
     .corp-hero pages stay left-aligned, so this is scoped, not a change to
     the shared component. */
  .srs-page .corp-hero {
    place-items: center;
    text-align: center;
  }

  .srs-page .corp-hero__inner {
    justify-items: center;
  }

  .srs-page .corp-hero__title {
    max-width: 18ch;
  }

  .srs-page .corp-hero__sub {
    max-width: 40ch;
    margin-inline: auto;
  }

/* ---- headings ------------------------------------------------------------ */

  /*
    A red rule sits above each section title, echoing the accent bar printed
    on the driver cards themselves. It is a ::before on the heading rather
    than a separate element so every existing heading picks it up without
    markup changes.
  */
  .srs-page .corp__title,
  .srs-page .drivers__title,
  .srs-page .news__title,
  .srs-page .teams__title,
  .srs-page .join__title {
    position: relative;
    padding-top: var(--space-sm);
    letter-spacing: var(--tracking-display);
  }

  .srs-page .corp__title::before,
  .srs-page .drivers__title::before,
  .srs-page .news__title::before,
  .srs-page .teams__title::before,
  .srs-page .join__title::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    width: 3.5rem;
    height: 3px;
    background: linear-gradient(to right, var(--action), transparent);
    /* Draws itself in as the heading reveals, so the accent feels part of
       the entrance rather than a static bar that was always there. */
    transform-origin: left center;
    transform: scaleX(0);
    transition: transform var(--dur-slow) var(--ease-out) 120ms;
  }

  [data-reveal].is-visible .corp__title::before,
  [data-reveal].is-visible .drivers__title::before,
  [data-reveal].is-visible .news__title::before,
  [data-reveal].is-visible .teams__title::before,
  [data-reveal].is-visible .join__title::before,
  .no-js .srs-page [class$="__title"]::before {
    transform: scaleX(1);
  }

  /* Class labels get the same accent language as the section titles. */
  .srs-page .drivers__class-label {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    border-bottom: 0;
    padding-bottom: 0;
  }

  .srs-page .drivers__class-label::after {
    content: "";
    flex: 1;
    height: 1px;
    background: linear-gradient(to right, var(--line-strong), transparent);
  }

/* ---- motion -------------------------------------------------------------- */

  /* The intro photos drift up a touch as they settle, so the alternating
     blocks feel composed rather than snapping into place. */
  .srs-page .corp__frame {
    transition:
      transform var(--dur-slow) var(--ease-out),
      box-shadow var(--dur-slow) var(--ease-out);
  }

  .srs-page .corp__frame:hover {
    transform: translateY(-6px);
    box-shadow: 0 1.5rem 3rem rgba(0, 0, 0, 0.6);
  }

  @media (prefers-reduced-motion: reduce) {
    .srs-page .corp__title::before,
    .srs-page .drivers__title::before,
    .srs-page .news__title::before,
    .srs-page .teams__title::before {
      transition: none;
      transform: scaleX(1);
    }

    .srs-page .corp__frame,
    .srs-page .corp__frame:hover {
      transform: none;
    }
  }

/* ==========================================================================
   EDITORIAL SUBPAGES — /korporativna-desavanja/ + /sim-racing-srbija/
   --------------------------------------------------------------------------
   Both pages are built out of the same three primitives: a photo hero, a
   stack of alternating copy/photo blocks (.corp) and a full-width photo band
   (.corp-band). On their own those primitives are just type and a picture on
   a flat ground, which is exactly how the owner described them — "too simple,
   just black with text and photo". Everything below is presentation only: no
   copy, no images and no markup order changes, just the devices the rest of
   the site already uses, applied here.

     · the engineering line grid behind each block   (.grid-backdrop, base.css)
     · a bordered instrument panel around each row   (.rig__card, sections.css)
     · corner brackets inside every photo frame      (.about__frame::after)
     · the red rule above each section heading       (.srs-page headings)
     · the telemetry scanline wash over the hero     (.hero__scanlines)

   SCOPED TO THESE TWO PAGES ONLY. `.corp`, `.corp__inner`, `.corp__frame` and
   `.corp-hero` are shared with /iznajmljivanje-simulatora/ and /sim-market/,
   which were not part of this request — every selector here is prefixed with
   `.corp-page` (set on <body> by tools/build_korporativna.py) or `.srs-page`
   so those two pages are untouched. Widening the treatment to them later is a
   matter of adding their body class to these selector lists.
   ========================================================================== */

/* ---- section grounds ---------------------------------------------------- */

  /*
    Corporate Events used a flat --color-black / --surface-base pair, so five
    stacked blocks read as one unbroken black field. These are the same
    three-axis treatment /sim-racing-srbija/ already carries (base tone, which
    corner the glow sits in, and its hue), so the two pages now separate their
    bands the same way.
  */
  .corp-page .corp {
    background:
      radial-gradient(ellipse 70% 55% at 88% 0%, rgba(0, 45, 53, 0.62), transparent 62%),
      var(--color-black);
    border-top: 1px solid var(--line-faint);
  }

  .corp-page .corp--alt {
    background:
      radial-gradient(ellipse 75% 60% at 8% 100%, rgba(232, 19, 14, 0.10), transparent 62%),
      linear-gradient(180deg, var(--surface-raised), var(--surface-base));
    border-top: 1px solid var(--line-soft);
  }

  /*
    The blueprint grid, as a pseudo-element rather than a .grid-backdrop
    element — these sections are generated markup and this needs no new node.
    `isolation: isolate` is what makes `z-index: -1` land ABOVE the section's
    own background and below its content; without it the layer would paint
    behind the background and never be seen.
  */
  .corp-page .corp,
  .srs-page .corp {
    position: relative;
    isolation: isolate;
  }

  .corp-page .corp::before,
  .srs-page .corp::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    background-image:
      linear-gradient(to right, var(--line-faint) 1px, transparent 1px),
      linear-gradient(to bottom, var(--line-faint) 1px, transparent 1px);
    background-size: 5rem 5rem;
    -webkit-mask-image: radial-gradient(ellipse 85% 70% at 50% 0%, #000 8%, transparent 74%);
            mask-image: radial-gradient(ellipse 85% 70% at 50% 0%, #000 8%, transparent 74%);
    opacity: 0.55;
  }

/* ---- each block becomes an instrument panel ----------------------------- */

  /*
    The same panel the homepage's rig rows sit in (.rig__card): a soft
    top-lit gradient, one hairline border, and a border that warms to red on
    hover. It is what turns "text next to a photo" into a composed row, and it
    is the single biggest change on both pages.
  */
  .corp-page .corp__inner,
  .srs-page .corp__inner {
    padding: var(--space-lg);
    background: linear-gradient(175deg, var(--surface-panel), var(--surface-void) 72%);
    border: 1px solid var(--line-faint);
    border-radius: var(--radius-md);
    transition: border-color var(--dur-base) var(--ease-out);
  }

  .corp-page .corp__inner:hover,
  .srs-page .corp__inner:hover {
    border-color: var(--line-strong);
  }

  @media (min-width: 62rem) {
    .corp-page .corp__inner,
    .srs-page .corp__inner {
      /* The bare block could afford --space-3xl between its columns; inside a
         padded panel that much air makes the two halves read as unrelated. */
      gap: var(--space-2xl);
      padding: var(--space-xl);
    }
  }

  /* On a phone the panel's padding stacks on top of the shell gutter, and at
     --space-lg the two together took ~53px off a 375px screen. */
  @media (max-width: 40rem) {
    .corp-page .corp__inner,
    .srs-page .corp__inner {
      padding: var(--space-md);
    }
  }

/* ---- headings ----------------------------------------------------------- */

  /*
    The red rule above the heading, ported from /sim-racing-srbija/ so both
    pages share one heading language. The scale-in on reveal is driven by the
    existing `[data-reveal].is-visible .corp__title::before` rule further up
    this file — that selector is page-agnostic and only ever matched headings
    that had a ::before to animate, so it picks this up with no change.
  */
  .corp-page .corp__title {
    position: relative;
    padding-top: var(--space-sm);
    letter-spacing: var(--tracking-display);
  }

  .corp-page .corp__title::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    width: 3.5rem;
    height: 3px;
    background: linear-gradient(to right, var(--action), transparent);
    transform-origin: left center;
    transform: scaleX(0);
    transition: transform var(--dur-slow) var(--ease-out) 120ms;
  }

  .no-js .corp-page .corp__title::before {
    transform: scaleX(1);
  }

  /* The standfirst gets the accent rule the community callout uses, so the
     one-line summary reads as a pull quote rather than a second paragraph. */
  .corp-page .corp__sub {
    padding-left: var(--space-md);
    border-left: 2px solid var(--action);
  }

  /*
    .teams__title had no size rule at all and was falling through to the UA's
    default h2 — "Timovi" rendered at roughly a third of the size of every
    other section title on the page. Matched to .drivers__title / .news__title.
  */
  .srs-page .teams__title {
    font-size: var(--fs-h2);
    font-weight: 800;
    line-height: var(--lh-snug);
    text-transform: uppercase;
  }

/* ---- photo frames ------------------------------------------------------- */

  .corp-page .corp__frame,
  .srs-page .corp__frame {
    border-color: var(--line-soft);
    transition:
      transform var(--dur-slow) var(--ease-out),
      box-shadow var(--dur-slow) var(--ease-out),
      border-color var(--dur-base) var(--ease-out);
  }

  /*
    The instrument-frame motif from .about__frame — an inset hairline masked
    down to two opposite corners, so it reads as a bracketed viewfinder rather
    than a second border. Same 45deg mask stops as the About photo, so the two
    are recognisably the same device.
  */
  .corp-page .corp__frame::after,
  .srs-page .corp__frame::after {
    content: "";
    position: absolute;
    inset: 0.75rem;
    pointer-events: none;
    /* Not --line-soft like the About frame: that hairline sits on one known
       photograph, while these brackets have to read over five different ones.
       A low-alpha white is the only value that survives a bright frame and a
       dark one alike. */
    border: 1px solid rgba(255, 255, 255, 0.42);
    border-radius: var(--radius-sm);
    -webkit-mask-image: linear-gradient(45deg, #000 0 18%, transparent 18% 82%, #000 82% 100%);
            mask-image: linear-gradient(45deg, #000 0 18%, transparent 18% 82%, #000 82% 100%);
  }

  /*
    NO `z-index` on that rule. It does not need one — an absolutely positioned
    pseudo-element already paints above its non-positioned <img> sibling — and
    adding `z-index: 1` to a MASKED pseudo-element made Chromium drop the
    photo underneath it entirely: every frame rendered as a flat black box
    with only the brackets showing. Same masked-corner device as
    .about__frame::after, which likewise sets no z-index.
  */

  .corp-page .corp__frame:hover,
  .srs-page .corp__frame:hover {
    transform: translateY(-6px);
    border-color: var(--line-strong);
    box-shadow: 0 1.5rem 3rem rgba(0, 0, 0, 0.6);
  }

  .corp-page .corp__frame img,
  .srs-page .corp__frame img {
    transition: transform var(--dur-slow) var(--ease-out);
  }

  .corp-page .corp__frame:hover img,
  .srs-page .corp__frame:hover img {
    transform: scale(1.04);
  }

/* ---- hero and photo bands ----------------------------------------------- */

  /*
    The homepage hero's near-invisible horizontal ruling. .corp-hero already
    carries `isolation: isolate` and puts its media at `z-index: -1`; this
    pseudo-element shares that level and, coming later in paint order, lands
    on top of the photo but still under the copy.
  */
  .corp-page .corp-hero::after,
  .srs-page .corp-hero::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    background: repeating-linear-gradient(
      to bottom,
      rgba(0, 201, 255, 0.035) 0 1px,
      transparent 1px 4px
    );
    opacity: 0.6;
    mix-blend-mode: overlay;
  }

  /* Lighter hero grade on this page (owner's request): the pit-lane
     celebration photo was reading almost black. Keeps the void anchor at the
     very bottom so the CTA row stays legible; the outlined H1 needs no help. */
  .srs-page .corp-hero__grade {
    background:
      linear-gradient(to top, var(--surface-void) 2%, rgba(0, 12, 15, 0.56) 42%, rgba(0, 12, 15, 0.2) 75%),
      linear-gradient(100deg, rgba(0, 12, 15, 0.7) 4%, rgba(0, 20, 24, 0.32) 50%, transparent 84%);
  }

  /* Lighter grade on the "Vreme je da Srbija ima…" band so the FIA trophy
     behind the panel reads (owner's request). Darkest at the top behind the
     heading, lightest through the middle where the trophy sits. The callout
     panel carries its own background, so its copy is unaffected. */
  .community-cta .corp-band__grade {
    background:
      linear-gradient(to bottom, rgba(4, 9, 11, 0.62) 0%, rgba(0, 16, 20, 0.26) 44%, rgba(4, 9, 11, 0.5) 100%),
      radial-gradient(ellipse 55% 65% at 50% 48%, rgba(232, 19, 14, 0.11), transparent 72%);
  }

  /* The photo bands were butting straight onto the block above and below with
     no edge; a hairline gives them the same explicit boundary the .corp bands
     now have. */
  .corp-page .corp-band,
  .srs-page .corp-band {
    border-block: 1px solid var(--line-soft);
  }

/* ---- Sim Racing Srbija: the two remaining bare bands --------------------- */

  /* Corner brackets, the same device and colour as .community-cta__panel
     higher up this page — the drivers wall and the community callout now read
     as one pair. z-index puts them over .carousel, which is positioned. */
  .srs-page .drivers__panel::before,
  .srs-page .drivers__panel::after {
    content: "";
    position: absolute;
    z-index: 2;
    width: 2.25rem;
    height: 2.25rem;
    border: 2px solid var(--action);
    pointer-events: none;
  }

  .srs-page .drivers__panel::before {
    top: -1px;
    left: -1px;
    border-right: 0;
    border-bottom: 0;
  }

  .srs-page .drivers__panel::after {
    right: -1px;
    bottom: -1px;
    border-left: 0;
    border-top: 0;
  }

  /* The team logos were drifting in open space. A ruled strip with a faint
     top-light gives them a track to run along, matching the framed feel of
     everything above them. */
  .srs-page .teams .marquee {
    padding-block: var(--space-lg);
    border-block: 1px solid var(--line-faint);
    background: linear-gradient(180deg, rgba(244, 247, 248, 0.035), transparent 70%);
  }

/* ---- reduced motion ----------------------------------------------------- */

  @media (prefers-reduced-motion: reduce) {
    .corp-page .corp__title::before {
      transition: none;
      transform: scaleX(1);
    }

    .corp-page .corp__frame,
    .corp-page .corp__frame:hover,
    .srs-page .corp__frame:hover {
      transform: none;
    }

    .corp-page .corp__frame:hover img,
    .srs-page .corp__frame:hover img {
      transform: none;
    }
  }

/* ===========================================================================
   ARTICLE PAGES — /vesti-iz-sampionata/<slug>/
   Scoped to `.article-page` on <body>. Built by tools/build_vesti.py.

   Almost nothing here is new. The masthead is the shared `.page-hero`, the
   "more news" row is the shared `.news` / `.post` card, and the closing CTA
   is the shared `.final` — so an article reads as the same site, and any
   later change to those components reaches it for free. What this block adds
   is the reading column itself, and one substitution in the hero.
   =========================================================================== */

/*
  THE HERO MARK IS THE ARTICLE'S OWN PHOTO, not one of the four schematics.

  `.page-hero::after` normally paints a technical line drawing chosen by
  `data-hero-mark`, defaulting to the wheel (see that rule's own notes). An
  article has no equipment to draw and there are six of them, so the slot
  instead carries the article's lead image — faded and masked exactly like a
  schematic, which gives every article a distinct masthead with no new asset
  and no extra element.

  Its URL arrives as `--hero-mark` in an inline style on the section, so it
  resolves against the DOCUMENT rather than this stylesheet — which is why
  the builder writes a three-level `../../../img/...` path there and not the
  two-level one every rule in this file uses.

  This must stay AFTER the `@media (min-width: 64rem)` block that sets the
  wheel: `.page-hero::after` and `.article-hero::after` have identical
  specificity (0,1,1) and a media query adds none, so source order alone
  decides it. Everything else is inherited, including the `display: none`
  below 64rem — a phone never fetches the image for this.
*/
.article-page .article-hero::after {
  left: auto;
  width: min(46rem, 58%);
  background-image: var(--hero-mark);
  background-size: cover;
  background-position: 50% 50%;
  opacity: 0.34;
  -webkit-mask-image: linear-gradient(to left, #000 28%, transparent 96%);
          mask-image: linear-gradient(to left, #000 28%, transparent 96%);
}

  /* Tighten the gap between the headline block and the article body by ~40%.
     That gap is the hero's padding-bottom (var(--space-section)) plus the
     .section padding-top below it; halving each side and rounding lands the
     combined space at ~0.6 of its former size on both. */
  .article-page .article-hero {
    padding-bottom: calc(var(--space-section) * 0.6);
  }

  .article-page .article__back {
    margin-bottom: var(--space-xs);
  }

  /* The base .link-arrow slides its arrow RIGHT on hover; this one points
     back, so it has to travel the other way or it walks away from its own
     direction of travel. */
  .article-page .article__back svg {
    transition: transform var(--dur-fast) var(--ease-out);
  }

  .article-page .article__back:hover svg {
    transform: translateX(-3px);
  }

  /* Smaller than the --fs-h1 a page hero normally uses: those are one- or
     two-word page names capped at 20ch, while a headline runs 40-60
     characters and at 104px would fill the screen on its own. */
  .article-page .article__title {
    max-width: 24ch;
    font-size: clamp(1.875rem, 1.1rem + 3.2vw, 3.5rem);
    line-height: var(--lh-snug);
  }

  .article-page .article__date {
    display: block;
    font-family: var(--font-mono);
    font-size: var(--fs-mono-label);
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--text-muted);
  }

/* ---- the reading column ------------------------------------------------ */

.article-page .article {
  background: var(--surface-base);
  padding-top: calc(var(--space-section) * 0.6);
}

  /*
    Capped and FLUSH LEFT — no `margin-inline: auto`. Centring it would put
    the article's left edge somewhere the "more news" grid below it does not
    share, which is the exact inconsistency §0.1.18 exists to prevent. This
    is safe to cap because .shell sits on the PARENT div, not on this
    element; never move the cap up onto the .shell itself.
  */
  .article-page .article__inner {
    max-width: 46rem;
  }

  /*
    Above 62rem the reading column keeps its 46rem cap and a sticky rail takes
    the space beside it — the article read as "empty" on a desktop because the
    right half of the page was bare. The grid REPLACES the 46rem cap with an
    explicit first track of the same size, so the article's left edge is
    exactly where it was and still lines up with the "more news" grid below
    (§0.1.18: the cap lives on this element, never on the .shell parent).
  */
  /*
    76rem, not 62rem: the shell's own gutters take up to 8rem, so the two
    tracks plus the gap (46 + 3 + 16 = 65rem) only fit inside the content
    column from about there. At 62rem they overflowed it by ~300px.
  */
  @media (min-width: 76rem) {
    .article-page .article__inner {
      display: grid;
      max-width: none;
      grid-template-columns: minmax(0, 46rem) minmax(16rem, 20rem);
      gap: var(--space-xl);
      align-items: start;
    }
  }

  /* ---- the sticky rail ---- */

  .article-page .article__rail {
    display: grid;
    gap: var(--space-md);
    margin-top: var(--space-xl);
  }

  @media (min-width: 76rem) {
    .article-page .article__rail {
      margin-top: 0;
      position: sticky;
      /* clears the sticky header, derived from its own token so the two
         cannot drift apart */
      top: calc(var(--header-h) + var(--space-lg));
    }
  }

  .article-page .article__rail-card {
    padding: var(--space-lg);
    background: var(--surface-raised);
    border: 1px solid var(--line-soft);
    border-radius: var(--radius-md);
  }

  .article-page .article__rail-card .eyebrow {
    margin-bottom: var(--space-sm);
  }

  .article-page .article__facts {
    display: grid;
    gap: var(--space-sm);
    margin: 0 0 var(--space-md);
  }

  .article-page .article__facts dt {
    font-family: var(--font-mono);
    font-size: var(--fs-mono-label);
    letter-spacing: var(--tracking-mono);
    text-transform: uppercase;
    color: var(--text-muted);
  }

  .article-page .article__facts dd {
    margin: 0;
    font-family: var(--font-display);
    font-size: var(--fs-h4);
    line-height: var(--lh-snug);
    color: var(--text-warm);
  }

  /* The same red left rule the community callout and the article lede use, so
     this panel reads as part of that one system rather than a new treatment. */
  .article-page .article__rail-body {
    margin: 0 0 var(--space-md);
    padding-left: var(--space-md);
    border-left: 2px solid var(--action);
    color: var(--text-secondary);
  }

  .article-page .article__rail-card--cta .btn {
    width: 100%;
    justify-content: center;
  }

  /*
    `width: fit-content` sizes the figure to the image's INTRINSIC width, and
    `max-width: 100%` clamps it to the column — so a picture is never blown
    up past its own resolution. Three of the six news images only exist at
    300px wide (their sources are 300px crops; see NEWS_IMAGES_LARGE), and a
    small sharp photo reads far better than a 2.4x upscale. Swapping in a
    real full-size source and re-deriving is the whole fix — no CSS change.
  */
  .article-page .article__figure {
    width: fit-content;
    max-width: 100%;
    margin: 0 0 var(--space-xl);
    padding: 0;
    position: relative;
    border: 1px solid var(--line-soft);
    border-radius: var(--radius-md);
    overflow: hidden;
  }

  /*
    The masked corner brackets from the editorial restyle (§0.1.23). NEVER give
    this a z-index: a positioned pseudo-element already paints above its
    non-positioned <img> sibling, and z-index on a masked pseudo-element makes
    Chromium drop the photograph underneath it entirely. Low-alpha white, not
    --line-soft, because it has to read over any photograph.
  */
  .article-page .article__figure::after {
    content: "";
    position: absolute;
    inset: var(--space-sm);
    border: 1px solid rgba(255, 255, 255, 0.42);
    pointer-events: none;
    -webkit-mask-image:
      linear-gradient(to right, #000 0 2.25rem, transparent 2.25rem calc(100% - 2.25rem), #000 calc(100% - 2.25rem) 100%),
      linear-gradient(to bottom, #000 0 2.25rem, transparent 2.25rem calc(100% - 2.25rem), #000 calc(100% - 2.25rem) 100%);
    -webkit-mask-composite: source-in;
            mask-image:
      linear-gradient(to right, #000 0 2.25rem, transparent 2.25rem calc(100% - 2.25rem), #000 calc(100% - 2.25rem) 100%),
      linear-gradient(to bottom, #000 0 2.25rem, transparent 2.25rem calc(100% - 2.25rem), #000 calc(100% - 2.25rem) 100%);
            mask-composite: intersect;
  }

  .article-page .article__figure img {
    display: block;
    max-width: 100%;
    height: auto;
  }

  .article-page .article__body {
    font-size: var(--fs-body-lg);
    line-height: var(--lh-body);
    color: var(--text-primary);
    text-wrap: pretty;
  }

  .article-page .article__body > p {
    margin: 0 0 var(--space-md);
  }

  .article-page .article__body > p:last-child {
    margin-bottom: 0;
  }

  /* The opening paragraph carries the same red left rule the community
     callout and the Corporate Events standfirst use, so a lede reads as a
     lede across the whole site rather than as one more body paragraph. */
  .article-page .article__body > p:first-child {
    padding-left: var(--space-md);
    border-left: 2px solid var(--action);
    color: var(--text-warm);
  }

  /* A display-face initial on the lede, so the article opens with a mark
     rather than with a wall of body copy. `float` keeps it in the text flow,
     so nothing has to be measured or positioned. */
  .article-page .article__body > p:first-child::first-letter {
    float: left;
    margin: 0.04em 0.11em 0 0;
    font-family: var(--font-display);
    font-size: 3.4em;
    line-height: 0.78;
    font-weight: 700;
    color: var(--action-text);
  }

  /* In-body gallery photos (news-meta "gallery" — see tools/_news.py). Same
     framed .article__figure as the lead image; it only needs breathing room
     above, since the lead figure sits at the top of the column and has none. */
  .article-page .article__body > .article__figure {
    margin-block: var(--space-lg) var(--space-lg);
  }

  /*
    Two gallery photos placed at the same point in the article, side by side
    (news-meta gallery items sharing an `after` — see tools/_news.py). The
    figures must NOT keep `width: fit-content` here: that sizes each to its own
    intrinsic width and the pair comes out ragged, so inside a row they fill
    their track instead. One column on a phone, where two half-width race shots
    would be unreadable.
  */
  .article-page .article__figures {
    display: grid;
    gap: var(--space-sm);
    margin-block: var(--space-lg);
  }

  @media (min-width: 34rem) {
    .article-page .article__figures {
      grid-template-columns: 1fr 1fr;
      align-items: start;
    }
  }

  .article-page .article__figures > .article__figure {
    width: auto;
    margin: 0;
  }

  /* Links inside the article's prose — the owner-named phrases from news-meta
     "links". Underlined so they are not carried by colour alone. */
  .article-page .article__body a,
  .article-page .article__credit a {
    color: var(--action-text);
    text-decoration: underline;
    text-underline-offset: 0.18em;
  }

  .article-page .article__body a:hover,
  .article-page .article__body a:focus-visible,
  .article-page .article__credit a:hover,
  .article-page .article__credit a:focus-visible {
    color: var(--color-white);
  }

  .article-page .article__figure figcaption {
    padding: var(--space-2xs) var(--space-sm) var(--space-xs);
    font-family: var(--font-mono);
    font-size: var(--fs-caption);
    letter-spacing: var(--tracking-mono);
    text-transform: uppercase;
    color: var(--text-muted);
  }

  /* Photo credit, printed under the body when the article carries one. */
  .article-page .article__credit {
    margin-top: var(--space-md);
    font-family: var(--font-mono);
    font-size: var(--fs-caption);
    letter-spacing: var(--tracking-mono);
    text-transform: uppercase;
    color: var(--text-muted);
  }

/* ---- pulled-out closing statement --------------------------------------- */

  /*
    An article's sign-off, lifted out of the prose into a framed panel so it
    reads as a statement rather than as one more paragraph (owner's request on
    the 2026 season piece). It borrows the .community-cta__panel devices —
    a raised ground, two opposite corner brackets and the red left rule — so
    it is the same system as the rest of the site rather than a one-off.
  */
  .article-page .article__callout {
    position: relative;
    margin: var(--space-xl) 0;
    padding: var(--space-lg);
    background: var(--surface-raised);
    border: 1px solid var(--line-strong);
  }

  .article-page .article__callout::before,
  .article-page .article__callout::after {
    content: "";
    position: absolute;
    width: 1.75rem;
    height: 1.75rem;
    border: 2px solid var(--action);
    pointer-events: none;
  }

  .article-page .article__callout::before {
    top: -1px;
    left: -1px;
    border-right: 0;
    border-bottom: 0;
  }

  .article-page .article__callout::after {
    right: -1px;
    bottom: -1px;
    border-left: 0;
    border-top: 0;
  }

  .article-page .article__callout p {
    margin: 0;
    padding-left: var(--space-md);
    border-left: 2px solid var(--action);
    font-family: var(--font-display);
    font-size: var(--fs-h4);
    line-height: 1.25;
    color: var(--color-white);
  }

/* ---- attached documents -------------------------------------------------- */

  /*
    PDFs the article links out to (the championship decision and regulations).
    Presented as real targets rather than an inline "click here", so the file
    type and weight are known before the tap.
  */
  .article-page .article__docs {
    display: grid;
    gap: var(--space-xs);
    margin: var(--space-xl) 0 0;
    padding: 0;
    list-style: none;
  }

  .article-page .article__doc {
    display: flex;
    gap: var(--space-sm);
    align-items: center;
    padding: var(--space-sm) var(--space-md);
    background: var(--surface-raised);
    border: 1px solid var(--line-soft);
    color: var(--text-warm);
    text-decoration: none;
    transition: border-color var(--dur-fast) var(--ease-out),
                background-color var(--dur-fast) var(--ease-out),
                transform var(--dur-fast) var(--ease-out);
  }

  .article-page .article__doc:hover,
  .article-page .article__doc:focus-visible {
    border-color: var(--line-strong);
    background: var(--surface-panel);
    transform: translateX(2px);
  }

  .article-page .article__doc-icon {
    flex: none;
    color: var(--action-text);
  }

  .article-page .article__doc-text {
    display: grid;
    gap: 2px;
    min-width: 0;
  }

  .article-page .article__doc-title {
    font-family: var(--font-display);
    font-size: var(--fs-body);
    letter-spacing: 0.01em;
  }

  .article-page .article__doc-meta {
    font-family: var(--font-mono);
    font-size: var(--fs-caption);
    letter-spacing: var(--tracking-mono);
    text-transform: uppercase;
    color: var(--text-muted);
  }

  @media (prefers-reduced-motion: reduce) {
    .article-page .article__doc {
      transition: none;
    }

    .article-page .article__doc:hover,
    .article-page .article__doc:focus-visible {
      transform: none;
    }
  }

/* ---- results table ------------------------------------------------------ */

  /*
    The classification, when an article supplies one. It scrolls inside its own
    container rather than widening the reading column — a 20-row table must not
    be what decides the article's left edge (§0.1.18).
  */
  .article-page .article__results {
    margin-top: var(--space-xl);
    overflow-x: auto;
    border: 1px solid var(--line-soft);
    border-radius: var(--radius-md);
    background: var(--surface-void);
  }

  .article-page .article__results table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--fs-body);
  }

  .article-page .article__results caption {
    padding: var(--space-sm) var(--space-md);
    border-bottom: 1px solid var(--line-strong);
    font-family: var(--font-display);
    font-size: var(--fs-h4);
    color: var(--text-warm);
    text-align: start;
  }

  .article-page .article__results th,
  .article-page .article__results td {
    padding: var(--space-2xs) var(--space-md);
    text-align: start;
    white-space: nowrap;
  }

  .article-page .article__results thead th {
    font-family: var(--font-mono);
    font-size: var(--fs-caption);
    letter-spacing: var(--tracking-mono);
    text-transform: uppercase;
    color: var(--text-accent);
    border-bottom: 1px solid var(--line-soft);
  }

  .article-page .article__results tbody tr + tr th,
  .article-page .article__results tbody tr + tr td {
    border-top: 1px solid var(--line-faint);
  }

  /* The position column is the row header — mono figures so the numbers line
     up, matching the price list's rate labels. */
  .article-page .article__results tbody th {
    font-family: var(--font-mono);
    font-weight: 500;
    color: var(--text-warm);
    width: 1%;
  }

  .article-page .article__results tbody td {
    color: var(--text-primary);
  }

  /* The top three carry the accent, the way a podium reads on a results
     board — the only decoration in the table. */
  .article-page .article__results tbody tr:nth-child(-n+3) th {
    color: var(--action-text);
  }

/* ---- more news --------------------------------------------------------- */

  /* This row is the "read another one" path, so it must not look like an
     afterthought tacked onto the end of the article. A hairline separates
     it from the reading column above. */
  .article-page .article-more {
    border-top: 1px solid var(--line-faint);
  }
