/* The site's one stylesheet (#37): the tokens, the base and the kit's elements. Base.astro loads it once for
   every page; a page adds only its own composition (where things stand), never a new look for an element. The site
   is built from the kit only (the pilot: "csak a kitbol lehet epitkezni"; website/CODING_STANDARDS.md): a new element
   comes here first, on the tokens, and onto the kit page (src/kit/KitPage.astro, /kit under `astro dev`) for the
   pilot to see. Plain CSS, as the platform's own pages load this file too. */

@import './tokens.css';

@layer base, kit;

@layer base {
  * {
    box-sizing: border-box;
  }

  html,
  body {
    margin: 0;
    min-height: 100%;
    background: var(--color-bg);
    color: var(--color-text);
    font-family: var(--font-body);
    line-height: 1.5;
  }

  /* On body only: on html it would change what a rem is. Body lets the page's backdrop through. */
  body {
    font-size: var(--text-body);
    background: transparent;
  }

  /* The page's backdrop (the pilot, #37: "A2, 0.6x"): a fine dot grid, barely there, standing still behind the
     page while it scrolls, strongest in the middle and fading out towards the edges. */
  body::before {
    content: '';
    position: fixed;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    /* The grid as the pilot tuned it over the instrument (#38: "varialjunk a pottyokkel"). */
    background: radial-gradient(circle, rgb(255 255 255 / 0.12) 0.4px, transparent 0.9px) 0 0 / 12px 12px;
    opacity: 0.3;
    mask-image: radial-gradient(ellipse 51% 60% at 50% 41%, black, transparent);
  }

  /* Behind the grid, the instrument in the dark, in macro, as a halftone (the pilot, #38: "nezzuk mar meg half tone
     osan", then "tul vilagos", "vegyel meg le a fenyebol", "Marad"): a 7px dot screen whose dots grow with the
     picture's light, very dark. One picture for every screen until a portrait one is made. */
  body::after {
    content: '';
    position: fixed;
    inset: -12px;
    z-index: -2;
    pointer-events: none;
    background:
      radial-gradient(circle, #fff 0, #000 75%) 0 0 / 7px 7px,
      url('/backdrop.avif') center / cover no-repeat;
    background-blend-mode: multiply;
    filter: grayscale(1) brightness(9) contrast(6) brightness(0.09);
    opacity: 0.65;
  }

  /* Cards slide in from beyond the window's sides and their light reaches past their box: the window's edge is
     the only place that cuts them, and nothing widens the page; on body too, as a phone's browser otherwise widens
     the page to a card still waiting beyond its side. */
  html,
  body {
    overflow-x: clip;
  }

  a {
    color: var(--color-accent);
  }

  /* Words for a screen reader only, where the eye has an icon. */
  .visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  /* A hidden element stays hidden, whatever display a kit class gives it (the pilot, #52: "kerulhet"). Important
     in the base layer, so it wins over the kit layer too. */
  [hidden] {
    display: none !important;
  }

  /* Pictures cannot be dragged out of the page (the pilot, #37: "kepeket ne lehessen ki dragalni"); Base.astro
     stops the drag in every browser, this in the ones that read it before a drag starts. */
  img {
    -webkit-user-drag: none;
    user-select: none;
  }

  /* Selected text: a faint white under the text's own colour, not the system's blue (the pilot, #37: "a kijelolest
     javitsuk"); letters drawn with a gradient take a plain colour while selected, so they stay readable. */
  ::selection {
    color: var(--color-text);
    background: rgb(255 255 255 / 0.1); /* the pilot: "visszafogottabb", then "FehĂ©r 10%" */
    -webkit-text-fill-color: var(--color-text);
  }
}

@layer kit {
  /* Eyebrow: the small spaced line above a section, with a short rule on each side and dots between the words. */
  .eyebrow {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    gap: 6px 22px;
    margin: 0;
    font-size: 0.75rem;
    letter-spacing: 0.32em;
    text-transform: uppercase;
    color: var(--color-muted);
  }

  .eyebrow::before,
  .eyebrow::after {
    content: '';
    width: 64px;
    height: 1px;
    background: color-mix(in srgb, var(--color-accent) 35%, transparent);
  }

  .eyebrow .dot {
    color: var(--color-accent);
    letter-spacing: 0;
  }

  /* Beside a window the eyebrow starts at the text's edge, without the side rules. */
  .eyebrow-start {
    justify-content: flex-start;
  }

  .eyebrow-start::before,
  .eyebrow-start::after {
    display: none;
  }

  @media (max-width: 600px) {
    .eyebrow {
      font-size: 0.65rem;
      letter-spacing: 0.24em;
    }

    .eyebrow::before,
    .eyebrow::after {
      display: none;
    }
  }

  /* Overline: the small spaced capitals that name a group (a menu's group, a table's columns, a changelog's area,
     a callout); the kit's one small label. */
  .overline,
  .table th,
  .pager small {
    margin: 0;
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--color-muted);
  }

  .side-nav-group > .overline {
    margin-bottom: 6px;
  }

  .overline + .toc {
    margin-top: 6px;
  }

  /* Display: the page's one big heading, lit from above; .accent marks the word in the brand colour. */
  .display {
    margin: 0;
    font-family: var(--font-display);
    font-size: clamp(2.5rem, 8vw, 5.5rem);
    font-weight: 600;
    line-height: 1.05;
    letter-spacing: -0.01em;
    background: var(--gradient-display);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
  }

  /* The publisher's word mark as the page's heading, alone on the middle of the home page: larger than a title. */
  .display-mark {
    font-size: clamp(3rem, 11vw, 8rem);
  }

  /* Tagline: the publisher's line, under its name (the home page, the footer): "The new standard in desktop flight
     simulation" (the pilot, #46: "a minosegre celzok"). */
  .tagline {
    margin: 0;
    font-family: var(--font-display);
    font-size: clamp(1.15rem, 2.4vw, 1.6rem);
    font-weight: 400;
    color: var(--color-text);
    text-wrap: balance;
  }

  /* The accent words of a big title, lit from above as on the coming soon page (the pilot, #37). */
  :is(.display, .heading, .signin-title) .accent {
    background: var(--gradient-accent);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
  }

  /* Heading: a section's or a scene's one sentence, in the display font without the light. */
  .heading {
    margin: 0;
    font-family: var(--font-display);
    font-size: var(--text-heading);
    font-weight: 600;
    line-height: 1.1;
    letter-spacing: -0.01em;
  }

  /* Reveal: a line that comes up as it scrolls into view (scripts/reveal.ts sets .is-in), one after the other in
     their order. With reduced motion it is simply there. */
  .reveal {
    transition:
      opacity 900ms ease,
      transform 900ms cubic-bezier(0.2, 0.7, 0.2, 1);
  }

  .reveal:not(.is-in) {
    opacity: 0;
    transform: translateY(24px);
  }

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

  /* Rabbit: a column of lights between lines, a flash running down it again and again, as the approach lights'
     running flash leads to the runway (the pilot, #39: "valami kellene a mondatok koze... futofeny lefele"). Eight
     lights; with reduced motion they only glow faintly. */
  .rabbit {
    display: grid;
    justify-items: center;
    align-content: space-between;
    height: 22vh;
  }

  .rabbit i {
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: color-mix(in srgb, var(--color-text) 14%, transparent);
    animation: rabbit 2.2s linear infinite;
  }

  .rabbit i:nth-child(2) { animation-delay: 0.1s; }
  .rabbit i:nth-child(3) { animation-delay: 0.2s; }
  .rabbit i:nth-child(4) { animation-delay: 0.3s; }
  .rabbit i:nth-child(5) { animation-delay: 0.4s; }
  .rabbit i:nth-child(6) { animation-delay: 0.5s; }
  .rabbit i:nth-child(7) { animation-delay: 0.6s; }
  .rabbit i:nth-child(8) { animation-delay: 0.7s; }

  @keyframes rabbit {
    0% {
      background: var(--color-text);
      box-shadow: 0 0 12px 3px color-mix(in srgb, var(--color-text) 55%, transparent);
    }
    10%,
    100% {
      background: color-mix(in srgb, var(--color-text) 14%, transparent);
      box-shadow: none;
    }
  }

  @media (prefers-reduced-motion: reduce) {
    .rabbit i {
      animation: none;
    }
  }

  /* Subheading: the name of a part within a section (an editor's part, a step). */
  .subheading {
    margin: 0;
    font-family: var(--font-display);
    font-size: var(--text-subheading);
    font-weight: 500;
    line-height: 1.25;
  }

  /* Fine: small print under a scene, muted. */
  .fine {
    margin: 0;
    font-size: var(--text-fine);
    color: var(--color-muted);
  }

  /* Button: a link or a button that does the page's one thing (.button), or the other choice beside it
     (.button-secondary); .button-small for the header. Lit from above as the big type (the pilot, #37: "b"):
     the accent's gradient, a light top edge, a warm glow under it; the other choice a glass. */
  .button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 14px 28px;
    font-family: var(--font-body);
    font-size: 1rem;
    font-weight: 600;
    line-height: 1.2;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    color: var(--color-on-accent);
    background: var(--gradient-accent);
    border: 1px solid color-mix(in srgb, var(--color-accent-soft) 60%, transparent);
    border-radius: var(--radius);
    box-shadow:
      inset 0 1px 0 rgb(255 255 255 / 0.45),
      0 10px 28px -10px color-mix(in srgb, var(--color-accent) 75%, transparent);
    transition:
      background 160ms ease,
      border-color 160ms ease,
      box-shadow 160ms ease,
      color 160ms ease,
      transform 160ms ease;
  }

  .button:hover {
    box-shadow:
      inset 0 1px 0 rgb(255 255 255 / 0.55),
      0 14px 36px -10px color-mix(in srgb, var(--color-accent) 95%, transparent);
  }

  .button-secondary {
    color: var(--color-text);
    background: var(--glass);
    border-color: var(--line-firm);
    box-shadow:
      inset 0 1px 0 rgb(255 255 255 / 0.12),
      0 10px 28px -14px rgb(0 0 0 / 0.8);
    backdrop-filter: blur(10px);
  }

  .button-secondary:hover {
    background: var(--glass-hover);
    box-shadow:
      inset 0 1px 0 rgb(255 255 255 / 0.18),
      0 10px 28px -14px rgb(0 0 0 / 0.8);
  }

  /* A button whose page or purchase is not there yet (#39, the closing): faint and still, leading nowhere. */
  .button[aria-disabled='true'] {
    opacity: 0.45;
    cursor: default;
    pointer-events: none;
    box-shadow: none;
  }

  /* Where the keyboard is: a thin, quiet frame, never the accent (as in the app: amber around a control reads as a
     warning). */
  .button:focus-visible {
    outline: var(--focus);
    outline-offset: 3px;
  }

  .button:active {
    transform: translateY(1px);
  }

  .button-small {
    padding: 8px 16px;
    font-size: 0.875rem;
  }

  /* Card: the app's own window in space (components/Card.astro; the pilot, #37: "magat az app windowt csinaljuk
     meg terben es szinben"): a whole-window screenshot on a body as thick as a window, in the app's colours. It
     rests turned into the depth, the side it came from nearer (data-from), and slides in from that side as it
     scrolls into view (cards.ts); it does not follow the pointer (the pilot: "az mar tul sok"). The four edges run
     back by --card-depth. Nothing stands behind it (the pilot, #37: "none", after a light and effects on the
     backdrop). */
  .card {
    --card-depth: 16px;
    --card-turn: 25deg; /* the pilot first asked for 35-45Â°, then: "tulsagosan nagy a szog" */
    --card-perspective: 2800px;
    --card-edge: linear-gradient(90deg, var(--color-app-surface), var(--color-app-bg));
    --rest-y: 0deg;
    position: relative;
    width: 100%;
    margin: 0;
    transform-style: preserve-3d;
    transform: perspective(var(--card-perspective)) rotateY(var(--rest-y));
    transition:
      transform 1100ms cubic-bezier(0.2, 0.7, 0.2, 1),
      opacity 900ms ease;
  }

  /* From the right: it rests with its left side further away and its right side, where it came from, nearer
     (the pilot: "en pont forditva dontenem", after the other way round). */
  .card[data-from='right'] {
    --rest-y: calc(var(--card-turn) * -1);
  }

  .card[data-from='left'] {
    --rest-y: var(--card-turn);
  }

  /* On a phone the card is narrow already; turned less, it stays readable. */
  @media (max-width: 760px) {
    .card {
      --card-turn: 14deg;
    }
  }

  .card[data-from='right']:not(.is-in) {
    opacity: 0;
    transform: perspective(var(--card-perspective)) translateX(45vw) rotateY(calc(var(--card-turn) * -1 - 25deg));
  }

  .card[data-from='left']:not(.is-in) {
    opacity: 0;
    transform: perspective(var(--card-perspective)) translateX(-45vw) rotateY(calc(var(--card-turn) + 25deg));
  }

  /* A flat card (Card.astro, flat): straight, no turn, rising a little into place. */
  .card[data-flat] {
    --card-turn: 0deg;
  }

  /* A flat card's picture is a whole window, frame and all: no frame of the card's own over it, its corners the
     window's (Windows 11, about 8 px), so only the window's own edge shows (the pilot: "itt a szogletes keretet mi
     rakjuk ra, vagy a kepen van?", "Igen, vedd le"). The same when shown large (cards.ts, .is-flat). */
  .card[data-flat] .card-face,
  .card-zoom-face.is-flat {
    border: 0;
    border-radius: 8px;
  }

  .card[data-flat][data-from]:not(.is-in) {
    opacity: 0;
    transform: perspective(var(--card-perspective)) translateY(24px);
  }

  .card-face {
    position: relative;
    container-type: inline-size;
    overflow: hidden;
    background: var(--color-app-bg);
    border: 1px solid var(--color-app-line);
    border-radius: 4px;
    box-shadow: 0 50px 80px -30px rgb(0 0 0 / 0.85);
  }

  /* A bare card: no window, only what stands in it, on a stage as wide as a shot (Card.astro, bare). */
  .card[data-bare] {
    cursor: default;
  }

  .card[data-bare] .card-face {
    overflow: visible;
    aspect-ratio: 16 / 9;
    background: none;
    border: 0;
    box-shadow: none;
  }

  .card-edge {
    position: absolute;
    background: var(--card-edge);
  }

  .card-edge[data-edge='left'] {
    top: 0;
    bottom: 0;
    left: 0;
    width: var(--card-depth);
    transform-origin: left;
    transform: rotateY(90deg);
  }

  .card-edge[data-edge='right'] {
    top: 0;
    bottom: 0;
    right: 0;
    width: var(--card-depth);
    transform-origin: right;
    transform: rotateY(-90deg);
  }

  .card-edge[data-edge='top'] {
    top: 0;
    left: 0;
    right: 0;
    height: var(--card-depth);
    transform-origin: top;
    transform: rotateX(-90deg);
    background: linear-gradient(180deg, var(--color-app-line), var(--color-app-surface));
  }

  .card-edge[data-edge='bottom'] {
    bottom: 0;
    left: 0;
    right: 0;
    height: var(--card-depth);
    transform-origin: bottom;
    transform: rotateX(90deg);
    background: var(--color-app-bg);
  }

  /* Its reflection, as if it stood over still water (the pilot, #37: "mintha a to felett lennenek"): the window's
     lower part mirrored right under it, in its plane, faint and fading out fast. Taken off over the instrument
     backdrop (#38: "vedd le a tukorzodest"), tried again over the halftone one (#39: "probaljuk meg visszahozni a
     tukrozodest"). The card keeps room for it below (the reflection is 40% of a window about 0.65 as tall as wide).
     A bare card has none. */
  .card:not([data-bare]) {
    margin-bottom: 0; /* 25% with the reflection; none while it is off, so the card and its text line up (#39) */
  }

  .card-reflection {
    display: none; /* off, to see the cards without it (the pilot: "vedd ki a tukrozodest nezzuk ugy") */
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    height: 40%;
    overflow: hidden;
    border-radius: 4px;
    pointer-events: none;
    opacity: 0.3; /* the pilot: "lehet ici picit visszabb fogni"; a touch more over the halftone backdrop (#39) */
    /* Fading from the card's edge into nothing, gently, long before its own bottom (the pilot: "a tukorkepnel nezzuk
       meg, ha elhalvanyul az alja a teljes transparencybe"). */
    mask-image: linear-gradient(
      to bottom,
      black,
      rgb(0 0 0 / 0.55) 20%,
      rgb(0 0 0 / 0.2) 45%,
      transparent 70%
    );
  }

  /* Not blurred (it was, as water not quite still: "nem tudnak homalyosak lenni a tukorkepek?"): blurred in the
     turned card it smeared (#39: "kasas meg mindig"). A reflection made beforehand as a picture was tried and is not
     wanted (#39: "a generalt megoldast nem kerem marad a css"). */
  .card-reflection .card-shot {
    transform: scaleY(-1);
  }

  /* A card to look at closely (the pilot, #39: "ha kattintok ra akkor befordul kozepre es nagyobb legyen"): a
     click turns it out of the depth to the middle of the window, as large as the window lets it, over a dimmed
     page (cards.ts); a click, Esc or a scroll puts it back. A bare card has nothing to show larger. */
  .card:not([data-bare]) {
    cursor: zoom-in;
  }

  .card:focus-visible {
    outline: var(--focus);
    outline-offset: 6px;
  }

  /* Under the pointer it turns a little towards the reader and comes a touch nearer, so it reads as something to
     click (the pilot, #39: "valami pici mozgas, ha az eger rajta van"); it does not follow the pointer. */
  @media (hover: hover) and (prefers-reduced-motion: no-preference) {
    .card.is-in:hover,
    .card.is-in:focus-visible {
      transform: perspective(var(--card-perspective)) rotateY(calc(var(--rest-y) * 0.8)) scale(1.01);
      transition-duration: 450ms;
    }
  }

  /* The picture shown large: at its own size in the middle, coming from the card's place and turn (cards.ts). */
  .card-zoom {
    position: fixed;
    inset: 0;
    z-index: 60;
    display: grid;
    place-items: center;
    cursor: zoom-out;
  }

  .card-zoom-face {
    position: relative;
    container-type: inline-size;
    overflow: hidden;
    transform-origin: center;
    transition: transform 600ms cubic-bezier(0.2, 0.7, 0.2, 1);
    border: 1px solid var(--color-app-line);
    border-radius: 4px;
    box-shadow: 0 50px 80px -30px rgb(0 0 0 / 0.85);
  }

  /* A gallery's picture stepped to while large: it slides in from its side (--step-from: 1 the right, -1 the left)
     as the one before slides out to the other (.is-leaving, --step-to), both whole and side by side, as a strip of
     film, never one through the other (the pilot: "szellemkepes gorgetesnel azt vegyuk ki"). */
  .card-zoom-face.is-stepped {
    animation: card-zoom-step-in 450ms cubic-bezier(0.3, 0.7, 0.2, 1) both;
  }

  .card-zoom.is-leaving {
    pointer-events: none;
  }

  .card-zoom.is-leaving .card-zoom-face {
    animation: card-zoom-step-out 450ms cubic-bezier(0.3, 0.7, 0.2, 1) both;
  }

  @keyframes card-zoom-step-in {
    from {
      transform: translateX(calc(var(--step-from, 1) * 100vw));
    }
  }

  @keyframes card-zoom-step-out {
    to {
      transform: translateX(calc(var(--step-to, -1) * 100vw));
    }
  }

  /* On the picture shown large, at its foot, its name and line when it has them (a gallery's), on a dark band fading
     up into the picture, coming in as it stands. */
  .card-zoom-caption {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    display: grid;
    gap: 2px;
    justify-items: center;
    margin: 0;
    padding: 48px 24px 18px;
    text-align: center;
    background: linear-gradient(to top, rgb(5 5 6 / 0.9), rgb(5 5 6 / 0.6) 55%, transparent);
    animation: card-zoom-caption 400ms ease 450ms both;
  }

  .card-zoom-caption .gallery-line {
    color: var(--color-text);
  }

  @keyframes card-zoom-caption {
    from { opacity: 0; }
  }

  @media (prefers-reduced-motion: reduce) {
    .card-zoom-face {
      transition: none;
    }

    .card-zoom-caption,
    .card-zoom-face.is-stepped,
    .card-zoom.is-leaving .card-zoom-face {
      animation: none;
    }
  }

  .card-veil {
    position: fixed;
    inset: 0;
    z-index: 55;
    background: rgb(5 5 6 / 0.8);
    backdrop-filter: blur(4px);
    opacity: 0;
    pointer-events: none;
    transition: opacity 400ms ease;
  }

  .card-veil.is-on {
    opacity: 1;
    pointer-events: auto;
    cursor: zoom-out;
  }

  .card-shot {
    display: block;
    width: 100%;
    height: auto;
  }

  .card-missing {
    display: grid;
    place-items: center;
    aspect-ratio: 16 / 10;
    border: 1px dashed var(--color-muted);
    color: var(--color-muted);
  }

  /* Gallery (components/Gallery.astro; #39, the editor's scene: "gorgetos kep galeria [...] teljes kepernyos
     kepekkent [...] keretestul"): the app's whole windows side by side, all of one height (--gallery-h), scrolling
     sideways and settling with one on the middle; its neighbours stand dimmed at the sides and fade out by the
     gallery's edges. Under the one on the middle its name and its line; under all, the arrows and the dots. Each
     window a flat card that opens large on a click. */
  .gallery {
    --gallery-h: clamp(240px, calc(100svh - 67px - 430px), 600px);
    display: grid;
    gap: 14px;
    width: 100%;
  }

  .gallery-track {
    display: flex;
    gap: 40px;
    padding: 6px 30%;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
    mask-image: linear-gradient(to right, transparent, black 14%, black 86%, transparent);
  }

  .gallery-track::-webkit-scrollbar {
    display: none;
  }

  .gallery-item {
    flex: 0 0 auto;
    display: grid;
    gap: 10px;
    width: calc(var(--gallery-h) * var(--ratio));
    margin: 0;
    scroll-snap-align: center;
    opacity: 0.4;
    transition: opacity 350ms ease;
  }

  .gallery-item[data-current] {
    opacity: 1;
  }

  .gallery-item figcaption {
    display: grid;
    gap: 2px;
    justify-items: center;
    text-align: center;
    visibility: hidden;
  }

  .gallery-item[data-current] figcaption {
    visibility: visible;
  }

  .gallery-name {
    color: var(--color-accent);
    font-size: var(--text-fine);
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
  }

  .gallery-line {
    font-size: var(--text-fine);
    color: var(--color-muted);
  }

  .gallery-controls {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 16px;
  }

  .gallery-arrow {
    display: grid;
    place-items: center;
    width: 36px;
    height: 36px;
    padding: 0;
    border: 1px solid var(--line-firm);
    border-radius: 50%;
    background: var(--wash);
    color: var(--color-text);
    cursor: pointer;
    transition: border-color 200ms ease;
  }

  .gallery-arrow:hover {
    border-color: var(--color-muted);
  }

  .gallery-arrow:focus-visible,
  .gallery-dot:focus-visible {
    outline: var(--focus);
    outline-offset: 2px;
  }

  .gallery-arrow svg {
    width: 16px;
    height: 16px;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
  }

  .gallery-dots {
    display: flex;
    gap: 8px;
  }

  .gallery-dot {
    width: 8px;
    height: 8px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: var(--line-firm);
    cursor: pointer;
    transition:
      background-color 200ms ease,
      width 200ms ease;
  }

  .gallery-dot[aria-current='true'] {
    width: 22px;
    border-radius: 4px;
    background: var(--color-accent);
  }

  @media (max-width: 760px) {
    .gallery {
      --gallery-h: 52vw;
    }

    .gallery-track {
      gap: 20px;
      padding: 6px 12%;
    }
  }

  /* A price (#39, the product page's closing: "hova szoktak az arat irni"): the amount large in the display font, lit
     from above in the accent, and under it what it buys in one line. */
  .price {
    display: grid;
    justify-items: center;
    gap: 4px;
    margin: 0;
  }

  .price-amount {
    font-family: var(--font-display);
    font-size: var(--text-subheading);
    font-weight: 600;
    line-height: 1.1;
    background: var(--gradient-accent);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
  }

  .price-note {
    font-size: var(--text-fine);
    color: var(--color-muted);
  }

  /* A product's logo, large, as the closing's picture (#39, the product page's closing: "A logó nagyban"): standing
     on a faint glow of the accent. */
  .product-hero-logo {
    display: block;
    width: clamp(150px, 24vh, 260px);
    height: auto;
    filter: drop-shadow(0 0 40px color-mix(in srgb, var(--accent-lit-bottom) 30%, transparent));
  }

  /* Share network (components/ShareNetwork.astro; #39, the sharing scene: "c", a glowing network with labels only):
     points on the page's ground ringed in the accent, the online one large with a halo and a faint glow, lights
     running along the lines from the maker up online and out to the pilots; the words beside them. The points come
     up in the story's order (data-step, .reveal). Wide it runs left to right; on a phone the tall one, top to bottom.
     With reduced motion the lights stand still. */
  .share-net svg {
    display: block;
    width: 100%;
    height: auto;
    overflow: visible;
  }

  .share-net .share-net-tall {
    display: none;
  }

  .share-net-lines path {
    fill: none;
    stroke: var(--color-accent);
    stroke-width: 1.5;
    stroke-dasharray: 3 7;
    opacity: 0.75;
    animation: share-run 1.4s linear infinite;
  }

  @keyframes share-run {
    to {
      stroke-dashoffset: -20;
    }
  }

  .share-net-point circle {
    fill: var(--color-bg);
    stroke: var(--color-accent);
    stroke-width: 1.5;
  }

  .share-net-hub circle:not(.share-net-halo) {
    fill: color-mix(in srgb, var(--color-accent) 10%, var(--color-bg));
    filter: drop-shadow(0 0 14px color-mix(in srgb, var(--color-accent) 35%, transparent));
  }

  .share-net-point circle.share-net-halo {
    fill: none;
    stroke-width: 1;
    opacity: 0.25;
  }

  .share-net-icon {
    fill: none;
    stroke: var(--color-accent);
    stroke-width: 1.5;
    stroke-linecap: round;
    stroke-linejoin: round;
  }

  .share-net-name {
    fill: var(--color-text);
    font-family: var(--font-body);
    font-size: 15px;
    font-weight: 600;
  }

  .share-net-line {
    fill: var(--color-muted);
    font-family: var(--font-body);
    font-size: 12px;
  }

  .share-net-ok {
    fill: var(--color-ok);
    font-weight: 700;
  }

  /* The story's order: the maker, online, then the three pilots (data-step). */
  .share-net .reveal {
    transition-delay: calc(200ms + var(--step, 0) * 300ms);
  }

  .share-net [data-step='1'] { --step: 1; }
  .share-net [data-step='2'] { --step: 2; }
  .share-net [data-step='3'] { --step: 3; }
  .share-net [data-step='4'] { --step: 4; }

  @media (prefers-reduced-motion: reduce) {
    .share-net-lines path {
      animation: none;
    }
  }

  @media (max-width: 760px) {
    .share-net .share-net-wide {
      display: none;
    }

    .share-net .share-net-tall {
      display: block;
      max-width: 360px;
      margin: 0 auto;
    }
  }

  /* The checklist on a sim shot (components/SimChecklist.astro): drawn by the page over a clean shot, as the add-on
     draws it in the sim (the product's addon/.../OsdChecklist/checklist.css), so it can tick its rows one by one
     (the pilot, #39: "te rakod ra a checklistet a kepre es a mozgas az lesz, hogy pipalodik"; sim-checklist.ts). Its
     size follows the shot's width (cqw of the card's face), so it stands on the shot as it stood in the sim. */
  .sim-checklist {
    --sim-font: 1.25cqw;
    position: absolute;
    width: 30em;
    font-family: var(--font-sim);
    font-size: var(--sim-font);
    line-height: 1.6;
    color: var(--color-sim-text);
    white-space: nowrap;
    pointer-events: none;
    /* The add-on's sharp dark outline in all eight directions: readable in front of light and dark. */
    text-shadow:
      -1px -1px 0 #000,
      1px -1px 0 #000,
      -1px 1px 0 #000,
      1px 1px 0 #000,
      0 -1px 0 #000,
      0 1px 0 #000,
      -1px 0 0 #000,
      1px 0 0 #000;
  }

  .sim-checklist p {
    margin: 0;
  }

  /* The look the pilot sets with the wheel in the sim (the add-on's appearance-control.js), as data on the panel
     (sim-checklist.ts steps through them): the backing's opacity (data-bg, in %) and colour (data-color), the size
     (data-size, the add-on's M 18 px, L 20, XL 22) and the responses' colour (data-resp; the current row's mark
     takes the other one). Without data-bg there is no backing, as on the opening's shot. */
  .sim-checklist[data-bg] {
    --sim-backing: var(--color-sim-backing-black);
    padding: 0.45em 0.8em;
    margin: -0.45em -0.8em;
    border-radius: 10px;
    background: color-mix(in srgb, var(--sim-backing) var(--sim-opacity), transparent);
    transition:
      background-color 400ms ease,
      font-size 400ms ease;
  }

  /* The add-on's nine levels, BG 1 to BG 9: none, framed, then 15 to 100 (appearance-control.js). */
  .sim-checklist[data-bg='0'] { --sim-opacity: 0%; }
  .sim-checklist[data-bg='framed'] { --sim-opacity: 0%; }
  .sim-checklist[data-bg='15'] { --sim-opacity: 15%; }
  .sim-checklist[data-bg='30'] { --sim-opacity: 30%; }
  .sim-checklist[data-bg='45'] { --sim-opacity: 45%; }
  .sim-checklist[data-bg='55'] { --sim-opacity: 55%; }
  .sim-checklist[data-bg='70'] { --sim-opacity: 70%; }
  .sim-checklist[data-bg='85'] { --sim-opacity: 85%; }
  .sim-checklist[data-bg='100'] { --sim-opacity: 100%; }

  /* Framed (BG 2): no backing, a frame round the rows to show where the panel is, as the add-on draws it
     (checklist.css .cl-frame): a 1 px line in the dashes' grey with a dark edge outside and inside. */
  .sim-checklist[data-bg='framed'] {
    box-shadow:
      inset 0 0 0 1px color-mix(in srgb, var(--color-sim-backing-black) 65%, transparent),
      inset 0 0 0 2px var(--color-sim-rule),
      inset 0 0 0 3px color-mix(in srgb, var(--color-sim-backing-black) 65%, transparent);
  }
  .sim-checklist[data-color='graphite'] { --sim-backing: var(--color-sim-backing-graphite); }
  .sim-checklist[data-color='navy'] { --sim-backing: var(--color-sim-backing-navy); }
  .sim-checklist[data-color='steel'] { --sim-backing: var(--color-sim-backing-steel); }
  .sim-checklist[data-color='teal'] { --sim-backing: var(--color-sim-backing-teal); }
  .sim-checklist[data-color='green'] { --sim-backing: var(--color-sim-backing-green); }
  .sim-checklist[data-color='red'] { --sim-backing: var(--color-sim-backing-red); }
  .sim-checklist[data-color='purple'] { --sim-backing: var(--color-sim-backing-purple); }
  .sim-checklist[data-size='l'] { font-size: calc(var(--sim-font) * 20 / 18); }
  .sim-checklist[data-size='xl'] { font-size: calc(var(--sim-font) * 22 / 18); }

  .sim-checklist[data-resp='amber'] .sim-row:not([data-state='done']) .sim-value {
    color: var(--color-sim-current);
  }

  .sim-checklist[data-resp='amber'] .sim-row[data-state='current'] .sim-mark {
    color: var(--color-sim-value);
  }

  .sim-checklist[data-resp='amber'] .sim-row[data-state='current']::before {
    background: var(--color-sim-value);
  }

  /* White: no colour of their own, the responses as their rows; the current mark white. */
  .sim-checklist[data-resp='white'] .sim-row:not([data-state='done']) .sim-value {
    color: inherit;
  }

  .sim-checklist[data-resp='white'] .sim-row[data-state='current'] .sim-mark,
  .sim-checklist[data-resp='white'] .sim-title {
    color: var(--color-text);
  }

  .sim-checklist[data-resp='white'] .sim-row[data-state='current']::before {
    background: var(--color-text);
  }

  .sim-checklist[data-resp='amber'] .sim-title {
    color: var(--color-sim-value);
  }

  /* A badge on a wheel change, above the title at the right (SIZE XL, COLOR NAVY): dark letters on the add-on's
     yellow, readable whatever the backing. Only while it is fresh (data-badge on). */
  .sim-badge {
    display: block;
    height: 1.5em;
    margin-bottom: 0.4em;
    text-align: right;
    font-size: 0.6em;
    line-height: 1.5;
  }

  .sim-badge span {
    display: inline-block;
    padding: 0 0.5em;
    border-radius: 3px;
    background: var(--color-sim-badge);
    color: var(--color-app-bg);
    font-weight: 700;
    text-shadow: none;
    opacity: 0;
    transition: opacity 200ms ease;
  }

  .sim-checklist[data-badge] .sim-badge span {
    opacity: 1;
  }

  /* The add-on's status row above the title, beside a joystick: MUTED at its right end while the voice is muted (the
     MUTE button), in a quiet grey, as the add-on writes it (checklist-renderer.js, cl-mute). */
  .sim-status {
    display: block;
    height: 1.5em;
    margin-bottom: 0.4em;
    text-align: right;
    font-size: 0.6em;
    line-height: 1.5;
    color: var(--color-sim-rule);
    font-weight: 700;
    opacity: 0;
    transition: opacity 200ms ease;
  }

  .sim-checklist[data-muted] .sim-status {
    opacity: 1;
  }

  /* On a bare card the panel itself is the picture: large on its stage, with the window's shadow under it. */
  .card[data-bare] .sim-checklist {
    --sim-font: 2.5cqw;
    filter: drop-shadow(0 40px 50px rgb(0 0 0 / 0.7));
  }

  .card[data-bare] .sim-pointer {
    width: 2.4cqw;
  }

  /* A stage for a panel standing straight, not on a card (beside a joystick: the pilot, "itt nem fogunk 3dzni mert
     torzitja"): as wide as its column, as high as the panel, the panel's size following its width. */
  .sim-stage {
    container-type: inline-size;
  }

  .sim-stage .sim-checklist {
    position: relative;
    margin: 0;
  }

  /* Over the voice's lanes (VoiceLanes.astro) the panel fills its stage. */
  .sim-stage .sim-checklist[data-voice] {
    --sim-font: 3.1cqw;
  }

  /* Ways: the ways a thing is done today, side by side (.ways > .way, each coming up after the one before: --i), each
     with its answer stamped on it (.stamp: the product page, #39). The stamp wears through the SVG filters
     #stamp-wear and #stamp-wear-light, which the page holds. */
  .ways {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 40px;
    width: 100%;
    margin: 0;
    padding: 0;
    list-style: none;
    text-align: left;
  }

  .way {
    display: grid;
    align-content: start;
    gap: 14px;
    padding-top: 22px;
    border-top: 1px solid var(--line-soft);
    transition-delay: calc(var(--i) * 180ms);
  }

  /* The page's own type and colours, as in the scenes around it (the pilot: "hasznaljuk a mar kitalalt
     typografiat szinvilagot"): a scene's heading, a third of the width smaller. */
  .way-title {
    font-size: clamp(1.75rem, 2.8vw, 2.4rem);
  }

  .way-title .accent {
    white-space: nowrap; /* "Half gone." stays on one line */
  }

  .way-text {
    text-wrap: pretty;
  }

  /* The answer stamped across the trouble, slanted (the pilot: "animalva ferden es mintha lepecsetelnenk, hogy ezt
     mi mind megoldjuk"): it comes down large once its card is up and presses in. With reduced motion it simply
     stands there. */
  .way {
    position: relative;
    padding-bottom: 76px; /* the stamp under the text, only its corner over it, so the trouble still reads */
    --stamp-delay: calc(var(--i) * 180ms + 1000ms);
  }

  .stamp {
    position: absolute;
    right: 4%;
    bottom: 0;
    padding: 9px 18px;
    font-family: var(--font-display);
    font-size: 1.3rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    white-space: nowrap;
    color: var(--color-accent);
    transform: rotate(-9deg);
    pointer-events: none;
  }

  /* Worn like real ink (the pilot: "a pecset szelei ilyen lekopottak legyenek"): the frame hard, the letters
     lightly. */
  .stamp::before {
    content: '';
    position: absolute;
    inset: 0;
    border: 3px solid var(--color-accent);
    border-radius: 6px;
    outline: 1px solid color-mix(in srgb, var(--color-accent) 60%, transparent);
    outline-offset: 3px;
    filter: url(#stamp-wear);
  }

  .stamp span {
    display: block;
    filter: url(#stamp-wear-light);
  }

  .stamp-wear {
    position: absolute;
  }

  .way.is-in .stamp {
    animation: stamp 520ms cubic-bezier(0.3, 0, 0.4, 1) var(--stamp-delay) both;
  }

  @keyframes stamp {
    0% {
      opacity: 0;
      transform: rotate(-16deg) scale(2.4);
    }
    55% {
      opacity: 1;
      transform: rotate(-9deg) scale(0.94);
    }
    75% {
      transform: rotate(-9deg) scale(1.03);
    }
    100% {
      opacity: 1;
      transform: rotate(-9deg) scale(1);
    }
  }

  @media (prefers-reduced-motion: reduce) {
    .way.is-in .stamp {
      animation: none;
    }
  }

  @media (max-width: 760px) {
    .ways {
      grid-template-columns: 1fr;
    }

    .way {
      transition-delay: 0ms;
      --stamp-delay: 900ms;
    }
  }

  /* Poster: a product shown by its panel alone, standing straight and large, read out over the voice's small waves
     (VoiceLanes mini), the sim's cockpit out of focus behind it, a faint warm glow (the pilot, #46: "nekem nem eleg
     utos ez a kep", "mutasd a 4est", "probald odarakni a pilotafulket moge"; "a sarga hatter tul sok"). The cockpit
     (.poster-shot) fades out by every edge, so it reaches nothing round it ("egymasra csusznak dolgok"). */
  .poster {
    position: relative;
    padding: 48px 32px 56px;
    isolation: isolate;
  }

  .poster::before {
    content: '';
    position: absolute;
    inset: -10% -6%;
    z-index: -1;
    background: radial-gradient(
      ellipse 50% 50% at 50% 50%,
      color-mix(in srgb, var(--accent-lit-bottom) 9%, transparent),
      transparent 70%
    );
    pointer-events: none;
  }

  .poster-shot {
    position: absolute;
    inset: 0;
    z-index: -1;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: 50% 62%; /* the windscreen and the glareshield's instruments, where the panel stands */
    filter: blur(3px) brightness(1.15) saturate(1.05);
    mask-image:
      linear-gradient(to right, transparent, black 18%, black 82%, transparent),
      linear-gradient(to bottom, transparent, black 20%, black 80%, transparent);
    mask-composite: intersect;
    pointer-events: none;
  }

  .poster .sim-stage {
    width: 100%;
    filter: drop-shadow(0 30px 60px rgb(0 0 0 / 0.6));
  }

  /* Larger than over the voice's lanes on the product page: here it is the picture. */
  .poster .sim-stage .sim-checklist[data-voice] {
    --sim-font: 3.5cqw;
    box-shadow: 0 0 70px -20px color-mix(in srgb, var(--accent-lit-bottom) 14%, transparent);
  }

  @media (max-width: 760px) {
    .poster {
      padding: 24px 0;
    }
  }

  /* Beside a joystick (Stick.astro) the panel fills its stage, and goes when it is hidden. */
  .sim-stage .sim-checklist[data-stick] {
    --sim-font: 2.9cqw;
    transition: opacity 300ms ease;
  }

  /* The checklist NEXT turns to: shown in place of the first while the panel is on it (data-page). */
  .sim-page[data-page='next'],
  .sim-checklist[data-page='next'] .sim-page:not([data-page]) {
    display: none;
  }

  .sim-checklist[data-page='next'] .sim-page[data-page='next'] {
    display: block;
  }

  .sim-checklist[data-hidden] {
    opacity: 0;
  }

  /* A joystick's grip in line with the add-on's six buttons named on it (components/Stick.astro), standing still
     beside the panel's bare card; the button pressed lights up in the accent with its name (sim-checklist.ts sets data-press). */
  .stick {
    display: block;
    width: 100%;
    height: auto;
    overflow: visible;
  }

  .stick-body,
  .stick-ring {
    fill: none;
    stroke: var(--color-muted);
    stroke-width: 1.5;
    stroke-linejoin: round;
  }

  /* A glint along a side button's face. */
  .stick-glint {
    fill: none;
    stroke: var(--color-text);
    stroke-width: 1;
    stroke-linecap: round;
    opacity: 0.5;
  }

  /* Seams, folds and rims: the drawing's finer lines. */
  .stick-detail {
    fill: none;
    stroke: var(--line-firm);
    stroke-width: 1;
    stroke-linecap: round;
  }

  .stick-button {
    fill: var(--color-app-surface);
    stroke: var(--color-text);
    stroke-width: 1.5;
    stroke-linejoin: round;
    transition:
      fill 150ms ease,
      filter 150ms ease;
  }

  .stick-label path,
  .stick-label-line {
    fill: none;
    stroke: var(--line-firm);
    stroke-width: 1;
  }

  .stick-label text {
    fill: var(--color-muted);
    font-family: var(--font-body);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.08em;
    transition: fill 150ms ease;
  }

  .stick[data-press='check'] .stick-button[data-button='check'],
  .stick[data-press='back'] .stick-button[data-button='back'],
  .stick[data-press='next'] .stick-button[data-button='next'],
  .stick[data-press='prev'] .stick-button[data-button='prev'],
  .stick[data-press='hide'] .stick-button[data-button='hide'],
  .stick[data-press='reset'] .stick-button[data-button='reset'],
  .stick[data-press='mute'] .stick-button[data-button='mute'],
  .stick[data-press='locate'] .stick-button[data-button='locate'] {
    fill: var(--color-accent);
    filter: drop-shadow(0 0 6px var(--color-accent));
  }

  .stick[data-press='check'] .stick-label[data-button='check'] text,
  .stick[data-press='back'] .stick-label[data-button='back'] text,
  .stick[data-press='next'] .stick-label[data-button='next'] text,
  .stick[data-press='prev'] .stick-label[data-button='prev'] text,
  .stick[data-press='hide'] .stick-label[data-button='hide'] text,
  .stick[data-press='reset'] .stick-label[data-button='reset'] text,
  .stick[data-press='mute'] .stick-label[data-button='mute'] text,
  .stick[data-press='locate'] .stick-label[data-button='locate'] text {
    fill: var(--color-accent);
  }

  .stick[data-press='check'] .stick-label[data-button='check'] path,
  .stick[data-press='back'] .stick-label[data-button='back'] path,
  .stick[data-press='next'] .stick-label[data-button='next'] path,
  .stick[data-press='prev'] .stick-label[data-button='prev'] path,
  .stick[data-press='hide'] .stick-label[data-button='hide'] path,
  .stick[data-press='reset'] .stick-label[data-button='reset'] path,
  .stick[data-press='mute'] .stick-label[data-button='mute'] path,
  .stick[data-press='locate'] .stick-label[data-button='locate'] path {
    stroke: var(--color-accent);
  }

  /* The voice under a panel (components/VoiceLanes.astro), as the pilot drew it: two waves one over the other, bars
     mirrored round their middle line (their heights set by the component, a bell from the middle out), glowing; the
     checklist's in the accent with "reads" under it, the pilot's in the responses' blue with "you answer". A wave
     moves and lights while that one speaks (data-on), and rests dim when not; under both, what is said, as a film's
     subtitle. With reduced motion the waves stand, lit. */
  .voice {
    display: grid;
    justify-items: center;
    gap: 40px;
    width: 100%;
  }

  /* The checklist's wave on the panel's left, the pilot's on its right, the subtitle under all three; on a narrow
     screen one under the other. */
  .voice-waves {
    --voice-color: var(--color-accent);
    display: grid;
    /* The middle a set width: a panel sized by its own width (container) has none to give an auto column. */
    grid-template-columns: minmax(0, 1fr) minmax(0, 520px) minmax(0, 1fr);
    align-items: center;
    justify-items: center;
    gap: 22px 40px;
    width: 100%;
  }

  .voice-line {
    grid-column: 1 / -1;
  }

  @media (max-width: 900px) {
    .voice-waves {
      grid-template-columns: minmax(0, 1fr);
    }

    .voice-waves > :nth-child(2) {
      order: -1;
    }
  }

  /* A small one (data-mini): the two waves side by side over the panel, each a speaker or microphone and a short
     wave, without who speaks; the subtitle under the panel. */
  .voice[data-mini] .voice-waves {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 18px 28px;
  }

  .voice[data-mini] .voice-waves > :nth-child(2) {
    grid-column: 1 / -1;
    grid-row: 2;
    order: 0;
  }

  .voice[data-mini] .voice-lane {
    grid-row: 1;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    gap: 12px;
  }

  .voice[data-mini] .voice-who {
    display: none;
  }

  .voice[data-mini] .voice-lane-icon {
    width: 18px;
    height: 18px;
  }

  .voice[data-mini] .voice-wave {
    height: 30px;
  }

  .voice[data-mini] .voice-wave i {
    width: 2px;
  }

  .voice[data-mini] .voice-line {
    grid-row: 3;
    margin: 4px 0 0;
    font-size: var(--text-body);
  }

  .voice-lane {
    display: grid;
    justify-items: center;
    gap: 8px;
    width: 100%;
  }

  .voice-lane[data-who='you'] {
    --voice-color: var(--color-sim-value);
  }

  /* Who speaks, under a wave: "reads" and "you answer" until a voice is picked, then the voice with its gender's
     icon ("Emma reads"); the icon of the voice's gender only (data-gender). */
  .voice-who {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: var(--text-body);
    color: var(--color-muted);
    transition: color 300ms ease;
  }

  .voice-who .gender-icon {
    display: none;
  }

  .voice-who[data-gender='female'] .gender-icon[data-gender='female'],
  .voice-who[data-gender='male'] .gender-icon[data-gender='male'] {
    display: block;
  }

  /* A voice's gender, as the app marks it: Lucide's venus and mars in its colours for them (GenderIcon.astro). */
  .gender-icon {
    width: 1em;
    height: 1em;
    flex: none;
    fill: none;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
  }

  .gender-icon[data-gender='female'] {
    stroke: var(--color-gender-female);
  }

  .gender-icon[data-gender='male'] {
    stroke: var(--color-gender-male);
  }

  .voice-lane[data-on] .voice-who {
    color: var(--color-text);
  }

  /* The speaker over the checklist's wave, the microphone over the pilot's, in the wave's colour, lit with it. */
  .voice-lane-icon {
    width: 26px;
    height: 26px;
    fill: none;
    stroke: var(--voice-color);
    stroke-width: 1.6;
    stroke-linecap: round;
    stroke-linejoin: round;
    opacity: 0.35;
    transition: opacity 300ms ease;
  }

  .voice-lane[data-on] .voice-lane-icon {
    opacity: 1;
    filter: drop-shadow(0 0 6px var(--voice-color));
  }

  .voice-wave {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    height: 72px;
    opacity: 0.3;
    filter: drop-shadow(0 0 6px var(--voice-color));
    transition: opacity 300ms ease;
  }

  .voice-lane[data-on] .voice-wave {
    opacity: 1;
  }

  .voice-wave i {
    width: 3px;
    border-radius: 2px;
    background: var(--voice-color);
    transform: scaleY(0.35);
    transition: transform 300ms ease;
  }

  .voice-lane[data-on] .voice-wave i {
    animation: voice-bar 520ms ease-in-out infinite alternate;
  }

  /* Each bar its own pace, so the wave reads as speech, not as a pulse. */
  .voice-lane[data-on] .voice-wave i:nth-child(2n) { animation-duration: 380ms; }
  .voice-lane[data-on] .voice-wave i:nth-child(3n) { animation-duration: 610ms; animation-delay: -90ms; }
  .voice-lane[data-on] .voice-wave i:nth-child(5n) { animation-duration: 450ms; animation-delay: -220ms; }
  .voice-lane[data-on] .voice-wave i:nth-child(7n) { animation-delay: -310ms; }

  @keyframes voice-bar {
    from { transform: scaleY(0.25); }
    to { transform: scaleY(1); }
  }

  @media (prefers-reduced-motion: reduce) {
    .voice-lane[data-on] .voice-wave i {
      animation: none;
      transform: scaleY(0.8);
    }
  }

  .voice-line {
    min-height: 1.5em;
    margin: 18px 0 0;
    text-align: center;
    font-size: var(--text-subheading);
    color: var(--color-text);
  }

  /* The subtitle in the colour of who speaks, its wave's: the checklist's accent, the pilot's blue (the pilot: "a
     felirat szine kovesse hogy ki beszel", "a waveform szinet kellene"). */
  .voice-line[data-who='reads'] {
    color: var(--color-accent);
  }

  .voice-line[data-who='you'] {
    color: var(--color-sim-value);
  }

  /* The voice's deck under the waves (VoiceLanes.astro): one raised panel holding the voices to hear and the two
     settings, a line between them; the note on the app under it. */
  .voice-deck {
    display: grid;
    width: min(100%, 1000px);
    border: 1px solid var(--line-soft);
    border-radius: var(--radius-lg);
    background: linear-gradient(180deg, var(--wash-strong), var(--wash));
  }

  .voice-deck-part {
    display: grid;
    justify-items: center;
    gap: 16px;
    padding: 22px 24px;
  }

  .voice-deck-part + .voice-deck-part {
    border-top: 1px solid var(--line);
  }

  .voice-deck-name {
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--color-muted);
  }

  .voice-deck-note {
    margin: -16px 0 0;
    max-width: 68ch;
    font-size: var(--text-fine);
    color: var(--color-muted);
    text-wrap: pretty;
  }

  /* One thought a line. */
  .voice-deck-note span {
    display: block;
  }

  .voice-deck-note strong {
    font-weight: 600;
    color: var(--color-text);
  }

  /* A voice to hear: a slim chip, its gender's icon, its name and its accent; the one reading lit in the accent. */
  .voice-picks {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 8px;
  }

  .voice-pick {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 12px 8px 14px;
    border: 1px solid var(--line-firm);
    border-radius: 999px;
    background: var(--wash);
    color: var(--color-text);
    font: inherit;
    font-weight: 600;
    cursor: pointer;
    transition:
      border-color 200ms ease,
      background-color 200ms ease,
      box-shadow 200ms ease;
  }

  .voice-pick:hover {
    border-color: var(--color-muted);
  }

  .voice-pick:focus-visible {
    outline: var(--focus);
    outline-offset: 2px;
  }

  .voice-pick[aria-pressed='true'] {
    border-color: var(--color-accent);
    background: color-mix(in srgb, var(--color-accent) 12%, transparent);
    box-shadow: 0 0 18px color-mix(in srgb, var(--color-accent) 30%, transparent);
  }

  .voice-pick-accent {
    padding: 1px 5px;
    border: 1px solid var(--line-firm);
    border-radius: 4px;
    font-size: 0.68rem;
    letter-spacing: 0.06em;
    color: var(--color-muted);
  }

  /* A crew: two pilots, who reads and who answers, and whether it plays (VoiceLanes.astro; the pilot, #39: "crew
     pairs"). A card, not a pill. */
  .voice-crew {
    display: grid;
    justify-items: start;
    gap: 4px;
    min-width: 190px;
    padding: 12px 16px;
    border-radius: var(--radius-lg);
    font-weight: 400;
    text-align: left;
  }

  .voice-crew-pilot {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
  }

  .voice-crew-pilot .voice-pick-name {
    font-weight: 600;
  }

  .voice-crew-pilot .voice-pick-accent {
    margin-left: auto;
  }

  .voice-crew-role {
    color: var(--color-muted);
  }

  .voice-crew-play {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: 6px;
    font-size: 0.8rem;
    color: var(--color-muted);
  }

  /* A crew's speed when it is not the voices' own (1.2×), after Play. */
  .voice-crew-speed {
    margin-left: 4px;
    padding: 0 5px;
    border: 1px solid var(--line-firm);
    border-radius: 4px;
    font-size: 0.68rem;
    letter-spacing: 0.04em;
    color: var(--color-muted);
  }

  .voice-crew-icon {
    width: 12px;
    height: 12px;
    fill: currentColor;
  }

  .voice-crew [data-shows='stop'],
  .voice-crew[aria-pressed='true'] [data-shows='play'] {
    display: none;
  }

  .voice-crew[aria-pressed='true'] [data-shows='stop'] {
    display: inline;
  }

  .voice-crew[aria-pressed='true'] .voice-crew-play {
    color: var(--color-text);
    font-weight: 600;
  }

  /* The crew that plays: a sharp accent edge, no wash (the pilot: "ez a sarga nem tetszik valami utosebb kell"), and
     four bars jumping beside "Playing" as it speaks. */
  .voice-pick.voice-crew[aria-pressed='true'] {
    border-color: var(--color-accent);
    background: var(--wash-strong);
    box-shadow:
      inset 0 0 0 1px var(--color-accent),
      0 12px 30px -18px color-mix(in srgb, var(--color-accent) 60%, transparent);
  }

  .voice-crew-eq {
    align-items: flex-end;
    gap: 2px;
    height: 12px;
  }

  .voice-crew[aria-pressed='true'] .voice-crew-eq {
    display: inline-flex;
  }

  .voice-crew-eq i {
    width: 3px;
    height: 100%;
    border-radius: 1px;
    background: var(--color-accent);
    transform-origin: bottom;
    animation: voice-crew-eq 900ms ease-in-out infinite;
  }

  .voice-crew-eq i:nth-child(2) { animation-delay: -300ms; }
  .voice-crew-eq i:nth-child(3) { animation-delay: -600ms; }
  .voice-crew-eq i:nth-child(4) { animation-delay: -150ms; }

  @keyframes voice-crew-eq {
    0%, 100% { transform: scaleY(0.25); }
    50% { transform: scaleY(1); }
  }

  @media (prefers-reduced-motion: reduce) {
    .voice-crew-eq i {
      animation: none;
      transform: scaleY(0.7);
    }
  }

  /* The voice's two settings, side by side. */
  .voice-tune {
    grid-template-columns: repeat(2, minmax(0, 260px));
    justify-content: center;
    gap: 16px 48px;
  }

  @media (max-width: 640px) {
    .voice-tune {
      grid-template-columns: minmax(0, 1fr);
    }
  }

  /* Wide, the crews and the two settings side by side, the settings one over the other: the scene stays a screen. */
  @media (min-width: 1000px) {
    .voice-deck {
      grid-template-columns: auto minmax(0, 300px);
      justify-content: center;
    }

    .voice-deck-part + .voice-deck-part {
      border-top: 0;
      border-left: 1px solid var(--line);
    }

    .voice-tune {
      grid-template-columns: minmax(0, 1fr);
      align-content: center;
      gap: 20px;
    }
  }

  /* Range: a slider with its name and value over it; a thin track filled in the accent up to a light round thumb.
     The script that reads it keeps --range-fill (0% to 100%) at its value. */
  .range-field {
    display: grid;
    gap: 10px;
    width: 100%;
    font-size: var(--text-fine);
    color: var(--color-muted);
    text-align: left;
  }

  .range-head {
    display: flex;
    justify-content: space-between;
  }

  .range-head output {
    font-variant-numeric: tabular-nums;
    color: var(--color-text);
  }

  .range {
    --range-fill: 50%;
    width: 100%;
    height: 18px;
    margin: 0;
    background: transparent;
    cursor: pointer;
    appearance: none;
  }

  .range::-webkit-slider-runnable-track {
    height: 4px;
    border-radius: 2px;
    background: linear-gradient(90deg, var(--color-accent) var(--range-fill), var(--line-firm) var(--range-fill));
  }

  .range::-moz-range-track {
    height: 4px;
    border-radius: 2px;
    background: linear-gradient(90deg, var(--color-accent) var(--range-fill), var(--line-firm) var(--range-fill));
  }

  .range::-webkit-slider-thumb {
    width: 16px;
    height: 16px;
    margin-top: -6px;
    border: 3px solid var(--color-accent);
    border-radius: 50%;
    background: var(--color-text);
    appearance: none;
  }

  .range::-moz-range-thumb {
    width: 10px;
    height: 10px;
    border: 3px solid var(--color-accent);
    border-radius: 50%;
    background: var(--color-text);
  }

  .range:focus-visible {
    outline: var(--focus);
    outline-offset: 4px;
  }

  /* Dragged to another place on the screen by the pilot's mouse (sim-checklist.ts moves it). */
  .sim-checklist[data-wheel] {
    transition:
      background-color 400ms ease,
      font-size 400ms ease,
      left 1100ms cubic-bezier(0.45, 0, 0.25, 1) 300ms,
      top 1100ms cubic-bezier(0.45, 0, 0.25, 1) 300ms; /* after the hand has closed on it */
  }

  /* The pilot's mouse on a sim shot: the pointer, and beside it the mouse with its wheel turning and the key held
     with it (Ctrl, Alt) while the wheel changes the panel; "Drag" while it moves it. Sized by the shot's width. */
  .sim-pointer {
    position: absolute;
    left: 88%;
    top: 92%;
    width: 1.5cqw;
    color: var(--color-text);
    pointer-events: none;
    opacity: 0;
    filter: drop-shadow(0 1px 3px rgb(0 0 0 / 0.7));
    transition:
      left 800ms cubic-bezier(0.45, 0, 0.25, 1),
      top 800ms cubic-bezier(0.45, 0, 0.25, 1),
      opacity 300ms ease;
  }

  .sim-pointer[data-on] {
    opacity: 1;
  }

  /* Dragging: it moves with the panel, as slowly. */
  .sim-pointer[data-drag] {
    transition-duration: 1100ms, 1100ms, 300ms;
    transition-delay: 300ms, 300ms, 0ms;
  }

  .sim-arrow {
    display: block;
    transition: opacity 150ms ease;
    width: 100%;
    height: auto;
    fill: currentColor;
    stroke: var(--color-app-bg);
    stroke-width: 1.2;
    stroke-linejoin: round;
  }

  /* Holding the panel: the arrow gives way to a closed hand, light with a dark edge as the arrow (the edge painted
     under the fill), a touch pressed in. */
  .sim-grab {
    position: absolute;
    left: -0.35em;
    top: -0.2em;
    width: 160%;
    height: auto;
    fill: var(--color-text);
    stroke-linecap: round;
    stroke-linejoin: round;
    opacity: 0;
    transform: scale(1.1);
    transition:
      opacity 150ms ease,
      transform 200ms ease;
  }

  .sim-grab g {
    stroke: var(--color-app-bg);
    stroke-width: 4;
    paint-order: stroke;
  }

  .sim-pointer[data-drag] .sim-arrow {
    opacity: 0;
  }

  .sim-pointer[data-drag] .sim-grab {
    opacity: 1;
    transform: scale(0.92);
  }

  /* What the mouse does, large under the card (components/MouseLegend.astro): the keys held, the mouse with its
     wheel turning in the accent (or its left button lit for a drag), and what it changes. */
  .mouse-legend {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 14px;
    min-height: 56px;
    margin-top: 32px;
    font-size: var(--text-body);
    color: var(--color-muted);
    opacity: 0;
    transition: opacity 300ms ease;
  }

  .mouse-legend[data-on] {
    opacity: 1;
  }

  .mouse-legend-keys {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: var(--text-subheading);
  }

  .mouse-legend-keys:empty {
    display: none;
  }

  .mouse-legend-mouse {
    width: 34px;
    height: auto;
    overflow: visible;
    fill: none;
    stroke: var(--color-text);
    stroke-width: 1.5;
  }

  .mouse-legend-button {
    stroke: none;
    fill: transparent;
    transition: fill 200ms ease;
  }

  .mouse-legend[data-drag] .mouse-legend-button {
    fill: var(--color-accent);
  }

  .mouse-legend-wheel {
    fill: var(--color-text);
    stroke: none;
  }

  .mouse-legend[data-rolling] .mouse-legend-wheel {
    fill: var(--color-accent);
    animation: mouse-wheel 450ms ease-in-out infinite alternate;
  }

  @keyframes mouse-wheel {
    to {
      transform: translateY(3px);
    }
  }

  @media (prefers-reduced-motion: reduce) {
    .mouse-legend[data-rolling] .mouse-legend-wheel {
      animation: none;
    }
  }

  .mouse-legend-label {
    min-width: 9em;
    color: var(--color-text);
  }

  .sim-title,
  .sim-closing {
    font-size: 0.8em;
    font-weight: 700;
    text-align: center;
    color: var(--color-sim-current);
    transition: color 300ms ease;
  }

  .sim-checklist .sim-title {
    margin-bottom: 0.3em;
  }

  .sim-checklist .sim-closing {
    margin-top: 0.3em;
    color: var(--color-ok);
    opacity: 0;
    transition: opacity 300ms ease;
  }

  .sim-checklist[data-complete] .sim-title {
    color: var(--color-ok);
  }

  .sim-checklist[data-complete] .sim-closing {
    opacity: 1;
  }

  .sim-row {
    position: relative;
    display: flex;
    padding: 0 0.45em;
    margin: 0 -0.45em;
    transition: color 300ms ease;
  }

  .sim-mark {
    flex: none;
    width: 1.111em;
    margin-right: 0.222em;
    text-align: center;
  }

  .sim-leader {
    flex: 1;
    overflow: hidden;
    margin: 0 0.6em; /* a margin, not a padding: the dots would run on into a padding */
    color: var(--color-sim-rule);
    font-weight: 400;
  }

  .sim-value {
    color: var(--color-sim-value);
  }

  /* Current: bold, the arrow, a bar on its left edge and a faint band fading right, in the amber mark. */
  .sim-row[data-state='current'] {
    font-weight: 700;
    background: linear-gradient(
      to right,
      color-mix(in srgb, var(--color-sim-current) 8%, transparent) 45%,
      transparent
    );
  }

  .sim-row[data-state='current']::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 3px;
    background: var(--color-sim-current);
    box-shadow: 0 0 0 1px rgb(0 0 0 / 0.35);
  }

  .sim-row[data-state='current'] .sim-mark {
    color: var(--color-sim-current);
  }

  .sim-row[data-state='current'] .sim-mark::before {
    content: '\25B6';
  }

  /* Done: the tick, and the row green to its value. */
  .sim-row[data-state='done'],
  .sim-row[data-state='done'] .sim-value {
    color: var(--color-ok);
  }

  .sim-row[data-state='done'] .sim-mark::before {
    content: '\2713';
  }

  /* Header: the publisher's frame at the top of every page (components/Header.astro). The brand on the left, the
     links, then the account and the small button; on a phone the links wait for a menu. A full-width bar (the
     pilot, #37: "A"), clear over the page's top; once scrolled, a dark glass with a hairline under it. */
  .site-header {
    position: sticky;
    top: 0;
    z-index: 50;
    display: flex;
    align-items: center;
    gap: 32px;
    padding: 14px 24px;
    border-bottom: 1px solid transparent;
    transition:
      background 240ms ease,
      border-color 240ms ease,
      padding 240ms ease,
      box-shadow 240ms ease;
  }

  .site-header.is-scrolled {
    background: rgb(12 13 15 / 0.72);
    border-bottom-color: var(--line);
    backdrop-filter: blur(14px) saturate(1.2);
  }

  .site-header-brand {
    display: flex;
    align-items: center;
    gap: 10px;
    font-family: var(--font-display);
    font-size: 1.6rem;
    font-weight: 600;
    color: var(--color-text);
    text-decoration: none;
    white-space: nowrap;
  }

  /* Word mark: Ten13Sim, the 13 from the logo in the accent lit from above, one look everywhere
     (components/Wordmark.astro; the pilot, #38). It takes the size of the text around it: the 13 stands on the
     baseline, as tall as the capitals. */
  .wordmark {
    display: inline-flex;
    align-items: baseline;
    white-space: nowrap;
  }

  .wordmark-13 {
    height: 0.74em;
    width: auto;
    margin: 0 0.1em 0 0.02em;
  }

  .wordmark-light-top {
    stop-color: var(--accent-lit-top);
  }

  .wordmark-light-bottom {
    stop-color: var(--accent-lit-bottom);
  }


  .site-header-nav {
    display: flex;
    gap: 28px;
    margin-left: auto;
  }

  /* The frame's links (header, footer): the text's colour, a little quieter until pointed at. */
  .site-header-nav a,
  .site-header-link,
  .site-footer-links a {
    color: var(--color-text);
    text-decoration: none;
    opacity: 0.8;
    transition: opacity 160ms ease;
  }

  .site-header-nav a:hover,
  .site-header-link:hover,
  .site-footer-links a:hover {
    opacity: 1;
  }

  .site-header-link {
    font-size: 0.9rem;
  }

  /* The header's menu in the eyebrow's spaced capitals, the site's own label (the pilot: "ezeket a menu pontokat
     menobbre kellene csinalni"). Pointed at, it only comes up to full; the page the visitor is on stands in the
     accent. A lit line under them was too much, under the pointer and under the page alike (the pilot: "a mouse
     hover nem tetszik rajta tulzas", "szerintem az alahuzas is az"). */
  .site-header-nav a {
    padding: 8px 0;
    font-size: 0.75rem;
    font-weight: 500;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    margin-right: -0.22em; /* the spacing after the last letter, so the word stands on its middle */
    transition:
      opacity 160ms ease,
      color 160ms ease;
  }

  /* The menu's own items only, not the links in the PRODUCTS panel: those mark the page their own way (.product-card). */
  .site-header-nav > a[aria-current='page'],
  .site-header-products > a[aria-current='page'] {
    opacity: 1;
    color: var(--accent-lit-top);
  }

  /* PRODUCTS and its panel (components/Header.astro): pointed at, or reached by the keyboard, a raised panel opens
     under it with a row a product: its name, its line, its own pages. A strip of air under PRODUCTS keeps it open on
     the pointer's way down. */
  .site-header-nav {
    align-items: center;
  }

  /* A flex box, so PRODUCTS stands on the same line as the links beside it, not on a text line of its own (the pilot:
     "el vannak csuszva egymastol"). */
  .site-header-products {
    position: relative;
    display: flex;
    align-items: center;
  }

  .site-header-products::after {
    content: '';
    position: absolute;
    top: 100%;
    left: -24px;
    right: -24px;
    height: 16px;
  }

  .site-header-panel {
    position: absolute;
    top: calc(100% + 14px);
    left: 50%;
    z-index: 10;
    display: grid;
    gap: 4px;
    width: max-content;
    min-width: 340px;
    padding: 10px;
    background: var(--color-bg);
    border: 1px solid var(--line-soft);
    border-radius: var(--radius);
    box-shadow: 0 24px 48px -12px rgb(0 0 0 / 0.6);
    opacity: 0;
    visibility: hidden;
    transform: translate(-50%, -4px);
    transition:
      opacity 160ms ease,
      transform 160ms ease,
      visibility 0s linear 160ms;
  }

  .site-header-products:hover .site-header-panel,
  .site-header-products:focus-within .site-header-panel {
    opacity: 1;
    visibility: visible;
    transform: translate(-50%, 0);
    transition:
      opacity 160ms ease,
      transform 160ms ease;
  }

  /* In the panel, the links are the card's own, not the menu's capitals. */
  .site-header-panel a {
    padding: 0;
    margin: 0;
    font-size: inherit;
    font-weight: inherit;
    letter-spacing: 0;
    text-transform: none;
    opacity: 1;
  }

  @media (prefers-reduced-motion: reduce) {
    .site-header-panel {
      transition: none;
    }
  }

  /* Product card: a product in the frame's menus (components/ProductCard.astro), the header's PRODUCTS panel and
     the phone's menu alike. Its logo (the app's own, copied as it is: assets/osd-checklist-logo.svg),
     its name and its line; the whole card leads to its page (the pilot, #46: "a mouse hover csak a feliratokon
     mukodik"), lighting up a little under the pointer, an arrow coming in at its right; its own pages as small dark
     chips, each its own link over the card. Dark as the app's own rows (its aircraft list), a faint light on the top
     edge, the orange only in the logo and where the visitor is (the pilot: "ez a narancs nem annyira jon itt be.
     valami sotetebbet kepzelek el"). */
  .product-card {
    position: relative;
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    gap: 14px 16px;
    padding: 16px;
    background: linear-gradient(180deg, rgb(255 255 255 / 0.035), rgb(255 255 255 / 0.012)), var(--color-bg);
    border: 1px solid var(--line-faint);
    border-radius: var(--radius-lg);
    box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.06);
    transition:
      background 160ms ease,
      border-color 160ms ease;
  }

  .product-card:hover,
  .product-card:focus-within {
    background: linear-gradient(180deg, rgb(255 255 255 / 0.06), rgb(255 255 255 / 0.025)), var(--color-bg);
    border-color: var(--line-soft);
  }

  .product-logo {
    display: block;
    width: 46px;
    height: auto;
  }

  .product-card-main {
    display: grid;
    gap: 2px;
    color: var(--color-text);
    text-decoration: none;
    outline: none;
  }

  /* The card's link covers the whole card; the chips stand over it. */
  .product-card-main::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
  }

  .product-card-main:focus-visible::after {
    outline: var(--focus);
    outline-offset: 2px;
  }

  /* The name as the home page's Products heading writes it (the pilot, #46: "nekem pont ez tetszik jobban"): the
     display font, the first word white, the rest lit from above in the accent, as a big title's .accent. */
  .product-card-name {
    font-family: var(--font-display);
    font-size: 1.3rem;
    font-weight: 600;
    line-height: 1.2;
  }

  .product-card-accent {
    background: var(--gradient-accent);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
  }

  .product-card-line {
    font-size: 0.85rem;
    color: var(--color-muted);
  }

  .product-card-arrow {
    width: 20px;
    height: 20px;
    fill: none;
    stroke: var(--color-muted);
    stroke-width: 1.8;
    stroke-linecap: round;
    stroke-linejoin: round;
    opacity: 0;
    transform: translateX(-6px);
    transition:
      opacity 160ms ease,
      transform 160ms ease;
  }

  .product-card:hover .product-card-arrow,
  .product-card:focus-within .product-card-arrow {
    opacity: 1;
    transform: none;
  }

  .product-card-links {
    position: relative;
    z-index: 1;
    grid-column: 1 / -1;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
  }

  .product-card-links a {
    padding: 7px 14px;
    font-size: 0.85rem;
    color: var(--color-muted);
    text-decoration: none;
    background: rgb(255 255 255 / 0.03);
    border: 1px solid var(--line-faint);
    border-radius: var(--radius-sm);
    transition:
      color 160ms ease,
      border-color 160ms ease;
  }

  .product-card-links a:hover {
    color: var(--color-text);
    border-color: var(--line-soft);
  }

  .product-card-links a[aria-current='page'] {
    color: var(--accent-lit-top);
  }

  .product-card-links a:focus-visible {
    outline: var(--focus);
    outline-offset: 2px;
  }

  @media (prefers-reduced-motion: reduce) {
    .product-card,
    .product-card-arrow {
      transition: none;
    }
  }


  .site-header-actions {
    display: flex;
    align-items: center;
    gap: 20px;
  }

  /* The header's and the phone menu's own bare icon buttons (menu, close). */
  .site-header-menu,
  .site-menu-close {
    padding: 6px;
    color: var(--color-text);
    background: none;
    border: 0;
    cursor: pointer;
  }

  .site-header-menu {
    display: none;
  }

  @media (max-width: 760px) {
    .site-header {
      gap: 16px;
      padding: 12px 16px;
    }

    .site-header-nav,
    .site-header-link {
      display: none;
    }

    .site-header-actions {
      gap: 8px;
      margin-left: auto;
    }

    .site-header-menu {
      display: inline-flex;
    }
  }

  /* The phone's menu (components/Header.astro): over the whole screen in the page's own dark, a faint warm light from
     its top corner (the pilot, #46: "mobilon ez a szurke menu nagyon fapados. valami szebbet alkoss"). At its top the
     word mark and the close, where the header's stand; the products as cards; the publisher's links large in the
     display type, the page the visitor is on in the accent; the trial at the bottom. It fades in, its parts rising
     one after the other; with reduced motion it is simply there. */
  .site-menu {
    width: 100vw;
    max-width: none;
    height: 100dvh;
    max-height: none;
    margin: 0;
    padding: 12px 16px 28px;
    color: var(--color-text);
    background:
      radial-gradient(ellipse 90% 45% at 100% 0%, color-mix(in srgb, var(--accent-lit-bottom) 12%, transparent), transparent 70%),
      var(--color-bg);
    border: 0;
    outline: none; /* it opens with the focus on itself, not on the word mark, so no ring shows until the keyboard moves */
    animation: kit-menu-in 240ms ease;
  }

  .site-menu[open] {
    display: flex;
    flex-direction: column;
    gap: 32px;
  }

  .site-menu::backdrop {
    background: var(--color-bg);
  }

  .site-menu-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
  }

  .site-menu-links {
    display: grid;
    gap: 14px;
    padding: 0 4px;
  }

  .site-menu-links > * {
    animation: kit-menu-rise 420ms cubic-bezier(0.2, 0.7, 0.2, 1) both;
  }

  .site-menu-links > :nth-child(2) { animation-delay: 60ms; }
  .site-menu-links > :nth-child(3) { animation-delay: 120ms; }
  .site-menu-links > :nth-child(4) { animation-delay: 180ms; }
  .site-menu-links > :nth-child(5) { animation-delay: 240ms; }

  .site-menu-links a {
    color: var(--color-text);
    text-decoration: none;
  }

  .site-menu-links .site-menu-group {
    margin-bottom: -4px;
  }

  /* The publisher's own links, large, a hairline between them. */
  .site-menu-links .site-menu-link {
    padding: 14px 0;
    font-family: var(--font-display);
    font-size: 1.6rem;
    font-weight: 600;
    border-bottom: 1px solid var(--line-faint);
  }

  .site-menu-links .site-menu-link[aria-current='page'] {
    color: var(--accent-lit-top);
  }

  /* At the bottom the trial, and the publisher's line, quiet. */
  .site-menu-foot {
    display: grid;
    gap: 18px;
    margin-top: auto;
    padding: 0 4px;
  }

  .site-menu-tagline {
    margin: 0;
    font-family: var(--font-display);
    font-size: 0.95rem;
    color: var(--color-muted);
  }

  @keyframes kit-menu-in {
    from {
      opacity: 0;
    }
  }

  @keyframes kit-menu-rise {
    from {
      opacity: 0;
      transform: translateY(14px);
    }
  }

  @media (prefers-reduced-motion: reduce) {
    .site-menu,
    .site-menu-links > * {
      animation: none;
    }
  }

  /* The frame (#38, layouts/Base.astro `frame`): the header on top, the page, and the footer at the bottom even
     when the page is short. */
  .has-frame {
    display: flex;
    flex-direction: column;
    min-height: 100dvh;
  }

  .has-frame > main {
    flex: 1;
  }

  /* Footer: the publisher's frame at the bottom of every page (components/Footer.astro), in columns (the pilot,
     #37: "a"): the brand on the left, the link groups beside it, the small print across the bottom. */
  .site-footer {
    display: grid;
    grid-template-columns: minmax(0, 1.2fr) minmax(0, 2fr);
    gap: 48px 32px;
    max-width: 1400px;
    margin: 0 auto;
    padding: 64px 24px 32px;
    font-size: 0.9rem;
    color: var(--color-muted);
    border-top: 1px solid var(--line);
  }

  .site-footer p {
    margin: 0;
  }

  .site-footer-brand {
    display: grid;
    align-content: start; /* the motto right under the name, not pushed down to the links' bottom */
    gap: 12px;
  }

  .site-footer-name {
    font-family: var(--font-display);
    font-size: 1.8rem;
    font-weight: 600;
    color: var(--color-text);
  }

  /* The publisher's line under its name, quiet. */
  .site-footer-motto {
    font-family: var(--font-display);
    font-size: 0.95rem;
    color: var(--color-muted);
    text-wrap: balance;
  }

  /* The link groups at the right, as many columns as there are groups, each as wide as its words, so no empty
     column is left standing. */
  .site-footer-links {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 32px 72px;
  }

  .site-footer-group {
    display: grid;
    gap: 12px;
    align-content: start;
  }

  .site-footer-group .overline {
    margin-bottom: 4px;
  }

  .site-footer-small {
    grid-column: 1 / -1;
    padding-top: 24px;
    font-size: 0.78rem;
    line-height: 1.6;
    border-top: 1px solid var(--line-faint);
  }

  @media (max-width: 760px) {
    .site-footer {
      grid-template-columns: 1fr;
    }

    .site-footer-links {
      justify-content: flex-start;
      gap: 32px 56px;
    }
  }

  /* Field: a label over its control, then a help or an error line. .input is every text control (input, select,
     textarea): a line under the text, as the app's field while typed in, turning to the accent (the pilot, #37:
     "a"). */
  .field {
    display: grid;
    gap: 8px;
    margin: 0;
    padding: 0;
    border: 0;
    min-width: 0;
  }

  .field-label {
    padding: 0;
    font-size: 0.85rem;
    font-weight: 500;
    color: var(--color-text);
  }

  .field-optional {
    margin-left: 6px;
    font-weight: 400;
    color: var(--color-muted);
  }

  .field-help,
  .field-error {
    font-size: 0.8rem;
    color: var(--color-muted);
  }

  .field-error {
    color: var(--color-error);
  }

  .input {
    width: 100%;
    padding: 12px 14px;
    font: inherit;
    font-size: 1rem;
    padding-inline: 12px;
    color: var(--color-text);
    background: transparent;
    border: 1px solid transparent;
    border-bottom-color: rgb(255 255 255 / 0.35);
    border-radius: 8px 8px 0 0; /* as the sign-in's line (the pilot: "lent is legyenek kereket a felso sarkok") */
    outline: none;
    /* Solid, so the backdrop's dots do not show through (the pilot: "az input alig latszik", then "zavaro, hogy
       latszik a potty alatta"). */
    background-color: color-mix(in srgb, var(--color-bg), white 2.5%);
    transition:
      border-color 160ms ease,
      background 160ms ease,
      box-shadow 160ms ease;
  }

  .input:hover {
    border-bottom-color: rgb(255 255 255 / 0.55);
  }

  .input:focus {
    border-bottom-color: var(--color-accent);
    box-shadow: inset 0 -1px 0 var(--color-accent);
  }

  .is-invalid .input {
    border-bottom-color: var(--color-error);
  }

  .input::placeholder {
    color: color-mix(in srgb, var(--color-muted) 70%, transparent);
  }

  textarea.input {
    resize: vertical;
    line-height: 1.5;
  }

  select.input {
    appearance: none;
    padding-right: 40px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5l5 5 5-5' fill='none' stroke='%23a39f97' stroke-width='1.5'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 14px center;
  }

  select.input option {
    color: var(--color-text);
    background: var(--color-app-surface);
  }

  /* The open list drawn by the page, not the system (the pilot, #37: "ez igy nagyon nem jo", about the system's
     blue list): a dark surface with the app's line, a quiet light under the pointer, the chosen one in the accent.
     Browsers that cannot draw it yet keep the system's list, dark. */
  @supports (appearance: base-select) {
    select.input,
    select.input::picker(select) {
      appearance: base-select;
    }

    select.input::picker-icon {
      display: none;
    }

    select.input::picker(select) {
      margin-top: 6px;
      padding: 6px;
      background: var(--color-raised);
      border: 1px solid var(--color-app-line);
      border-radius: var(--radius);
      box-shadow: 0 18px 40px -12px rgb(0 0 0 / 0.9);
    }

    select.input option {
      padding: 9px 12px;
      font-size: 0.95rem;
      background: transparent;
      border-radius: var(--radius-sm);
      cursor: pointer;
    }

    select.input option:hover,
    select.input option:focus-visible {
      background: rgb(255 255 255 / 0.06);
      outline: none;
    }

    select.input option:checked {
      color: var(--color-accent);
    }

    select.input option::checkmark {
      display: none;
    }
  }

  /* Check: a checkbox or a radio with its words; the mark in the accent. */
  .check {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    font-size: 0.95rem;
    cursor: pointer;
  }

  .check input {
    appearance: none;
    flex: none;
    width: 18px;
    height: 18px;
    margin: 2px 0 0;
    background: transparent;
    border: 1px solid color-mix(in srgb, var(--color-text) 35%, transparent);
    border-radius: 4px;
    cursor: pointer;
    transition:
      background 160ms ease,
      border-color 160ms ease;
  }

  .check input[type='radio'] {
    border-radius: 50%;
  }

  .check input:checked {
    background: var(--color-accent);
    border-color: var(--color-accent);
  }

  .check input[type='checkbox']:checked {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='10' viewBox='0 0 12 10'%3E%3Cpath d='M1 5l3.5 3.5L11 1.5' fill='none' stroke='%230c0d0f' stroke-width='2'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: center;
  }

  .check input[type='radio']:checked {
    box-shadow: inset 0 0 0 4px var(--color-bg);
  }

  /* Switch: an on/off with its words; on, the track takes the accent. */
  .switch {
    display: flex;
    align-items: center;
    gap: 12px;
    font-size: 0.95rem;
    cursor: pointer;
  }

  .switch input {
    appearance: none;
    position: relative;
    flex: none;
    width: 38px;
    height: 22px;
    margin: 0;
    background: rgb(255 255 255 / 0.12);
    border-radius: 999px;
    cursor: pointer;
    transition: background 200ms ease;
  }

  .switch input::after {
    content: '';
    position: absolute;
    top: 3px;
    left: 3px;
    width: 16px;
    height: 16px;
    background: var(--color-text);
    border-radius: 50%;
    transition: transform 200ms ease;
  }

  .switch input:checked {
    background: var(--color-accent);
  }

  .switch input:checked::after {
    background: var(--color-bg);
    transform: translateX(16px);
  }

  .check input:focus-visible,
  .switch input:focus-visible {
    outline: var(--focus);
    outline-offset: 3px;
  }

  /* Badge: a licence's kind; Status: a state with a dot (ok green, off grey). */
  .badge {
    display: inline-block;
    padding: 2px 10px;
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    border: 1px solid color-mix(in srgb, var(--color-text) 25%, transparent);
    border-radius: 999px;
  }

  .badge[data-kind='purchased'] {
    color: var(--color-accent);
    border-color: color-mix(in srgb, var(--color-accent) 50%, transparent);
  }

  .status {
    display: inline-flex;
    align-items: center;
    gap: 8px;
  }

  .status::before {
    content: '';
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--color-muted);
  }

  .status[data-state='ok']::before {
    background: var(--color-ok);
  }

  /* Table: rows of records (licences, machines) on hairlines (the pilot, #37: "a"); wide ones scroll inside their
     wrap on a phone. */
  .table-wrap {
    overflow-x: auto;
  }

  .table {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    font-size: 0.95rem;
    white-space: nowrap;
  }

  .table th {
    padding: 10px 16px;
    text-align: left;
    border-bottom: 1px solid var(--line-firm);
  }

  .table td {
    padding: 14px 16px;
    border-bottom: 1px solid var(--line-faint);
  }

  .table tbody tr:hover td {
    background: rgb(255 255 255 / 0.02);
  }

  .table-mono {
    font-family: var(--font-mono);
    font-size: 0.88rem;
  }

  .table-action {
    text-align: right;
  }

  .table-action a {
    text-decoration: none;
  }

  /* Danger: a button that destroys something (remove a machine, delete the account): a quiet red, no glow (the
     pilot, #37, about the first, loud one: "ez nagyon otromba"). */
  .button-danger {
    color: #ff9a90;
    background: rgb(224 96 90 / 0.12);
    border-color: rgb(255 138 128 / 0.35);
    box-shadow: none;
  }

  .button-danger:hover {
    background: rgb(224 96 90 / 0.2);
    box-shadow: none;
  }

  /* Quiet: the way out beside a choice (Cancel): words only, no frame. */
  .button-quiet {
    color: var(--color-muted);
    background: none;
    border-color: transparent;
    box-shadow: none;
  }

  .button-quiet:hover {
    color: var(--color-text);
    box-shadow: none;
  }

  /* Busy: the button's words give way to a turning ring while it works. */
  .button.is-busy {
    position: relative;
    color: transparent;
    pointer-events: none;
  }

  .button.is-busy::after {
    content: '';
    position: absolute;
    inset: 0;
    width: 18px;
    height: 18px;
    margin: auto;
    border: 2px solid currentColor;
    border-color: var(--color-on-accent) var(--color-on-accent) transparent;
    border-radius: 50%;
    animation: kit-turn 800ms linear infinite;
  }

  .button-secondary.is-busy::after {
    border-color: var(--color-text) var(--color-text) transparent;
  }

  @keyframes kit-turn {
    to {
      transform: rotate(1turn);
    }
  }

  /* An outside link carries a small arrow, so the reader knows it leaves the site. */
  .external::after {
    content: 'â†—';
    margin-left: 0.25em;
    font-size: 0.85em;
  }

  /* Notice: a message in the page (sent, about to end, gone wrong), a coloured line on its left. */
  .notice {
    display: grid;
    gap: 4px;
    padding: 14px 18px;
    background: rgb(255 255 255 / 0.03);
    border-left: 2px solid var(--notice, var(--color-muted));
    border-radius: 0 8px 8px 0;
  }

  .notice-title {
    margin: 0;
    font-weight: 600;
    color: var(--color-text);
  }

  .notice p {
    margin: 0;
    font-size: 0.92rem;
    color: var(--color-muted);
  }

  .notice[data-tone='ok'] {
    --notice: var(--color-ok);
  }

  .notice[data-tone='warn'] {
    --notice: var(--color-accent);
  }

  .notice[data-tone='error'] {
    --notice: var(--color-error);
  }

  /* Toast: a short word after an action, at the bottom right, gone after a few seconds (scripts/toast.ts). */
  .toast-stack {
    position: fixed;
    right: 20px;
    bottom: 20px;
    z-index: 80;
    display: grid;
    gap: 10px;
    max-width: min(380px, calc(100vw - 40px));
  }

  .toast {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 12px 16px;
    font-size: 0.92rem;
    background: rgb(20 22 25 / 0.92);
    border: 1px solid var(--line-soft);
    border-radius: var(--radius);
    box-shadow: 0 18px 40px -14px rgb(0 0 0 / 0.9);
    backdrop-filter: blur(10px);
    animation: kit-toast-in 240ms ease;
  }

  .toast a,
  .toast button {
    margin-left: auto;
    font: inherit;
    font-weight: 600;
    color: var(--color-accent);
    background: none;
    border: 0;
    cursor: pointer;
  }

  @keyframes kit-toast-in {
    from {
      opacity: 0;
      transform: translateY(8px);
    }
  }

  /* Dialog: a question that waits for an answer (remove this machine?), over a dimmed page. */
  .dialog {
    width: min(420px, calc(100vw - 32px));
    padding: 32px 32px 24px;
    color: var(--color-text);
    /* A glass lit from above (the pilot: "uveges"), as the app's raised glass: the page shows through it, blurred. */
    background:
      linear-gradient(180deg, rgb(255 255 255 / 0.07), transparent 45%),
      rgb(18 20 23 / 0.62);
    border: 1px solid var(--line-soft);
    border-radius: 14px;
    box-shadow:
      inset 0 1px 0 rgb(255 255 255 / 0.14),
      0 30px 80px -20px rgb(0 0 0 / 0.9);
    backdrop-filter: blur(24px) saturate(1.2);
  }

  .dialog::backdrop {
    background: rgb(5 5 6 / 0.45);
  }

  /* The dialog opens with the focus on its title, so no ring shows until the keyboard moves. */
  .dialog-title {
    margin: 0 0 12px;
    font-family: var(--font-display);
    font-size: 1.25rem;
    font-weight: 600;
    outline: none;
  }

  .dialog p:not(.dialog-title) {
    margin: 0;
    font-size: 0.95rem;
    line-height: 1.55;
    color: var(--color-muted);
  }

  .dialog-actions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    margin-top: 28px;
  }

  /* Tabs: the parts of one place (the account), the current one underlined in the accent. */
  .tabs {
    display: flex;
    gap: 28px;
    overflow-x: auto;
    scrollbar-width: none;
    border-bottom: 1px solid var(--line-soft);
  }

  .tabs a {
    padding: 12px 0;
    font-size: 0.95rem;
    color: var(--color-muted);
    text-decoration: none;
    white-space: nowrap;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
  }

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

  .tabs a[aria-current='page'] {
    color: var(--color-text);
    border-bottom-color: var(--color-accent);
  }

  /* Side menu: the chapters of the docs or the account, in groups; the current one marked in the accent. */
  .side-nav {
    display: grid;
    gap: 22px;
    font-size: 0.92rem;
  }

  .side-nav-group {
    display: grid;
    gap: 2px;
  }

  .side-nav a {
    padding: 6px 12px;
    color: var(--color-muted);
    text-decoration: none;
    border-left: 2px solid var(--line);
  }

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

  .side-nav a[aria-current='page'] {
    color: var(--color-text);
    border-left-color: var(--color-accent);
  }

  /* The docs' chapters around the side menu (components/DocsMenu.astro): on a desktop the menu alone; on a phone folded
     under one line, the chapter shown beside it, so the page's text comes first (#41). */
  .docs-chapters > summary {
    display: none;
  }

  @media (max-width: 760px) {
    .docs-chapters {
      padding: 12px 16px;
      border: 1px solid var(--line-firm);
      border-radius: var(--radius);
    }

    .docs-chapters > summary {
      display: list-item;
      cursor: pointer;
    }

    .docs-chapters > summary::marker {
      color: var(--color-accent);
    }

    .docs-chapters > summary span {
      color: var(--color-muted);
    }

    .docs-chapters[open] > summary {
      margin-bottom: 16px;
    }
  }

  /* A version's date beside it in the changelog's list of versions (#42). */
  .toc small {
    margin-left: 6px;
    color: var(--color-muted);
  }

  /* Key: a licence key to read and copy; the button says Copied for a moment (scripts/copy.ts). */
  .key {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 14px 16px 14px 20px;
    background: rgb(255 255 255 / 0.03);
    border: 1px solid var(--line-soft);
    border-radius: var(--radius);
  }

  .key code {
    font-family: var(--font-mono);
    font-size: 1.15rem;
    letter-spacing: 0.08em;
    color: var(--color-text);
    overflow-wrap: anywhere;
  }

  /* Its Copy: only a quiet icon, no frame (the pilot: "a copy gomb valami visszafogottabb", then "ikon"); a tick
     for a moment once copied. */
  .key-copy {
    display: inline-flex;
    align-items: center;
    margin-left: auto;
    padding: 8px;
    color: var(--color-muted);
    background: none;
    border: 0;
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: color 160ms ease;
  }

  .key-copy:hover {
    color: var(--color-text);
  }

  .key-copy-done,
  .key-copy.is-copied .key-copy-icon {
    display: none;
  }

  .key-copy.is-copied .key-copy-done {
    display: block;
    color: var(--color-ok);
  }

  .key-copy:focus-visible {
    outline: var(--focus);
    outline-offset: 2px;
  }

  /* Panel: a faint framed sheet that holds one thing (a licence, a topic, a page before or after). */
  .panel {
    background: var(--wash);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
  }

  /* Licence: one licence in the account: its product and kind, its state, the machine it is active on, the moves
     left, and what to do next (.scratch/web/specs/020-licencfolyamat.html: active on one machine at a time). */
  .licence {
    display: grid;
    gap: 16px;
    padding: 22px 24px;
  }

  .licence-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px 14px;
  }

  .licence-name {
    margin: 0;
    font-family: var(--font-display);
    font-size: 1.15rem;
    font-weight: 600;
  }

  .licence-head .status {
    margin-left: auto;
    font-size: 0.9rem;
  }

  .licence-key {
    font-family: var(--font-mono);
    font-size: 0.85rem;
    letter-spacing: 0.06em;
    color: var(--color-muted);
  }

  .licence-machine {
    margin: 0;
    color: var(--color-text);
  }

  .licence-machine small {
    margin-left: 8px;
    font-size: 0.85rem;
    color: var(--color-muted);
  }

  .licence p {
    margin: 0;
  }

  .licence-foot {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px 20px;
    padding-top: 14px;
    border-top: 1px solid var(--line-faint);
  }

  .licence-foot .button {
    margin-left: auto;
  }

  .status[data-state='warn']::before {
    background: var(--color-accent);
  }

  .status[data-state='error']::before {
    background: var(--color-error);
  }

  /* Moves: the self-service moves left in 30 days, a dot each, used ones hollow. */
  .moves {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    font-size: 0.85rem;
    color: var(--color-muted);
  }

  .moves-dots {
    display: inline-flex;
    gap: 5px;
  }

  .moves-dots i {
    width: 8px;
    height: 8px;
    border: 1px solid var(--color-text);
    border-radius: 50%;
  }

  .moves-dots i.is-left {
    background: var(--color-text);
  }

  .moves[data-none] .moves-dots i {
    border-color: var(--color-accent);
  }

  /* A dialog's list of what will happen. */
  .dialog-list {
    display: grid;
    gap: 8px;
    margin: 14px 0 0;
    padding-left: 18px;
    font-size: 0.92rem;
    color: var(--color-muted);
  }

  .dialog .notice {
    margin-top: 16px;
  }

  /* Prose: the docs' running text (docs/user of the product): headings, paragraphs, lists, links, code and keys,
     tables and pictures, at a reading width. */
  .prose {
    max-width: 46rem;
    font-size: 1.0625rem;
    line-height: 1.7;
    color: color-mix(in srgb, var(--color-text) 88%, transparent);
  }

  .prose > * + * {
    margin-top: 1.1em;
  }

  .prose h1,
  .prose h2,
  .prose h3 {
    font-family: var(--font-display);
    font-weight: 600;
    line-height: 1.2;
    color: var(--color-text);
    scroll-margin-top: 88px;
  }

  .prose h1 {
    margin: 0;
    font-size: clamp(2rem, 4vw, 2.8rem);
    letter-spacing: -0.01em;
  }

  .prose h2 {
    margin-top: 2.4em;
    padding-top: 1.2em;
    font-size: 1.6rem;
    border-top: 1px solid var(--line);
  }

  .prose h3 {
    margin-top: 1.8em;
    font-size: 1.2rem;
  }

  .prose p,
  .prose ul,
  .prose ol {
    margin-bottom: 0;
  }

  .prose ul,
  .prose ol {
    padding-left: 1.3em;
  }

  .prose li + li {
    margin-top: 0.45em;
  }

  .prose li::marker {
    color: var(--color-accent);
  }

  .prose strong {
    font-weight: 600;
    color: var(--color-text);
  }

  .prose a {
    text-decoration-color: color-mix(in srgb, var(--color-accent) 45%, transparent);
    text-underline-offset: 3px;
  }

  .prose a:hover {
    text-decoration-color: var(--color-accent);
  }

  /* Code: a word as the app or the panel writes it. */
  .prose code {
    padding: 0.1em 0.4em;
    font-family: var(--font-mono);
    font-size: 0.88em;
    color: var(--color-text);
    background: rgb(255 255 255 / 0.06);
    border-radius: 5px;
  }

  /* Key: a key on the keyboard, as a little keycap. */
  kbd {
    display: inline-block;
    min-width: 1.6em;
    padding: 0.05em 0.45em;
    font-family: var(--font-body);
    font-size: 0.82em;
    font-weight: 500;
    line-height: 1.5;
    text-align: center;
    color: var(--color-text);
    background: linear-gradient(180deg, rgb(255 255 255 / 0.08), rgb(255 255 255 / 0.03));
    border: 1px solid var(--line-firm);
    border-bottom-width: 2px;
    border-radius: 5px;
  }

  .prose .table {
    font-size: 0.95rem;
    white-space: normal;
  }

  .prose .table td {
    vertical-align: top;
  }

  /* Figure: a picture of the app with its caption. */
  .prose figure {
    margin-inline: 0;
  }

  .prose figure img {
    display: block;
    width: 100%;
    height: auto;
    border: 1px solid var(--color-app-line);
    border-radius: 8px;
  }

  .prose figcaption {
    margin-top: 10px;
    font-size: 0.85rem;
    color: var(--color-muted);
  }

  /* Callout: a tip, a note or a warning set off from the text. */
  .callout {
    display: grid;
    gap: 4px;
    padding: 16px 20px;
    background: rgb(255 255 255 / 0.03);
    border: 1px solid var(--line);
    border-left: 2px solid var(--callout, var(--color-muted));
    border-radius: 0 10px 10px 0;
  }

  .callout .overline {
    color: var(--callout, var(--color-muted));
  }

  .callout p {
    margin: 0;
  }

  .callout[data-tone='tip'] {
    --callout: var(--color-ok);
  }

  .callout[data-tone='warn'] {
    --callout: var(--color-accent);
  }

  /* Crumbs: where this page stands in the docs. */
  .crumbs {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 10px;
    margin: 0;
    padding: 0;
    font-size: 0.85rem;
    list-style: none;
    color: var(--color-muted);
  }

  .crumbs li + li::before {
    content: '/';
    margin-right: 10px;
    color: rgb(255 255 255 / 0.2);
  }

  .crumbs a {
    color: var(--color-muted);
    text-decoration: none;
  }

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

  /* On this page: the page's sections, beside the text on a wide screen. */
  .toc {
    display: grid;
    gap: 2px;
    font-size: 0.85rem;
  }

  .toc a {
    padding: 4px 0;
    color: var(--color-muted);
    text-decoration: none;
  }

  .toc a:hover,
  .toc a[aria-current='true'] {
    color: var(--color-text);
  }

  .toc a.toc-sub {
    padding-left: 14px;
  }

  /* Pager: the page before and after, at the end of a docs page. */
  .pager {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px;
  }

  .pager a {
    display: grid;
    gap: 4px;
    padding: 16px 20px;
    color: var(--color-text);
    text-decoration: none;
    transition: border-color 160ms ease;
  }

  .pager a:hover {
    border-color: rgb(255 255 255 / 0.22);
  }

  .pager-next {
    text-align: right;
  }

  /* Sign in (account.ten13sim.com/login): no card, the form stands on the page itself (the pilot, #37, about a
     card: "gyokeresen valtoztass, mert otromba"). One field on a line with its arrow; the providers as small round
     marks. Its arrangement is under discussion. */
  .signin {
    display: grid;
    gap: 22px;
    width: min(420px, 100%);
  }

  .signin p {
    margin: 0;
  }

  .signin-title {
    font-family: var(--font-display);
    font-size: clamp(2.2rem, 5vw, 3.2rem);
    font-weight: 600;
    line-height: 1.05;
    letter-spacing: -0.01em;
  }

  .signin-small {
    font-size: 0.9rem;
    color: var(--color-muted);
  }

  .signin-links {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 20px;
    font-size: 0.9rem;
  }

  .signin-links a,
  .signin-links button {
    padding: 0;
    font: inherit;
    color: var(--color-muted);
    background: none;
    border: 0;
    text-decoration: underline;
    text-decoration-color: rgb(255 255 255 / 0.2);
    text-underline-offset: 3px;
    cursor: pointer;
  }

  .signin-links a:hover,
  .signin-links button:hover {
    color: var(--color-text);
  }

  /* The field and its arrow on one line. */
  .signin-line {
    display: flex;
    align-items: center;
    gap: 10px;
    border-bottom: 1px solid rgb(255 255 255 / 0.35);
    background: color-mix(in srgb, var(--color-bg), white 4%);
    border-radius: 8px 8px 0 0;
    transition: border-color 160ms ease;
  }

  .signin-line:focus-within {
    border-bottom-color: var(--color-accent);
    box-shadow: inset 0 -1px 0 var(--color-accent);
  }

  .signin-line .input {
    flex: 1;
    padding: 16px 14px;
    font-size: 1.15rem;
    background: none;
    border: 0;
    box-shadow: none;
  }

  /* A round button with only a mark: the arrow, a provider. */
  .icon-button {
    display: inline-grid;
    place-items: center;
    flex: none;
    width: 44px;
    height: 44px;
    padding: 0;
    color: var(--color-text);
    background: var(--glass);
    border: 1px solid var(--line-firm);
    border-radius: 50%;
    cursor: pointer;
    transition:
      border-color 160ms ease,
      box-shadow 160ms ease;
  }

  .icon-button:hover {
    border-color: rgb(255 255 255 / 0.3);
  }

  .icon-button:focus-visible {
    outline: var(--focus);
    outline-offset: 3px;
  }

  .icon-button.is-accent {
    color: var(--color-on-accent);
    background: var(--gradient-accent);
    border-color: color-mix(in srgb, var(--color-accent-soft) 60%, transparent);
    box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.45);
  }

  .signin-line .icon-button {
    margin-right: 6px;
    width: 40px;
    height: 40px;
  }

  .signin-providers {
    display: flex;
    align-items: center;
    gap: 12px;
    font-size: 0.85rem;
    color: var(--color-muted);
  }

  /* Download: the version to install now: the product's mark, its name and version, a quiet line of what it is,
     the button across, and the earlier versions under a hairline; a glass lit from above (the pilot: "szebben"). */
  .download {
    display: grid;
    gap: 20px;
    padding: 24px;
    background:
      linear-gradient(180deg, rgb(255 255 255 / 0.05), transparent 45%),
      rgb(255 255 255 / 0.015);
    border: 1px solid rgb(255 255 255 / 0.09);
    border-radius: 14px;
    box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.08);
  }

  .download-head {
    display: flex;
    align-items: center;
    gap: 16px;
  }

  .download-logo {
    flex: none;
    width: 56px;
    height: auto;
  }

  .download-head > div {
    display: grid;
    gap: 6px;
  }

  .download-name {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 10px;
    margin: 0;
    font-family: var(--font-display);
    font-size: 1.25rem;
    font-weight: 600;
    white-space: nowrap;
  }

  .download-meta {
    margin: 0;
    font-size: 0.85rem;
    color: var(--color-muted);
  }

  .download .button {
    width: 100%;
  }

  .download-more {
    margin: 0;
    padding-top: 16px;
    font-size: 0.85rem;
    color: var(--color-muted);
    border-top: 1px solid var(--line-faint);
  }

  /* Danger zone: what cannot be undone (deleting the account), set apart in a quiet red frame. */
  .danger-zone {
    display: grid;
    gap: 12px;
    padding: 22px 24px;
    border: 1px solid rgb(255 138 128 / 0.25);
    border-radius: var(--radius-lg);
  }

  .danger-zone p {
    margin: 0;
    font-size: 0.95rem;
    color: var(--color-muted);
  }

  .danger-zone .button {
    justify-self: start;
  }

  /* From the app: the page the app opens when it cannot go on (taken, no moves, ended, revoked): what happened in
     one sentence, and the way on. */
  .from-app {
    display: grid;
    gap: 14px;
    align-content: start;
    padding: 26px 26px 24px;
    border-top: 2px solid var(--from-app, var(--color-muted));
    background: rgb(255 255 255 / 0.02);
    border-radius: 0 0 12px 12px;
  }

  .from-app p {
    margin: 0;
  }

  .from-app-title {
    font-family: var(--font-display);
    font-size: 1.35rem;
    font-weight: 600;
    line-height: 1.2;
  }

  .from-app-text {
    font-size: 0.95rem;
    color: var(--color-muted);
  }

  .from-app-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 4px;
  }

  .from-app[data-tone='warn'] {
    --from-app: var(--color-accent);
  }

  .from-app[data-tone='error'] {
    --from-app: var(--color-error);
  }

  /* E-mail: a preview of a letter as it arrives (the real ones are built for mail clients, on the platform). */
  .email {
    max-width: 520px;
    overflow: hidden;
    color: var(--color-text);
    background: var(--color-raised);
    border: 1px solid var(--color-app-line);
    border-radius: var(--radius-lg);
  }

  .email-head {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 18px 28px;
    font-family: var(--font-display);
    font-size: 1.4rem;
    font-weight: 600;
    border-bottom: 1px solid var(--line-faint);
  }

  .email-body {
    display: grid;
    gap: 16px;
    padding: 28px;
  }

  .email-body p {
    margin: 0;
    font-size: 0.95rem;
    line-height: 1.6;
    color: color-mix(in srgb, var(--color-text) 85%, transparent);
  }

  .email-body .email-title {
    font-family: var(--font-display);
    font-size: 1.4rem;
    font-weight: 600;
    color: var(--color-text);
  }

  .email-key {
    padding: 14px 18px;
    font-family: var(--font-mono);
    font-size: 1.1rem;
    letter-spacing: 0.08em;
    text-align: center;
    background: var(--wash-strong);
    border: 1px solid var(--line-soft);
    border-radius: 8px;
  }

  .email-body .button {
    justify-self: start;
  }

  .email-foot {
    padding: 16px 28px 22px;
    font-size: 0.78rem;
    color: var(--color-muted);
    border-top: 1px solid var(--line-faint);
  }

  /* Topic: a card into one chapter of the docs, on the support page. */
  .topic {
    display: grid;
    gap: 6px;
    padding: 20px 22px;
    color: var(--color-text);
    text-decoration: none;
    transition:
      border-color 160ms ease,
      background 160ms ease;
  }

  .topic:hover {
    background: var(--wash-strong);
    border-color: rgb(255 255 255 / 0.2);
  }

  .topic strong {
    font-family: var(--font-display);
    font-size: 1.1rem;
    font-weight: 600;
  }

  .topic span {
    font-size: 0.9rem;
    color: var(--color-muted);
  }

  /* FAQ: a question that opens to its answer; the mark turns as it opens. */
  .faq {
    border-bottom: 1px solid var(--line);
  }

  .faq summary {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 18px 0;
    font-weight: 500;
    list-style: none;
    cursor: pointer;
  }

  .faq summary::-webkit-details-marker {
    display: none;
  }

  .faq summary::after {
    content: '';
    flex: none;
    width: 8px;
    height: 8px;
    margin-left: auto;
    border-right: 1.5px solid var(--color-muted);
    border-bottom: 1.5px solid var(--color-muted);
    transform: rotate(45deg);
    transition: transform 200ms ease;
  }

  .faq[open] summary::after {
    transform: rotate(225deg);
  }

  .faq p {
    margin: 0 0 18px;
    max-width: 44rem;
    color: var(--color-muted);
  }

  /* A ticket's state: open (waiting for us), answered (waiting for you), closed. */
  .badge[data-ticket='open'] {
    color: var(--color-accent);
    border-color: color-mix(in srgb, var(--color-accent) 50%, transparent);
  }

  .badge[data-ticket='answered'] {
    color: var(--color-ok);
    border-color: rgb(127 216 154 / 0.45);
  }

  .badge[data-ticket='closed'] {
    color: var(--color-muted);
  }

  /* Thread: a ticket's messages, the pilot's on the right, support's on the left, each with its time. */
  .thread {
    display: grid;
    gap: 18px;
  }

  .message {
    display: grid;
    gap: 8px;
    max-width: min(560px, 88%);
    padding: 16px 20px;
    background: rgb(255 255 255 / 0.03);
    border: 1px solid var(--line);
    border-radius: 14px 14px 14px 4px;
  }

  .message[data-from='me'] {
    justify-self: end;
    background: color-mix(in srgb, var(--color-accent) 8%, transparent);
    border-color: color-mix(in srgb, var(--color-accent) 22%, transparent);
    border-radius: 14px 14px 4px 14px;
  }

  .message p {
    margin: 0;
    font-size: 0.95rem;
    line-height: 1.6;
  }

  .message-who {
    font-size: 0.78rem;
    color: var(--color-muted);
  }

  /* Chip: an attached file, with its size and a way to take it off. */
  .chips {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
  }

  .chip {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 5px 8px 5px 12px;
    font-size: 0.82rem;
    background: rgb(255 255 255 / 0.05);
    border: 1px solid var(--line-soft);
    border-radius: 999px;
  }

  .chip small {
    color: var(--color-muted);
  }

  .chip button {
    display: inline-grid;
    place-items: center;
    width: 20px;
    height: 20px;
    padding: 0;
    font: inherit;
    line-height: 1;
    color: var(--color-muted);
    background: none;
    border: 0;
    border-radius: 50%;
    cursor: pointer;
  }

  .chip button:hover {
    color: var(--color-text);
    background: rgb(255 255 255 / 0.08);
  }

  /* Dropzone: where files are dropped or chosen, lit when a file is over it. */
  .dropzone {
    position: relative;
    display: grid;
    justify-items: center;
    gap: 6px;
    padding: 22px;
    font-size: 0.9rem;
    text-align: center;
    color: var(--color-muted);
    border: 1px dashed rgb(255 255 255 / 0.18);
    border-radius: var(--radius-lg);
    cursor: pointer;
    transition:
      border-color 160ms ease,
      background 160ms ease;
  }

  .dropzone:hover,
  .dropzone.is-over {
    color: var(--color-text);
    background: rgb(255 255 255 / 0.03);
    border-color: color-mix(in srgb, var(--color-accent) 60%, transparent);
  }

  .dropzone input {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
  }

  .dropzone:focus-within {
    outline: var(--focus);
    outline-offset: 3px;
  }

  /* Release: one version in the changelog (the product's format, pottom/osd-checklist-dev#321): its number and
     date, Latest on the newest, at most one callout, its areas, each line a short sentence with its tag. */
  .release {
    display: grid;
    gap: 20px;
    padding-bottom: 40px;
    border-bottom: 1px solid var(--line);
    scroll-margin-top: 88px;
  }

  .release-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 8px 16px;
  }

  .release-version {
    margin: 0;
    font-family: var(--font-display);
    font-size: 1.8rem;
    font-weight: 600;
  }

  .release-date {
    font-size: 0.9rem;
    color: var(--color-muted);
  }

  .release-area {
    display: grid;
    gap: 10px;
  }

  .changes {
    display: grid;
    gap: 10px;
    margin: 0;
    padding: 0;
    list-style: none;
  }

  .changes li {
    display: grid;
    grid-template-columns: 84px minmax(0, 1fr);
    gap: 14px;
    align-items: baseline;
    font-size: 0.98rem;
    line-height: 1.55;
  }

  /* Tag: what a line is: added, changed, fixed, removed. */
  .tag {
    justify-self: start;
    padding: 1px 8px;
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--tag, var(--color-muted));
    background: color-mix(in srgb, var(--tag, var(--color-muted)) 12%, transparent);
    border-radius: 5px;
  }

  .tag[data-tag='added'] {
    --tag: var(--color-ok);
  }

  .tag[data-tag='changed'] {
    --tag: var(--color-info);
  }

  .tag[data-tag='fixed'] {
    --tag: var(--color-accent);
  }

  .tag[data-tag='removed'] {
    --tag: var(--color-error);
  }

  /* Empty: a place with nothing in it yet, and the way to fill it. */
  .empty {
    display: grid;
    justify-items: center;
    gap: 12px;
    padding: 48px 24px;
    text-align: center;
    border: 1px dashed rgb(255 255 255 / 0.12);
    border-radius: 14px;
  }

  .empty-mark {
    width: 44px;
    height: 44px;
    color: var(--color-muted);
  }

  .empty-title {
    margin: 0;
    font-family: var(--font-display);
    font-size: 1.2rem;
    font-weight: 600;
  }

  .empty p {
    margin: 0;
    max-width: 28rem;
    color: var(--color-muted);
  }

  /* Skeleton: where something is still loading, a faint shape of it, shimmering. */
  .skeleton {
    display: block;
    height: 14px;
    border-radius: var(--radius-sm);
    background: linear-gradient(90deg, rgb(255 255 255 / 0.04), rgb(255 255 255 / 0.09), rgb(255 255 255 / 0.04)) 0 0 /
      200% 100%;
    animation: kit-shimmer 1400ms ease infinite;
  }

  @keyframes kit-shimmer {
    to {
      background-position: -200% 0;
    }
  }

  @media (prefers-reduced-motion: reduce) {
    .skeleton,
    .toast {
      animation: none;
    }
  }

  /* Horizon: a faint warm light behind a run of scenes, as the coming soon page's night sky, far quieter. Each glow
     stays wholly inside the box (its centre plus its radius within 0-100%), so none is cut off at an edge. Not on
     the product page: over the instrument backdrop its edges show (the pilot, #39: "vedd le"). */
  .horizon {
    background:
      radial-gradient(ellipse 45% 14% at 50% 84%, color-mix(in srgb, var(--color-accent) 9%, transparent), transparent),
      radial-gradient(ellipse 30% 12% at 70% 22%, color-mix(in srgb, var(--color-accent) 5%, transparent), transparent),
      radial-gradient(ellipse 30% 12% at 30% 52%, color-mix(in srgb, var(--color-accent) 5%, transparent), transparent);
  }

  /* Rule: the short accent bar under a heading. */
  .rule {
    width: 72px;
    height: 3px;
    margin: 28px 0 0;
    border-radius: 2px;
    background: var(--color-accent);
  }

  /* Lede: the light, large paragraph that opens a page; strong words take the accent. */
  .lede {
    max-width: 40rem;
    margin: 22px 0 0;
    font-family: var(--font-display);
    font-size: clamp(1.05rem, 2.2vw, 1.4rem);
    font-weight: 300;
    color: var(--color-text);
    text-shadow: var(--shadow-text);
  }

  .lede strong {
    font-weight: 600;
    color: var(--color-accent);
  }

  /* Slides: a page that scrolls from section to section, not by the line (the pilot, #46: "ne standard gorgetes
     legyen, hanem kvazi a megfelelo szekciokra ugras legyen"; #39: "az osd checklist pagen is slide szeru scrollozas
     kene"). On the page's main; each section of it a screen high under the header, its content on its middle, the page
     settling on one by its top; the footer last. The snapping counts from under the header (67 px), so at the page's
     top the first section already stands where it settles and nothing moves. A section taller than the screen scrolls
     through before the next settles. The page sets its own gap and padding to none here; on a phone, where a section
     can be taller than the screen, it scrolls as usual. */
  @media (min-width: 761px) {
    html:has(.slides) {
      scroll-snap-type: y mandatory;
      scroll-padding-top: 67px;
    }

    .slides > section {
      min-height: calc(100svh - 67px);
      align-content: center;
      scroll-snap-align: start;
    }

    html:has(.slides) .site-footer {
      scroll-snap-align: end;
    }
  }
}
