/* Aimlink | Hero "Through the sight": a film intro driven by scroll (assets/film/film.js).
   The page opens on the Aimlink ident (the mark as a machined emblem) with no header; the camera pushes through
   its black glass into the hall, the title lands on a silhouetted air-pistol shooter, the camera settles on the
   sight picture and flies the 10 m down the lane into the black aiming mark. There ten shots tear through the
   paper in slow motion. The ten glowing holes become ten pellets that lift out of the paper and float over a quiet
   contour landscape (assets/film/pellets.js, one WebGL canvas), and in the middle the page says what Aimlink is,
   with the two buttons. Then the header arrives.

   Two modes on the same markup:
   - static (default; no JS, reduced motion, Save-Data, no WebGL): poster hero with the title, header at once, then
     the pellet picture (a still of the scene) with the copy and the buttons centred over it.
   - .is-live (film.js): one sticky 100svh stage, all layers stacked, driven by scroll progress. */

@layer sections {
  .film { --film-len: 600svh; --film-floor: 0px; position: relative; isolation: isolate; background: var(--color-night); color: var(--text); }
  .film-stage { position: relative; display: grid; }
  /* under 1024 px the phone bar (nav.css) covers the bottom 88 px */
  @media (max-width: 1023.98px) { .film { --film-floor: calc(88px + env(safe-area-inset-bottom, 0px)); } }

  /* ── Media: poster (LCP), the three scrubbed clips (film, target, and the ident over them) ── */
  .film-screen { grid-area: 1 / 1; position: relative; min-height: 100svh; overflow: clip; background: var(--color-night); }
  .film-poster, .film-poster img, .film-video { position: absolute; inset: 0; width: 100%; height: 100%; }
  .film-poster img, .film-video { object-fit: cover; object-position: var(--film-x, 50%) 50%; }
  .film-video { opacity: 0; pointer-events: none; }
  .film-screen::after {
    /* legibility: a soft floor of night under the copy, and a whisper of vignette */
    content: ""; position: absolute; inset: 0; pointer-events: none;
    background:
      radial-gradient(120% 90% at 50% 45%, transparent 55%, color-mix(in srgb, var(--color-night) 55%, transparent) 100%),
      linear-gradient(180deg, color-mix(in srgb, var(--color-night) 45%, transparent) 0%, transparent 20%, transparent 52%, color-mix(in srgb, var(--color-night) 88%, transparent) 100%);
    opacity: var(--shade, 1);
  }
  .film-ident { display: none; }

  /* ── Opening copy (the page's H1) ── */
  /* .hero-content's grid, gap and padding come from site.css (and nav.css clears the phone bar) */
  .film .hero-content { grid-area: 1 / 1; align-self: end; position: relative; z-index: 2; }
  .film .h1 { max-width: 12ch; }
  .film .film-title { margin: 0; }
  .film .w { display: inline-block; animation: rise var(--duration-reveal) var(--ease-out) both; animation-delay: calc(120ms + var(--i) * var(--motion-stagger)); }
  /* live: the title is set by scroll (film.js), word by word, once the camera is through the lens */
  .film.is-live .w { animation: none; opacity: 0; }

  /* ── After the film: AIMLINK with the mark as the page's heading, what it is in one line, the three apps, centred ── */
  .film-about { display: grid; gap: var(--space-5); justify-items: center; text-align: center; width: min(100%, 44rem); margin-inline: auto; }
  .film-brand {
    display: flex; align-items: center; justify-content: center; gap: 0.14em; margin: 0;
    font: 600 min(calc(0.5rem + 17vw), 11.5rem, 24svh)/0.8 var(--font-display); text-transform: uppercase; letter-spacing: 0.02em; color: var(--color-snow);
  }
  .film-brand-mark { position: relative; display: grid; place-items: center; width: 0.74em; height: 0.74em; flex: none; margin-top: -0.04em; }
  .film-brand-mark svg { display: block; width: 100%; height: 100%; }
  .film-brand-word { display: block; padding-top: 0.06em; }
  .film-tag {
    margin: 0; font: 500 clamp(1.5rem, 0.8rem + 2vw, 2.5rem)/1 var(--font-display); text-transform: uppercase; letter-spacing: 0.03em; color: var(--color-snow);
  }
  .film-tag .hl { display: inline-block; }
  .film-act { display: grid; justify-items: center; gap: var(--space-4); padding-top: var(--space-2); }
  .film-act .lede { color: var(--color-snow-2); max-width: 34ch; text-wrap: balance; }
  .film-apps { list-style: none; margin: var(--space-5) 0 0; padding: 0; display: flex; flex-wrap: wrap; justify-content: center; gap: var(--space-3); }
  .film-app {
    --accent: var(--color-lime);
    display: inline-flex; align-items: center; gap: 0.6rem; min-height: 52px; padding: 6px 20px 6px 7px; border-radius: var(--radius-pill);
    background: color-mix(in srgb, var(--color-snow) 8%, transparent);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--color-snow) 18%, transparent);
    -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
    color: var(--color-snow); font: 500 1.5rem/1 var(--font-display); letter-spacing: 0.04em; text-transform: uppercase;
    transition: background-color var(--duration-hover) var(--ease-hover), box-shadow var(--duration-hover) var(--ease-hover), transform var(--duration-hover) var(--ease-hover);
  }
  .film-app img { display: block; width: 38px; height: 38px; border-radius: 11px; }
  .film-app > span { padding-top: 0.08em; }
  @media (hover: hover) and (pointer: fine) {
    .film-app:hover { transform: translateY(-2px); background: color-mix(in srgb, var(--color-snow) 13%, transparent); box-shadow: inset 0 0 0 1.5px var(--accent), 0 8px 28px -10px color-mix(in srgb, var(--accent) 60%, transparent); }
  }
  .film-app:active { transform: scale(var(--motion-press-scale)); }
  .film-app:focus-visible { outline: var(--line-focus) solid var(--color-lime); outline-offset: 3px; }
  @media (max-width: 480px) {
    .film-apps { gap: var(--space-2); }
    .film-app { gap: 0.45rem; min-height: 46px; padding: 5px 14px 5px 5px; font-size: 1.25rem; }
    .film-app img { width: 34px; height: 34px; border-radius: 10px; }
  }
  .film-flash { display: none; }

  /* ── Title cards: real text; in the static page they are read by screen readers only ── */
  .film-cards { list-style: none; margin: 0; padding: 0; position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .film-card { display: grid; gap: var(--space-3); }
  .film-card .h2 { display: block; }
  .film-card p { font-size: var(--type-lede-size); line-height: var(--type-lede-leading); color: var(--color-snow); opacity: 0.84; max-width: 26ch; text-wrap: balance; }

  /* ── The pellet picture at rest, behind that copy (static: a still of the scene) ── */
  .film-rest {
    grid-area: 2 / 1; position: relative; isolation: isolate; overflow: clip; display: grid; align-items: center;
    min-height: min(100svh, 52rem); padding: var(--section) var(--gutter); background: var(--color-night); color: var(--text);
  }
  .film-pellets { position: absolute; inset: 0; z-index: -1; }
  .film-pellets-poster, .film-pellets-poster img { display: block; width: 100%; height: 100%; }
  .film-pellets-poster img { object-fit: cover; object-position: 50% 50%; }
  .film-pellets-canvas { display: none; }

  /* Coming back to the page (no intro, html.film-skip from the head script): only the landing, from the first paint */
  html.film-skip .film:not(.is-live) .film-screen, html.film-skip .film:not(.is-live) .hero-content { display: none; }
  html.film-skip .film:not(.is-live) .film-rest { min-height: 100svh; }
  html.film-skip .film-pellets { animation: film-fade 900ms var(--ease-out) backwards; }
  @keyframes film-fade { from { opacity: 0; } to { opacity: 1; } }

  .film-bars, .film-ui { display: none; }

  /* ════════════════════════ Live: one sticky stage ════════════════════════ */
  .film.is-live { height: calc(100svh + var(--film-len)); }
  /* When the three-device scene follows (index.html), the film does not scroll away: the stage stays pinned for
     one more screen while the scene's page slides up over it (devices.css pulls the scene up by that screen).
     film.js reads the pull, keeps it out of the film's own timeline, and lets the stage step back under the page. */
  .film.is-live:has(+ .showcase) { height: calc(200svh + var(--film-len)); }
  /* The intro plays once: when it has landed (film.js adds .is-done) the film stops scrolling. The page is the landing,
     still pinned for the one screen in which the next page slides up over it. Scrolling back up leads to the top of that,
     not into the film again (it plays on a refresh, and on a first visit). */
  .film.is-live.is-done { height: 100svh; }
  .film.is-live.is-done:has(+ .showcase) { height: 200svh; }
  .film.is-live .film-stage { position: sticky; top: 0; height: 100svh; overflow: clip; display: block; }
  .film.is-live .film-screen { position: absolute; inset: 0; min-height: 0; }
  /* the opening copy is only the title; once it has faded it still lies over the stage, so it must not catch the
     clicks meant for the two buttons at the end */
  .film.is-live .hero-content { position: absolute; left: 0; right: 0; bottom: 0; z-index: 3; pointer-events: none; }
  /* the ident's still: over its clip while the emblem is at rest (film.js fades it as the page moves); until the
     clip is ready it carries the opening alone and opens like an iris at the lens */
  .film.is-live .film-ident {
    display: block; position: absolute; inset: 0; transform-origin: 50% 50%;
    -webkit-mask-image: radial-gradient(circle at 50% 50%, transparent var(--hole, 0px), #000 calc(var(--hole, 0px) + 1px));
    mask-image: radial-gradient(circle at 50% 50%, transparent var(--hole, 0px), #000 calc(var(--hole, 0px) + 1px));
  }
  .film-ident img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 50%; }
  /* cards: left third on wide screens (the sights sit in the centre), low on phones */
  .film.is-live .film-cards {
    position: absolute; inset: 0; width: auto; height: auto; overflow: visible; clip-path: none; white-space: normal;
    pointer-events: none; z-index: 3;
  }
  .film.is-live .film-card {
    position: absolute; left: max(var(--gutter), calc((100% - var(--container)) / 2));
    bottom: calc(max(var(--bar-h, 0px), var(--film-floor)) + clamp(2rem, 6svh, 4rem)); max-width: min(34rem, 84vw);
    opacity: 0; color: var(--color-snow);
  }
  .film.is-live .film-card::before {
    content: ""; position: absolute; z-index: -1; inset: -45% -40% -45% -30%; pointer-events: none;
    background: radial-gradient(closest-side, color-mix(in srgb, var(--color-night) 66%, transparent), transparent);
  }
  .film.is-live .film-card p:not(.h2) { text-shadow: 0 1px 12px color-mix(in srgb, var(--color-night) 80%, transparent); }
  .film.is-live .film-card .h2 { font-size: clamp(3rem, 1.6rem + 4.6vw, 6rem); line-height: 0.86; text-shadow: 0 2px 30px color-mix(in srgb, var(--color-night) 70%, transparent); }
  @media (min-width: 1024px) {
    .film.is-live .film-card { bottom: auto; top: 50%; translate: 0 -50%; }
  }

  /* The pellet scene: one canvas over the film (film.js fades it in over the target clip's last frame, where the
     ten holes glow, and draws it while it is on screen). Where WebGL is missing, the still stands in. Nothing in
     this layer is interactive but the two buttons; it must never catch clicks meant for anything else. */
  .film.is-live .film-rest { position: absolute; inset: 0; display: block; padding: 0; min-height: 0; overflow: visible; background: none; color: var(--text); max-width: none; margin: 0; pointer-events: none; }
  .film.is-live .film-pellets { z-index: 1; opacity: 0; visibility: hidden; }
  .film.is-live .film-pellets-canvas { display: block; position: absolute; inset: 0; width: 100%; height: 100%; }
  .film.is-live .film-pellets.has-gl .film-pellets-poster { display: none; }

  /* The landing: AIMLINK, what it is, the apps, in the middle of the stage over the scene. It is not scrubbed: when the
     film has landed (film.js adds .is-landed) it clicks in: a flash and a ring from the mark, the mark recoils, the
     word snaps tight, then the lines and the apps rise one after the other. */
  .film.is-live .film-about {
    position: absolute; left: 50%; top: calc(50% - var(--film-floor) / 2); translate: -50% -50%; z-index: 2; visibility: hidden;
    width: min(44rem, calc(100% - 2 * var(--gutter))); gap: var(--space-4);
  }
  .film.is-live.is-landed .film-about { visibility: visible; }
  .film.is-live .film-about::before {
    /* a soft floor of night under the words, wider than they are */
    content: ""; position: absolute; z-index: -1; inset: -30% -40%; pointer-events: none;
    background: radial-gradient(closest-side, color-mix(in srgb, var(--color-night) 58%, transparent), transparent);
    opacity: 0; transition: opacity 700ms var(--ease-out);
  }
  .film.is-live.is-landed .film-about::before { opacity: 1; }
  .film.is-live .film-brand-mark, .film.is-live .film-brand-word, .film.is-live .film-tag .hl, .film.is-live .film-act { opacity: 0; }
  .film.is-live.is-landed .film-brand-mark,
  .film.is-live.is-landed .film-brand-word,
  .film.is-live.is-landed .film-tag .hl,
  .film.is-live.is-landed .film-act { opacity: 1; }
  .film.is-acting .film-about a { pointer-events: auto; }
  .film.is-live .film-flash {
    display: block; position: absolute; inset: 0; z-index: 1; pointer-events: none; opacity: 0;
    background: radial-gradient(60% 55% at 50% 46%, color-mix(in srgb, var(--color-lime) 38%, transparent), color-mix(in srgb, var(--color-lime) 8%, transparent) 55%, transparent 80%);
  }
  .film-brand-mark::after {
    content: ""; position: absolute; inset: -6%; border-radius: 50%; pointer-events: none; opacity: 0;
    box-shadow: 0 0 0 2px var(--color-lime), 0 0 38px color-mix(in srgb, var(--color-lime) 60%, transparent);
  }
  @media (prefers-reduced-motion: no-preference) {
    .film.is-live.is-landed:not(.is-still) .film-flash { animation: film-flash 620ms var(--ease-out) both; }
    .film.is-live.is-landed:not(.is-still) .film-brand-mark { animation: film-mark 640ms cubic-bezier(0.2, 1.3, 0.3, 1) both; }
    .film.is-live.is-landed:not(.is-still) .film-brand-mark::after { animation: film-ring 760ms var(--ease-out) both; }
    .film.is-live.is-landed:not(.is-still) .film-brand-word { animation: film-snap 480ms var(--ease-out) both; }
    .film.is-live.is-landed:not(.is-still) .film-tag .hl { animation: film-rise 560ms var(--ease-out) both; animation-delay: calc(240ms + var(--n, 0) * 90ms); }
    .film.is-live.is-landed:not(.is-still) .film-act { animation: film-rise 600ms var(--ease-out) 560ms both; }
    .film.is-live .film-tag .hl:nth-child(2) { --n: 1; }
    .film.is-live .film-tag .hl:nth-child(3) { --n: 2; }
  }
  @keyframes film-flash { 0% { opacity: 0; } 14% { opacity: 1; } 100% { opacity: 0; } }
  @keyframes film-mark { 0% { opacity: 0; transform: scale(1.45); } 30% { opacity: 1; } 55% { transform: scale(0.88); } 100% { opacity: 1; transform: scale(1); } }
  @keyframes film-ring { 0% { opacity: 0.95; transform: scale(0.7); } 100% { opacity: 0; transform: scale(2.6); } }
  @keyframes film-snap { 0% { opacity: 0; letter-spacing: 0.3em; transform: scale(1.05); } 55% { opacity: 1; } 100% { opacity: 1; letter-spacing: 0.02em; transform: scale(1); } }
  @keyframes film-rise { 0% { opacity: 0; transform: translateY(0.45em); } 100% { opacity: 1; transform: none; } }

  /* letterbox: scope 2.39:1 on wide screens, none on tall ones */
  .film.is-live .film-bars { display: block; position: absolute; inset: 0; pointer-events: none; z-index: 2; }
  .film.is-live .film-bars::before, .film.is-live .film-bars::after {
    content: ""; position: absolute; left: 0; right: 0; height: var(--bar-h); background: #05080B;
    transform: scaleY(var(--bars, 0));
  }
  .film.is-live .film-bars::before { top: 0; transform-origin: 50% 0; }
  .film.is-live .film-bars::after { bottom: 0; transform-origin: 50% 100%; }
  .film.is-live .film-stage { --bar-h: 0px; }
  @media (min-aspect-ratio: 4/3) { .film.is-live .film-stage { --bar-h: max(0px, calc((100svh - 100vw / 2.39) / 2)); } }

  /* loader line + sound toggle */
  .film.is-live .film-ui { display: block; position: absolute; inset: 0; z-index: 4; pointer-events: none; }
  .film-load { position: absolute; left: 0; right: 0; bottom: var(--film-floor); height: 2px; background: var(--color-lime); transform-origin: 0 50%; transform: scaleX(var(--loaded, 0)); transition: opacity 600ms var(--ease-out); }
  .film-load.is-done { opacity: 0; }
  .film-sound {
    pointer-events: auto; position: absolute; right: max(var(--gutter), calc((100% - var(--container)) / 2)); bottom: calc(var(--film-floor) + var(--space-5));
    display: inline-flex; align-items: center; gap: 0.6rem; min-height: 44px; padding: 0 16px;
    border: 0; border-radius: var(--radius-pill); background: color-mix(in srgb, var(--color-night) 55%, transparent);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--color-snow) 28%, transparent);
    color: var(--color-snow); font: 500 0.875rem/1 var(--font-text); cursor: pointer;
    -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
    transition: opacity 400ms var(--ease-out), box-shadow var(--duration-hover) var(--ease-hover);
  }
  .film-sound:focus-visible { outline: var(--line-focus) solid var(--color-lime); outline-offset: 3px; }
  @media (hover: hover) and (pointer: fine) { .film-sound:hover { box-shadow: inset 0 0 0 1px var(--color-snow); } }
  .film-sound .eq { display: inline-flex; align-items: end; gap: 2px; height: 12px; }
  .film-sound .eq i { display: block; width: 2px; height: 4px; background: currentColor; border-radius: 1px; }
  .film-sound[aria-pressed="true"] .eq i { background: var(--color-lime); animation: film-eq 900ms var(--ease-out) infinite alternate; }
  .film-sound[aria-pressed="true"] .eq i:nth-child(2) { animation-delay: -300ms; }
  .film-sound[aria-pressed="true"] .eq i:nth-child(3) { animation-delay: -600ms; }
  @keyframes film-eq { from { height: 3px; } to { height: 12px; } }
  /* only while the film proper rolls: not over the ident, not once the picture pulls back */
  .film.is-live:not(.is-rolling) .film-sound { opacity: 0; visibility: hidden; pointer-events: none; transition: opacity 400ms var(--ease-out), visibility 0s linear 400ms; }
  @media (prefers-reduced-transparency: reduce) { .film-sound { background: var(--color-night); -webkit-backdrop-filter: none; backdrop-filter: none; } }
  /* phones: top right (the menu bar is at the bottom) */
  @media (max-width: 1023.98px) {
    .film-sound { top: calc(env(safe-area-inset-top, 0px) + var(--space-4)); bottom: auto; right: var(--gutter); }
  }

  /* the pause for the scene: there once the pellets float (a scene that moves by itself needs one) */
  .film-bg-toggle {
    right: max(var(--gutter), calc((100% - var(--container)) / 2)); bottom: calc(var(--film-floor) + var(--space-5));
    opacity: 0; visibility: hidden; pointer-events: none; transition: opacity 400ms var(--ease-out), visibility 0s linear 400ms;
  }
  .film.is-settled .film-bg-toggle { opacity: 0.85; visibility: visible; pointer-events: auto; transition: opacity 400ms var(--ease-out); }
  @media (max-width: 1023.98px) {
    .film-bg-toggle { top: calc(env(safe-area-inset-top, 0px) + var(--space-4)); bottom: auto; right: var(--gutter); }
  }
}

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

/* The header waits for the film (film.js sets html.film-veil and --film-nav, 0 to 1 as the strips hand over).
   Unlayered on purpose, so it wins over nav.css; a keyboard user who tabs into the bar gets it at once. */
html.film-veil .site-header, html.film-veil .mtop { opacity: var(--film-nav, 0); }
html.film-veil .site-header *, html.film-veil .mtop * { pointer-events: none; }
html.film-veil .site-header:focus-within { opacity: 1; }
