/* motion.css: interaction states, press feedback, menus, dialog, carousel arrows and the scroll wheel (design review
   20.10.2026, owner: site.js + this file belong together). Loaded after sections.css and form.css, so these rules win.
   Tokens (site.css): --ease-out, --ease-in-out, --ease-drawer, --t-press 70ms, --t-release 160ms, --t-ui 220ms, and the
   elevation shadows --sh-1/2/3, --sh-btn, --sh-btn-press, --sh-press, --hi.

   One press model: a pressable thing sinks 1 px towards the paper and its shadow drops to the pressed level in 70 ms;
   it comes back in 160 ms with ease-out. Hover (a lift of 1 to 2 px) only for a real mouse: (hover:hover) and
   (pointer:fine), so a tap never leaves a hover state behind. iOS fires :active because site.js listens to touchstart. */

/* ---------- buttons: sections.css already carries the model for .btn and .about-link (lift on a real hover, sink 1 px
   with the pressed shadow); on a touch screen there is no hover, so the blue button also darkens while pressed ---------- */
.btn:active { background-color: var(--blue-deep, #1A45C0); }
/* the form buttons (form.css has the same model): the hover lift (:not() makes it stronger) must not win over the press */
.lf-btn:not([aria-disabled="true"]):active { transform: translateY(1px); transition-duration: var(--t-press); }
.lf-btn:not([aria-disabled="true"]):active { box-shadow: var(--sh-btn-press); }
.lf-back { transition: transform var(--t-release) var(--ease-out), color 150ms ease; }
.lf-back:not([disabled]):active { transform: translateY(1px); transition-duration: var(--t-press); }

/* ---------- clickable reels (the film poster has its own press in sections.css: the play icon sinks, the picture zooms) ---------- */
.reel-phone { transition: transform 200ms var(--ease-out), box-shadow 200ms var(--ease-out); }
@media (hover: hover) and (pointer: fine) { .reel-phone:hover { transform: translateY(-2px); box-shadow: var(--sh-3); } }
.reel-phone:active { transform: translateY(1px); box-shadow: var(--sh-1); transition-duration: var(--t-press); }

/* ---------- small text controls: colour and background only ---------- */
.chap, .lang-it, .lang-btn, .faq-item summary, .projects a, .ftr-req a, .lf-note a { transition: background-color 150ms ease, color 150ms ease, border-color 150ms ease; }
.lang-btn:active { background: var(--paper2); }

/* ---------- sticky call to action (site.js sets is-on; the slide itself is in sections.css .sticky-dock): with «reduce
   motion» it fades instead of sliding ---------- */
@media (prefers-reduced-motion: reduce) {
  [data-sticky-cta] { transform: none !important; opacity: 0; transition: opacity 150ms ease, visibility 0s linear 150ms !important; }
  [data-sticky-cta].is-on { opacity: 1; transition: opacity 150ms ease, visibility 0s !important; }
}

/* ---------- film dialog ---------- */
/* the page under it does not scroll (site.js toggles is-locked); the gutter stays, so nothing shifts sideways */
html.is-locked { overflow: hidden; scrollbar-gutter: stable; }
/* open: fades and settles from 96 %, 240 ms; close: 150 ms. Browsers without @starting-style simply snap. */
.film-dlg { opacity: 0; transform: scale(.98);
  transition: opacity 150ms var(--ease-out), transform 150ms var(--ease-out);
  transition: opacity 150ms var(--ease-out), transform 150ms var(--ease-out), overlay 150ms allow-discrete, display 150ms allow-discrete; }
.film-dlg[open] { opacity: 1; transform: none; transition-duration: 240ms; }
@starting-style { .film-dlg[open] { opacity: 0; transform: scale(.96) translateY(8px); } }
.film-dlg::backdrop { background-color: rgba(20, 22, 26, 0);
  transition: background-color 240ms ease;
  transition: background-color 240ms ease, overlay 240ms allow-discrete, display 240ms allow-discrete; }
.film-dlg[open]::backdrop { background-color: rgba(20, 22, 26, .9); }
@starting-style { .film-dlg[open]::backdrop { background-color: rgba(20, 22, 26, 0); } }
@media (prefers-reduced-motion: reduce) {
  .film-dlg, .film-dlg[open] { transform: none !important; }
}
.film-close { transition: transform var(--t-release) var(--ease-out), background-color 150ms ease, box-shadow var(--t-release) var(--ease-out); }
.film-close:active { transform: translateY(1px); transition-duration: var(--t-press); }
/* wide screens: the close button stands above the sheet, so the sheet keeps 60 px of air on short screens too */
@media (min-width: 1024px) { .film-video { max-height: min(82svh, calc(100svh - 150px)); } }
/* phones and tablets: the dialog fills the screen and scrolls inside; the close button stays in the top right corner
   (it belongs to the dialog, not to the scrolling sheet) and the call to action sticks to the bottom over the chapter
   list, so both are always within reach (before: the close button sat 32 px above the screen and the call to action
   119 px below it, with no way to scroll there) */
@media (max-width: 1023px) {
  .film-dlg { inset: 0; width: 100%; max-width: none; height: 100%; height: 100dvh; max-height: none; margin: 0; overflow: hidden; background: var(--paper); }
  .film-dlg-in { position: static; height: 100%; overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch;
    align-content: start; padding: 64px 12px max(16px, env(safe-area-inset-bottom)); }
  .film-video { max-height: 58svh; }
  .film-dlg-side .chaps { max-height: none; overflow: visible; }
  .film-dlg [data-film-cta] { position: sticky; z-index: 2; bottom: max(12px, env(safe-area-inset-bottom)); width: 100%;
    box-shadow: var(--sh-btn), 0 0 0 12px var(--paper), 0 16px 0 12px var(--paper), 0 -14px 14px 6px var(--paper); }
  .film-dlg [data-film-cta]:active { box-shadow: var(--sh-btn-press), 0 0 0 12px var(--paper), 0 16px 0 12px var(--paper), 0 -14px 14px 6px var(--paper); }
  .film-close { top: 10px; right: 10px; z-index: 3; color: var(--ink); background: var(--sheet); border: 1px solid var(--edge-2); box-shadow: var(--hi), var(--sh-2); }
  .film-close:active { background: var(--paper2); box-shadow: var(--hi), var(--sh-press); }
}

/* ---------- language menu: grows from the button (site.js plays 160 ms on open; closing is instant) ---------- */
.lang-list { transform-origin: top right; }
.lang-btn .lang-caret { transition: transform 160ms var(--ease-out); }

/* ---------- questions: the answer opens in 220 ms (browsers without ::details-content snap, as before) ---------- */
.faq-item { interpolate-size: allow-keywords; }
.faq-item::details-content { block-size: 0; overflow-y: clip;
  transition: block-size var(--t-ui) var(--ease-in-out), content-visibility var(--t-ui) allow-discrete; }
.faq-item[open]::details-content { block-size: auto; }
.faq-item summary::after { transition: transform var(--t-ui) var(--ease-out); }
@media (prefers-reduced-motion: reduce) { .faq-item::details-content { transition: none; } }

/* ---------- reveals (site.js adds v2-rev and is-in): 480 ms, 12 px, ease-out, a row of reels 60 ms apart; the gallery
   wipe and its pen line 700 ms, the signature 900 ms. With «reduce motion» only a 200 ms fade. ---------- */
.v2-rev .reel, .v2-rev .film-card, .v2-rev .about-photo, .v2-rev .bridge {
  opacity: 0; transform: translateY(12px);
  transition: opacity 480ms var(--ease-out), transform 480ms var(--ease-out); transition-delay: calc(var(--i, 0) * 60ms); }
.v2-rev .reel.is-in, .v2-rev .film-card.is-in, .v2-rev .about-photo.is-in, .v2-rev .bridge.is-in { opacity: 1; transform: none; }
.v2-rev .gal-group .gal-row { transition: clip-path 700ms var(--ease-in-out); }
.v2-rev .gal-group::after { transition: transform 700ms var(--ease-in-out); }
.v2-rev .sign { transition: stroke-dashoffset 900ms var(--ease-in-out) 150ms; }
@media (prefers-reduced-motion: reduce) {
  .v2-rev .reel, .v2-rev .film-card, .v2-rev .about-photo, .v2-rev .bridge { transform: none !important; transition: opacity 200ms ease !important; }
  .v2-rev .gal-group .gal-row, .v2-rev .gal-group.is-in .gal-row { clip-path: none !important; }
  .v2-rev .gal-group .gal-row { opacity: 0; transition: opacity 200ms ease !important; }
  .v2-rev .gal-group.is-in .gal-row { opacity: 1; }
  .v2-rev .gal-group::after { transform: none !important; }
  .v2-rev .sign { stroke-dashoffset: 0 !important; }
}

/* ---------- carousel arrows: the same press; a disabled arrow shrinks away and cannot be focused ---------- */
.car-btn { visibility: visible;
  transition: opacity 150ms ease, transform var(--t-release) var(--ease-out), box-shadow var(--t-release) var(--ease-out), background-color 150ms ease, visibility 0s; }
@media (hover: hover) and (pointer: fine) { .car-btn:not([disabled]):hover { transform: translateY(-1px); } }
.car-btn:not([disabled]):active { transform: translateY(1px); box-shadow: var(--sh-press); transition-duration: var(--t-press); }
.car-btn[disabled] { opacity: 0; transform: scale(.9); visibility: hidden; pointer-events: none;
  transition: opacity 150ms ease, transform 150ms var(--ease-out), visibility 0s linear 150ms; }

/* ---------- the scroll wheel (site.js): a wider transparent touch area around the visible body; the body keeps its
   size and gets a soft shadow from above instead of the offset one; it widens a little while held ---------- */
.wheel { right: 0; width: 40px; height: 136px; margin-top: -68px; padding-right: 10px; display: flex; align-items: center; justify-content: flex-end;
  border-radius: 0; background: none; box-shadow: none; -webkit-tap-highlight-color: transparent; }
.wheel::before, .wheel::after { content: none; }
.wheel-body { position: relative; flex: none; width: 22px; height: 112px; border-radius: 11px;
  box-shadow: 0 0 0 1.5px var(--ink), 0 1px 2px rgba(20, 22, 26, .30), 0 6px 12px -4px rgba(20, 22, 26, .32), 0 16px 30px -12px rgba(20, 22, 26, .40);
  transition: transform 160ms var(--ease-out); }
.wheel-body canvas { display: block; border-radius: 11px; }
/* the axle caps above and below, so it reads as a wheel in a slot */
.wheel-body::before, .wheel-body::after { content: ''; position: absolute; left: 50%; width: 30px; height: 6px; margin-left: -15px; background: var(--ink); border-radius: 2px;
  box-shadow: 0 1px 2px rgba(20, 22, 26, .25); }
.wheel-body::before { top: -9px; }
.wheel-body::after { bottom: -9px; }
.wheel.is-drag .wheel-body { transform: scaleX(1.12); transition-duration: 120ms; }
/* phones: the body stays 10 px thin in the side gutter, the touch area is 22 px (the carousel arrows end 22 px from
   the edge) */
@media (max-width: 760px) {
  .wheel { width: 22px; height: 108px; margin-top: -54px; padding-right: 3px; }
  .wheel-body { width: 10px; height: 84px; border-radius: 5px;
    box-shadow: 0 0 0 1px var(--ink), 0 1px 2px rgba(20, 22, 26, .28), 0 4px 10px -3px rgba(20, 22, 26, .30), 0 10px 20px -8px rgba(20, 22, 26, .36); }
  .wheel-body canvas { border-radius: 5px; }
  .wheel-body::before, .wheel-body::after { width: 14px; margin-left: -7px; height: 4px; }
  .wheel-body::before { top: -7px; }
  .wheel-body::after { bottom: -7px; }
}
@media (prefers-reduced-motion: reduce) { .wheel-body { transition: none; } }
