/* gethoy.app, the home page: the app's own hello, carried on by the scroll.
   A crowd floats up and Dominik's face says hello (the app's Welcome); scrolling, three of the crowd land beside it,
   the menu bar forms round them, and the four things he names are done by Hoy itself while a camera moves over it.
   Every piece of Hoy is drawn at the app's own sizes in points (1pt = 1px here) and scaled as a whole. Values come
   from the app's source (see _explore/research/hoy-map/build), not from taste.
   Order: the page around it (film, hello, crowd, captions, ending), then the strip, the card, the drops,
   the composer, the catcher, the things in the air, phone, motion.
   What every page has is in site.css: the bar, the buttons and their sizes, the chip (.pro), the dashed pill, the
   hello's type (.narr), the ring's keyframes (hf-sonar-s, hf-sonar-o). */

/* the page around it ------------------------------------------------ */
/* a jump from the bar (Hoy Pro) does not scroll the page through the film: the page goes out, is put there, and
   comes in again (hoy.js: is-jumping) */
main { transition: opacity .3s cubic-bezier(.2, .7, .2, 1); }
.is-jumping main { opacity: 0; transition-duration: .16s; }
.is-arriving .controls, .is-arriving .get .btn { pointer-events: none; }      /* (see jumpTo: no click on the bar while it changes under the pointer) */
.say:focus:not(:focus-visible) { outline: none; }      /* (the jump hands the heading the focus; no ring unless the keyboard asked) */
.glyphs { position: absolute; }
/* ?at=2.4 shows the film as it stands that many screens into its scroll, with nothing moving (for checking frames) */
.is-frozen *, .is-frozen *::before, .is-frozen *::after { transition: none !important; animation: none !important; }

/* the film. Without scripts, or with reduced motion, it is only its words: the hello, the four things, the ending */
.film-pin { display: grid; justify-items: start; gap: clamp(28px, 4vw, 44px); padding: clamp(124px, 17vh, 220px) var(--side) 0; }
.hello { display: grid; justify-items: start; gap: 22px; }
.hello-face { display: block; width: 88px; height: 88px; }
.hello-fly, .hello-bob { display: block; width: 100%; height: 100%; }
.hello-bob { position: relative; border-radius: 50%; }
.hello-sonar { display: none; }
.hello-bob picture, .hoy picture, .fly-pic picture { display: contents; }
.hello-bob img { display: block; width: 100%; height: 100%; border-radius: 50%; object-fit: cover; }
.hello .ctas { display: flex; flex-direction: column; align-items: flex-start; margin: 0; }
/* under the hello's Download, what comes next, in the fine line's type and as far under it as the pill's own
   caption: "iOS / iPadOS" and the Soon chip the dashed pill has. It is in the button's paragraph, so it comes, stays
   and leaves with the button */
.hello .ctas .fine { display: flex; align-items: center; gap: 7px; margin: 18px 0 0; }
/* the ending's line starts with the link symbol, as tall as the line's capitals and in its ink */
.lk { display: inline-block; width: .84em; height: .84em; margin-right: .26em; vertical-align: -.1em; fill: currentColor; overflow: visible; }
.fin .ctas { display: flex; margin-top: clamp(28px, 2.5vw, 44px); }
.fin .fine { margin-top: 22px; }
html:not(.js) :is(.crowd, .hoy, .fw, .fly, .burst, .cue) { display: none; }
html:not(.js) .phone .hoy.ph { display: block; }      /* (the phone under the Pro line is there without scripts too) */

/* with scripts: one tall section, its stage pinned while the page scrolls through the film (hoy.js) */
.js .film { position: relative; height: 1220vh; height: calc(100svh * 12.2); }
.js .film-pin { position: sticky; top: 0; display: block; height: 100vh; height: 100svh; padding: 0; overflow: hidden; overflow: clip; --oe: cubic-bezier(0, 0, .58, 1); }
/* until hoy.js has run nothing on the stage is placed or sized (it sets --fs and says what is there), and a browser
   that paints before a deferred script runs, as Chrome does on a reload, would show that for a frame: so the stage
   is unseen until the script says it is its own (.has-film, the first thing it does) */
.js:not(.has-film) .film-pin { visibility: hidden; }
/* once the glass has gone and only the drops are left, the older ones fade out under the bar */
.js .film-pin::before { content: ""; position: absolute; z-index: 3; inset: 0 0 auto; height: 26%; background: linear-gradient(var(--bg) 34%, transparent); opacity: calc(var(--free, 0) * (1 - var(--near, 0)) * (1 - var(--gone, 0))); pointer-events: none; }      /* (--gone: Hoy has left the stage, and the wash goes with it) */

/* a sentence's words sharpen in together from a blur, 55ms apart; a said line settles back as the next begins;
   a line still to come waits faintly, so there is always more to scroll for */
.js .np { transition: opacity .65s ease-in-out; }
.js .np .sn { display: inline-block; white-space: nowrap; }      /* a short sentence stays in one piece */
.js .np .w { display: inline-block; opacity: 0; filter: blur(calc(var(--fs) * .16)); translate: 0 calc(var(--fs) * .1); transition: opacity .55s var(--oe), filter .55s var(--oe), translate .55s var(--oe); }
.js .np[data-s="said"] .w, .js .np[data-s="quiet"] .w { opacity: 1; filter: none; translate: 0 0; transition-delay: calc(var(--i) * 55ms); }
.js .np[data-s="quiet"] { opacity: .4; }
.js .np[data-s="ghost"] .w { opacity: .15; filter: none; translate: 0 0; }
.js .np[data-s="gone"] .w { opacity: 0; filter: blur(calc(var(--fs) * .24)); translate: 0 calc(var(--fs) * -.12); transition-duration: .4s; }

/* the hello: his face over his words, the two a little above the middle */
.js .hello { position: absolute; z-index: 1; left: 50%; top: 46%; translate: -50% -50%; width: min(var(--fs) * 20, 100% - var(--gutter) * 2); display: flex; flex-direction: column; align-items: center; gap: calc(var(--fs) * .6); text-align: center; }
/* the menu bar forms right on his face: its own face takes over there, same size, same spot */
.js .hello.is-landed { pointer-events: none; }
.js .hello.is-landed .hello-face { visibility: hidden; }
.js .hello-face { flex: none; width: calc(var(--fs) * 2.96); height: calc(var(--fs) * 2.96); animation: face-up var(--t-rise, 1s) var(--e-rise, var(--ease)) .5s backwards; }
.js .hello-face.is-up { animation: none; }
/* the button under the lines: it rises in when the faded line appears, and leaves with the words */
.js .hello .ctas { align-items: center; margin-top: calc(var(--fs) * .32); visibility: hidden; }
.js .hello.has-cta .ctas { visibility: visible; animation: rise .8s var(--ease) backwards; }
.js .hello-bob { box-shadow: 0 calc(var(--fs) * .08) calc(var(--fs) * .3) rgb(0 0 0 / .2); transition: box-shadow .3s; animation: face-bob-in .95s ease-in-out 1.7s both, face-bob 1.9s ease-in-out 2.65s infinite alternate; }
/* once the page moves it stops bobbing and loses its shadow: it is about to be a face in the menu bar */
.js .hello-face.is-still .hello-bob { animation: none; box-shadow: 0 0 0 rgb(0 0 0 / 0); }
@keyframes face-up { from { translate: 0 90vh; } }
/* settled, it eases up into its bob from rest (starting the bob itself there was a 2.5px step) */
@keyframes face-bob-in { from { translate: 0 0; } to { translate: 0 -2.5px; } }
@keyframes face-bob { from { translate: 0 -2.5px; } to { translate: 0 2.5px; } }

/* the crowd: faces at their depths, nearer ones bigger and in front, the nearest and farthest out of focus. Each
   floats up to its spot, hangs there, and lifts away (--away, the scroll) when the face takes off */
.crowd { position: absolute; z-index: 0; inset: 0; pointer-events: none; --away: 0; }
.cf { position: absolute; left: var(--x); top: var(--y); width: var(--d); height: var(--d); margin: calc(var(--d) / -2) 0 0 calc(var(--d) / -2);
  --u: clamp(0, (var(--away) - var(--lag)) / (1 - var(--lag)), 1);
  translate: 0 calc(var(--u) * var(--u) * var(--lift) * -1px); opacity: calc(1 - var(--u) * var(--u) * var(--u));
  animation: cf-up var(--dur) var(--ease) var(--delay) backwards; }
/* three of them stay when the rest lift away: they are the ones who take the spots beside him. They float here
   only until they set off; from then on each is the strip's own face, flying (see .hf.is-flying) */
.crowd--top { z-index: 3; }
.cf--land { translate: none; opacity: 1; }
.cf--land .cf-p { background: #8e8e93 center / cover; filter: none; }
.crowd.is-away .cf:not(.cf--land) { display: none; }
.cf-b, .cf-s, .cf-p { display: block; width: 100%; height: 100%; }
.cf-b { animation: cf-bob var(--bobT) ease-in-out var(--ph1) infinite alternate; }
.cf-s { animation: cf-sway var(--swayT) ease-in-out var(--ph2) infinite alternate; }
.cf-p { border-radius: 50%; overflow: hidden; background: #8e8e93 url(/assets/img/crowd.jpg) 0 0 / 800% 500%; background-image: image-set(url("/assets/img/crowd.avif") type("image/avif"), url("/assets/img/crowd.jpg") type("image/jpeg")); filter: blur(var(--blur)); box-shadow: 0 calc(var(--d) * .02) calc(var(--d) * .06) rgb(0 0 0 / .22); }
.cf-p svg { display: block; width: 100%; height: 100%; }
@keyframes cf-up { from { transform: translateY(var(--from)) rotate(var(--tilt)); } }
@keyframes cf-bob { from { translate: 0 calc(var(--bob) * -1); } to { translate: 0 var(--bob); } }
@keyframes cf-sway { from { translate: calc(var(--sway) * -1) 0; rotate: calc(var(--turn) * -1); } to { translate: var(--sway) 0; rotate: var(--turn); } }

/* what he says while the app does it, where a film has its subtitles */
/* the line under the zoomed-out menu bar: in the hello's place and size */
.js .mid { position: absolute; z-index: 4; left: 50%; top: 46%; translate: -50% -50%; width: min(100% - var(--gutter) * 2, var(--fs) * 20); text-align: center; pointer-events: none; }
.js .cap { position: absolute; z-index: 4; left: 50%; bottom: clamp(26px, 6.5vh, 64px); translate: -50% 0; width: min(100% - var(--gutter) * 2, var(--fs) * 22); display: grid; justify-items: center; text-align: center; font-size: calc(var(--fs) * .78); pointer-events: none; }
.js .cap .np { grid-area: 1 / 1; margin: 0; }

/* "Work with channel files in Finder." (Pro): the channels as the folders they are in Finder, and nothing of Finder
   around them but its back and forward, at their top left. No frame, no lights, no title. Four folders in a row (two
   by two on a phone), a name under each as Finder sets it. They come up with the scroll, one by one (--fwo, --fwy,
   --p, --y: hoy.js). Then the pointer opens one with a double click and its files take the folders' places. */
.fw { --fdw: clamp(104px, 9.6vw, 144px); --cell: calc(var(--fdw) * 1.34); --rowh: calc(var(--fdw) + 44px); --fw-ctl: #fff; --fw-line: rgb(0 0 0 / .14); --fw-sel: rgb(0 0 0 / .08); --fw-acc: #0a82ff;
  position: absolute; z-index: 3; left: 50%; top: 45%; translate: -50% calc(-50% + var(--fwy, 0px)); opacity: var(--fwo, 0); font-family: var(--sans); color: var(--ink); visibility: hidden; pointer-events: none; }
.fw.is-on { visibility: visible; }
/* back and forward in one capsule, a hairline between them, over the first folder's left edge: Back lights up once
   there is somewhere to go back to */
.fw-nav { position: absolute; left: calc((var(--cell) - var(--fdw)) / 2 + var(--fdw) * .04); bottom: calc(100% + 4px); display: flex; align-items: center; gap: 21px; height: 32px; padding: 0 13px; border-radius: 16px; background: linear-gradient(var(--fw-line), var(--fw-line)) 50% 50% / 1px 15px no-repeat, var(--fw-ctl); box-shadow: 0 0 0 .5px rgb(0 0 0 / .1), 0 1px 4px rgb(0 0 0 / .08); }
.fw-nav svg { display: block; width: 8px; height: 13px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; opacity: .28; transition: opacity .2s var(--oe); }
.fw.is-open .fw-back { opacity: .9; }
/* the folders, and (in the same places, once one is opened) that folder's files */
.fw-grid { display: grid; grid-template-columns: repeat(4, var(--cell)); align-items: start; margin: 0; padding: 0; list-style: none; }
.fw-grid li { display: grid; justify-items: center; }
.fw-ico { position: relative; display: grid; place-items: center; width: var(--fdw); height: var(--fdw); border-radius: calc(var(--fdw) * .1); transition: background-color .1s var(--oe); }
.fw-ico picture { display: contents; }
.fw-ico img { display: block; width: 100%; height: 100%; }
/* (the pictures have empty room around the folder for its shadow: the name is pulled up to sit as near as Finder's) */
.fw-grid b { max-width: calc(var(--cell) + 16px); margin-top: calc(var(--fdw) * -.06); font: 400 12px/16px var(--sans); letter-spacing: -.003em; text-align: center; text-wrap: balance; overflow-wrap: anywhere; }
.fw-grid b span { padding: 1.5px 5px 2px; border-radius: 5px; -webkit-box-decoration-break: clone; box-decoration-break: clone; transition: background-color .1s var(--oe), color .1s var(--oe); }
.fw-grid b i { font-style: normal; white-space: nowrap; }
/* the folders come up one by one */
.fw-dirs li { opacity: var(--p, 0); translate: 0 var(--y, 0); scale: calc(.94 + .06 * var(--p, 0)); }
/* clicked: Finder's own selection, a grey square behind the icon and the name on the accent colour */
.fw-grid li.is-sel .fw-ico { background: var(--fw-sel); }
.fw-grid li.is-sel b span { background: var(--fw-acc); color: #fff; }
/* the files: over the folders, place for place, as many as there are folders. A picture and a recording show as
   themselves, as Finder shows them, standing where a folder stands; the other two are this Mac's own icons for their
   kinds, at the size the folders are */
.fw-files { position: absolute; left: 0; top: 0; grid-auto-rows: var(--rowh); }
.fw-shot .fw-ico { align-items: end; padding-bottom: 13%; }
.fw-shot img { width: 80%; height: auto; border-radius: 3px; box-shadow: 0 0 0 .5px rgb(0 0 0 / .22), 0 1.5px 4px rgb(0 0 0 / .2); }
.fw-doc img { width: 84%; height: 84%; }
/* opened: the folders make way and the files come into their places, one after the other; back, the files go first */
.fw-dirs { transition: opacity .2s var(--oe) .12s, scale .3s var(--ease) .12s; }
.fw.is-open .fw-dirs { opacity: 0; scale: 1.03; transition: opacity .14s var(--oe), scale .2s var(--oe); }
.fw-files li { opacity: 0; scale: .92; translate: 0 6px; transition: opacity .12s var(--oe), scale .12s var(--oe), translate .12s var(--oe); }
.fw.is-open .fw-files li { --d: calc(.1s + var(--n, 0) * 45ms); opacity: 1; scale: 1; translate: 0 0; transition: opacity .26s var(--oe) var(--d), scale var(--t-launch, .5s) var(--e-launch, var(--ease)) var(--d), translate var(--t-launch, .5s) var(--e-launch, var(--ease)) var(--d); }
/* the pointer that opens it (hoy.js brings it over) */
.fw-ptr { position: absolute; z-index: 3; left: 0; top: 0; width: 17px; height: 24px; margin: -1px 0 0 -1px; translate: var(--px, 0px) var(--py, 0px); opacity: var(--po, 0); transform-origin: 2px 2px; filter: drop-shadow(0 1px 2px rgb(0 0 0 / .3)); }
@media (prefers-color-scheme: dark) {
  .fw { --fw-ctl: rgb(255 255 255 / .08); --fw-line: rgb(255 255 255 / .16); --fw-sel: rgb(255 255 255 / .13); --fw-acc: #0a84ff; }
  .fw-nav { box-shadow: 0 0 0 .5px rgb(255 255 255 / .12); }
}
@media (max-width: 720px) {
  .fw { --fdw: min(30vw, 124px); --cell: calc(var(--fdw) * 1.3); }
  .fw-grid { grid-template-columns: repeat(2, var(--cell)); }
  .fw-dirs { grid-auto-rows: var(--rowh); }          /* (so the files' rows are the folders' rows) */
}

/* the ending: the line and the button, a little above the middle like the hello */
.js .fin { position: absolute; z-index: 4; left: 50%; top: 46%; translate: -50% -50%; width: min(100% - var(--gutter) * 2, var(--fs) * 20); display: flex; flex-direction: column; align-items: center; text-align: center; visibility: hidden; }
.js .fin.is-on { visibility: visible; }
/* (its line leads with the link's mark, so centred as a whole its words stand right of the middle, over Download.
   The line is pulled left by .3em, a little over half of what the mark and its gap push the words right by (.55em),
   so the words sit nearly over the button and the mark hangs out to the left) */
.js .fin .narr { position: relative; left: -.3em; }
.js .fin .ctas, .js .fin .fine { opacity: 0; translate: 0 10px; transition: opacity .5s var(--ease), translate .7s var(--ease); }
.js .fin.is-cta .ctas, .js .fin.is-cta .fine { opacity: 1; translate: 0 0; }
.js .fin:not(.is-cta) .ctas { pointer-events: none; }      /* (not yet shown, the button takes no click either) */
.js .fin.is-cta .fine { transition-delay: .08s; }

/* the faces of the ending: the app's Pro burst, a fountain from behind the bottom edge (hoy.js steps it) */
.burst { position: absolute; z-index: 6; inset: 0; overflow: hidden; pointer-events: none;
  /* they come up out of nothing and fall back into it: the stage's bottom edge is never a line across them */
  -webkit-mask: linear-gradient(#000 calc(100% - clamp(120px, 24vh, 260px)), #0000 calc(100% - 6px)); mask: linear-gradient(#000 calc(100% - clamp(120px, 24vh, 260px)), #0000 calc(100% - 6px)); }
.bf { position: absolute; left: 0; top: 0; border-radius: 50%; overflow: hidden; background: #8e8e93 url(/assets/img/crowd.jpg) 0 0 / 800% 500%; background-image: image-set(url("/assets/img/crowd.avif") type("image/avif"), url("/assets/img/crowd.jpg") type("image/jpeg")); box-shadow: 0 2px 6px rgb(0 0 0 / .22); will-change: transform; }
.bf svg { display: block; width: 100%; height: 100%; }
.bn { position: absolute; left: 0; top: 0; display: flex; align-items: center; height: 2.1em; padding: 0 .95em; border-radius: 99px; background: color-mix(in srgb, var(--bg) 80%, transparent); box-shadow: 0 6px 24px rgb(0 0 0 / .14), inset 0 0 0 1px rgb(128 128 128 / .18); font-weight: 600; color: var(--ink); white-space: nowrap; will-change: transform; }

/* something below: a small chevron under the hello, until the page moves */
.cue { position: absolute; z-index: 4; left: 50%; bottom: clamp(22px, 5vh, 44px); width: 13px; height: 13px; margin-left: -6.5px; border: solid var(--lo); border-width: 0 1.5px 1.5px 0; rotate: 45deg; opacity: 0; transition: opacity .6s; }
.cue.is-on { opacity: 1; animation: cue 1.8s ease-in-out infinite; }
@keyframes cue { 50% { translate: 0 6px; } }

/* after the film: pricing, the phone, then the questions */

/* soon on iPhone and iPad -------------------------------------------------------------------------------------- */
/* The statement and its placeholder on the left, the phone on the right; under them on a narrow screen. The placeholder
   is the app's own way of drawing what is not there yet: a dashed capsule */
.ios-pin { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 48px clamp(40px, 7vw, 140px); }
/* with scripts the section is tall and its stage sticks while the page scrolls through it, as the film's does: the
   phone comes closer at its top (--pz, from its top edge, so it grows downward), its drops arrive, and its lower part
   runs out under a wash of the page's colour, so the phone ends in the page and the questions follow closely */
.js .ios { height: 230vh; height: calc(100svh * 2.3); }
.js .ios-pin { position: sticky; top: 0; height: 100vh; height: 100svh; align-items: start; overflow-x: visible; overflow-y: clip; }
.js .ios-say { align-self: center; }
.js .ios .phone { margin-top: clamp(84px, 13vh, 132px); scale: var(--pz, 1); transform-origin: 50% 0; }
/* (the wash is the phone's own, so it comes closer with it and always takes the same part of it: from the middle of
   the list down the phone is gone into the page, well before its bar, its lower edge and their shadow, which are never
   seen. As the stage's, a share of the screen's height, it would let the bar show through on a tall one) */
.js .ios .phone::after { content: ""; position: absolute; z-index: 5; left: -90px; right: -90px; top: 50%; bottom: -130px; background: linear-gradient(to bottom, transparent, var(--bg) 44%); pointer-events: none; }
/* (and the stage has one of its own along its lower edge, where it cuts the phone off: close up on a low screen the
   phone's wash has not finished by there, and the cut showed as a hard line as the stage scrolled away) */
.js .ios-pin::after { content: ""; position: absolute; z-index: 2; left: calc(var(--gutter) * -1); right: calc(var(--gutter) * -1); bottom: 0; height: 32%; background: linear-gradient(to bottom, transparent, var(--bg) 74%); pointer-events: none; }
.js .ios + .block { margin-top: clamp(28px, 4vw, 72px); }
.ios .say { margin-top: 0; }
.ios .ctas { display: flex; margin: clamp(28px, 2.5vw, 44px) 0 0; }
.ios .ctas + .fine { margin-top: 18px; }      /* (when: "TestFlight available Nov 16, 2026", in the fine line's type, as far under the pill as pricing's is under its buttons) */
/* the phone: drawn, after a picture of a current iPhone (no photograph, no device art): a frame of brushed metal with the
   light running round it, a thin black bezel inside it, the screen with its own corners, the island with its lens, and
   the keys on the frame's sides (action, volume up and down on the left, the side button on the right). The app sits in
   it at the phone's own points (393 by 852), the whole scaled down by --k */
.phone { --k: .76; --rim: 3.5px; --bz: 5px; --ph-bg: #f3f3f2; --ph-chip: rgb(0 0 0 / .055); --ph-lit: rgb(0 136 255 / .12); --ph-glass: rgb(255 255 255 / .72);
  --metal: linear-gradient(140deg, #eef3f7 0%, #b4c2cf 14%, #e6edf2 30%, #9fb0c0 48%, #dde6ed 64%, #a9b9c8 82%, #e9eff4 100%);
  position: relative; flex: none; width: calc(393px * var(--k) + (var(--rim) + var(--bz)) * 2); height: calc(852px * var(--k) + (var(--rim) + var(--bz)) * 2); margin-right: clamp(0px, 5vw, 110px); padding: calc(var(--rim) + var(--bz)); border-radius: calc(55px * var(--k) + var(--rim) + var(--bz)); background: var(--metal);
  box-shadow: inset 0 0 0 .5px rgb(255 255 255 / .75), inset 0 0 1.5px .5px rgb(0 0 0 / .28), 0 0 0 .5px rgb(0 0 0 / .32), 0 50px 90px -46px rgb(0 0 0 / .55), 0 18px 36px -18px rgb(0 0 0 / .22); }
/* (the bezel: black, a hair of light where the glass meets the metal) */
.phone::before { content: ""; position: absolute; inset: var(--rim); border-radius: calc(55px * var(--k) + var(--bz)); background: #050506; box-shadow: 0 0 0 .5px rgb(0 0 0 / .6), inset 0 0 0 .75px rgb(255 255 255 / .09); }
.phone-screen { position: relative; z-index: 1; width: 100%; height: 100%; border-radius: calc(55px * var(--k)); overflow: hidden; background: var(--ph-bg); isolation: isolate; }
.phone-island { position: absolute; z-index: 3; left: 50%; top: calc(var(--rim) + var(--bz) + 11px * var(--k)); width: calc(122px * var(--k)); height: calc(35px * var(--k)); margin-left: calc(-61px * var(--k)); border-radius: 99px; background: #000; }
.phone-island::after { content: ""; position: absolute; left: 13%; top: 50%; width: calc(11px * var(--k)); height: calc(11px * var(--k)); margin-top: calc(-5.5px * var(--k)); border-radius: 50%; background: radial-gradient(circle at 38% 34%, #31466f 0, #131b33 38%, #05060c 68%); box-shadow: inset 0 0 0 .5px rgb(255 255 255 / .06); }
/* its keys: slivers of the same metal standing a little out of the frame */
.phone-key { position: absolute; left: -2px; width: 3.5px; border-radius: 1.5px 0 0 1.5px; background: linear-gradient(to right, #8796a6, #dfe7ee 55%, #b3c0cc); box-shadow: inset 0 .5px 0 rgb(255 255 255 / .6), inset 0 -.5px 0 rgb(0 0 0 / .25), -0.5px 0 0 rgb(0 0 0 / .18); }
.phone-key--action { top: 20.5%; height: 3.6%; }
.phone-key--up { top: 27.6%; height: 6.4%; }
.phone-key--down { top: 35.8%; height: 6.4%; }
.phone-key--side { left: auto; right: -2px; top: 30.5%; height: 10.4%; border-radius: 0 1.5px 1.5px 0; background: linear-gradient(to left, #8796a6, #dfe7ee 55%, #b3c0cc); box-shadow: inset 0 .5px 0 rgb(255 255 255 / .6), inset 0 -.5px 0 rgb(0 0 0 / .25), .5px 0 0 rgb(0 0 0 / .18); }
.hoy.ph { width: 393px; height: 852px; transform: scale(var(--k)); }
/* its status bar: the time (the real one: hoy.js), reception and the battery */
.ph-status { position: absolute; z-index: 3; left: 0; right: 0; top: 0; display: flex; align-items: center; justify-content: space-between; height: 54px; padding: 4px 34px 0 48px; }
.ph-clock { font: 600 16px/20px var(--sans); letter-spacing: -.01em; }
.ph-sys { display: flex; align-items: center; gap: 7px; }
.ph-bars { display: flex; align-items: flex-end; gap: 2px; height: 11px; }
.ph-bars i { width: 3px; height: 4px; border-radius: 1px; background: currentColor; }
.ph-bars i:nth-child(2) { height: 6px; } .ph-bars i:nth-child(3) { height: 8.5px; } .ph-bars i:nth-child(4) { height: 11px; }
.hoy .ph-batt { width: 27px; height: 12.4px; }
.ph-home { position: absolute; z-index: 4; left: 50%; bottom: 8px; width: 134px; height: 5px; margin-left: -67px; border-radius: 3px; background: var(--hi); }
/* the app's home, the list (ChannelListTitle, ChannelRow, DropStrip). Its title: "Channels", the chevron that offers the
   other lists when they hold something, and the dot that says one of them has something new */
.ph-list { position: absolute; inset: 0; background: var(--ph-bg); }
.ph-title { display: flex; align-items: center; gap: 6px; margin: 0; padding: 66px 37px 8px; font: 700 34px/41px var(--sans); letter-spacing: -.022em; color: var(--hi); }
.hoy .ph-down { flex: none; width: 17px; height: 11px; margin-top: 4px; color: var(--hi2); }
.ph-new { flex: none; width: 9px; height: 9px; margin: 4px 0 0 2px; border-radius: 50%; background: var(--hacc); }
/* a row a channel, at one height: the face, the name and when, and under the name the strip of its
   latest drops; a hairline under each, from the name on. The rows run out under a wash of the screen's colour above
   the bar, as the app fades them at the phone's foot */
.ph-rows { margin: 0; padding: 0; list-style: none; }
.ph-row { display: flex; align-items: center; gap: 9px; height: 94px; padding-left: 29px; }      /* (the app's is 85: they breathe more here) */
.ph-list::after { content: ""; position: absolute; z-index: 1; left: 0; right: 0; bottom: 0; height: 250px; background: linear-gradient(transparent, var(--ph-bg) 60%); }
/* (the face's column is as wide as a group's cluster, 1.3 faces, in every row, a lone face in its middle: so the names
   stand in one line, 103 in, as in the app, and the title starts at a lone face's edge) */
.ph-face { position: relative; flex: none; display: grid; place-items: center; width: 65px; height: 50px; }
/* (the faces are squircles here, the app's other avatar shape, its corner two fifths of the face; everywhere else on
   the page they are round) */
.ph-pic { display: block; width: 50px; height: 50px; border-radius: 40%; overflow: hidden; background: #8e8e93; }
/* a group's face (FaceCluster): up to three members as bubbles of different sizes that just touch, whoever dropped
   last the biggest and in front; each cuts a ring out of the ones behind it (here: an outline in the screen's colour).
   Where each sits and how big it is are the app's numbers, in units of the row's face (--x, --y, --d) */
.ph-face--group { display: block; }
.ph-face--group .ph-pic { position: absolute; left: calc(var(--x) * 50px); top: calc(var(--y) * 50px); width: calc(var(--d) * 50px); height: calc(var(--d) * 50px); translate: -50% -50%; box-shadow: 0 0 0 3px var(--ph-bg); }
.ph-face--group .ph-pic:nth-child(1) { z-index: 3; }
.ph-face--group .ph-pic:nth-child(2) { z-index: 2; }
.ph-tile b { font-weight: 600; }      /* (in a group the newest drop's words are led by who dropped it) */
.ph-col { flex: 1; min-width: 0; align-self: stretch; display: flex; flex-direction: column; justify-content: center; gap: 5px; box-shadow: 0 .5px 0 var(--hline); }
.ph-name { display: flex; align-items: baseline; gap: 8px; height: 22px; margin: 0; padding-right: 37px; }
.ph-name b { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font: 600 17px/22px var(--sans); letter-spacing: -.012em; color: var(--hi); }
.ph-name span { font: 400 13px/16px var(--sans); color: var(--hi3); }
/* the strip: the newest drop readable on a capsule (with a glimpse of what it is: a waveform, a picture, a link's page
   and its glyph), the ones before it as glimpses (a picture, a video's frame under a play mark, a file's icon, a voice
   note's length, the start of some words); it fades out where the row ends. What is unread is lit in the accent: its
   words and wash, a ring round its picture */
.ph-strip { display: flex; align-items: center; gap: 5px; height: 30px; margin: 0; overflow: hidden; white-space: nowrap; -webkit-mask: linear-gradient(to right, #000 85%, #0000); mask: linear-gradient(to right, #000 85%, #0000); }
.ph-tile { flex: none; max-width: 130px; height: 30px; padding: 0 10px; border-radius: 15px; background: var(--ph-chip); font: 400 13px/30px var(--sans); color: var(--hi2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; transform-origin: 0 50%; transition: max-width .45s cubic-bezier(.2, .8, .2, 1); }
.ph-tile:first-child { max-width: 220px; }
.ph-tile--pic { padding-left: 6px; }
.ph-tile.is-lit { background: var(--ph-lit); color: var(--hacc); }
.ph-file { display: inline-block; width: 18px; height: 18px; margin-right: 6px; border-radius: 5px; overflow: hidden; vertical-align: -4.5px; }
.hoy .ph-wave { display: inline-block; width: 15px; height: 13.3px; margin-right: 6px; vertical-align: -2px; }
.hoy .ph-play { display: inline-block; width: 8.4px; height: 9.4px; margin-right: 5px; vertical-align: -.5px; }
.hoy .ph-link { display: inline-block; width: 13px; height: 13px; margin-left: 6px; vertical-align: -2px; }
.ph-thumb { position: relative; flex: none; height: 30px; aspect-ratio: 3 / 2; border-radius: 8.4px; overflow: hidden; background: var(--hbed); transform-origin: 0 50%; }
.ph-thumb--wide { aspect-ratio: 16 / 10; }
.ph-thumb--video::before { content: ""; position: absolute; inset: 0; z-index: 1; background: rgb(0 0 0 / .18); }
.hoy .ph-thumb--video .ph-play { position: absolute; z-index: 2; left: 50%; top: 50%; width: 9px; height: 10px; margin: -5px 0 0 -3.5px; color: #fff; }
.ph-thumb.is-lit::after { content: ""; position: absolute; inset: 0; z-index: 2; border-radius: inherit; box-shadow: inset 0 0 0 2px var(--hacc); }
/* whoever is active pulses here too: the app's ring (see .hf-sonar), at its own 1pt, while the phone is in view */
.ph-sonar { position: absolute; inset: 0 7.5px; pointer-events: none; }
.ph-sonar i { position: absolute; inset: 0; border-radius: 40%; border: 1px solid var(--hp); opacity: 0; }
@media (prefers-reduced-motion: no-preference) {
  .ph-row.is-live .ph-sonar i { animation: hf-sonar-s 2.5s cubic-bezier(0, 0, .58, 1) infinite paused, hf-sonar-o 2.5s infinite paused; }
  .phone.is-seen .ph-row.is-live .ph-sonar i { animation-play-state: running; }
  .ph-row[data-who="x1"].is-live .ph-sonar i { animation-delay: -1.1s; }      /* (the two are not in step) */
}
/* its bar at the foot: Search, New channel, Settings and his face, on glass */
.ph-bar { position: absolute; z-index: 2; left: 50%; bottom: 30px; translate: -50% 0; display: flex; align-items: center; gap: 24px; height: 48px; padding: 0 20px; border-radius: 24px; background: var(--ph-glass); box-shadow: 0 6px 24px rgb(0 0 0 / .12), inset 0 0 0 .5px rgb(255 255 255 / .7), 0 0 0 .5px rgb(0 0 0 / .06); color: var(--hp); }
.hoy .ph-bar svg { flex: none; width: 22px; height: 22px; }
.hoy .ph-bar .ph-plus { width: 19px; height: 19px; }
.ph-me { flex: none; width: 26px; height: 26px; border-radius: 40%; overflow: hidden; }
@media (prefers-color-scheme: dark) {
  .phone { --ph-bg: #0d0d0d; --ph-chip: rgb(255 255 255 / .1); --ph-lit: rgb(0 145 255 / .18); --ph-glass: rgb(58 58 56 / .78); box-shadow: inset 0 0 0 .5px rgb(255 255 255 / .75), inset 0 0 1.5px .5px rgb(0 0 0 / .28), 0 0 0 .5px rgb(0 0 0 / .5), 0 50px 90px -46px #000; }
  .ph-bar { box-shadow: 0 6px 24px rgb(0 0 0 / .4), inset 0 0 0 .5px rgb(255 255 255 / .16); }
}
@media (max-width: 860px) {
  .ios-pin { grid-template-columns: minmax(0, 1fr); }
  .phone { --k: .72; justify-self: start; margin-right: 0; }
  .js .ios-pin { align-content: start; gap: 0; padding-top: 92px; }
  .js .ios-say { align-self: start; }
  .js .ios .phone { justify-self: center; margin-top: 36px; }
}

/* (the Pro statement breaks at set places on a wide screen: four lines, its quiet last sentence on a line of its
   own; on a phone the words fall as they will) */
@media (max-width: 720px) { .say br.wide { display: none; } }
/* and it says itself one sentence at a time: the sentence being said is in ink, its words turning 25ms apart,
   and the others wait in the quiet tone, the last one too. (The hello's words turn 55ms apart over half a
   second; but here a turn lasts a quarter of a second at an ordinary scroll, and at the hello's pace no
   sentence would be said out before the next begins. So a sentence of five words is in ink within .4s, and
   the one before is quiet in .4s.) hoy.js splits the sentences into words and marks the one being said
   (is-lit) from how far the page has scrolled through the section. The one before goes quiet a little slower
   than it came, so one hands over to the next. Without scripts or with reduced motion all of it is in ink but
   the last sentence.
   For that the section STICKS, as the phone's does: with scripts it is 2.8 screens tall and its stage stays in view,
   the words a little above the middle as the hello's are, while six turns are taken, some three tenths of a screen
   of scroll each, after a short opening with none; then the page goes on. The stage brings its own room above
   and below, so the section and the one after it stand off by nothing more.
   It is two statements in the one heading, the free one above "Hoy Pro.": each is a block (.tier), most of a
   line apart. Their two names, "Hoy is free." and "Hoy Pro.", have no turn: they are plain words, always in
   ink. The turns are what the free one comes with (its two sentences together) and Pro's five, and the
   statement opens with none said yet.
   And the stage is not still while it sticks: what is on it drifts up by an eighth of the screen from the first
   turn to the last (--drift, hoy.js), so the page is seen to go on */
.js .pricing { height: 280vh; height: calc(100svh * 2.8); margin-top: 0; }
.js .pricing-pin > * { translate: 0 var(--drift, 0px); }
.steps .tier { display: block; }
.steps .tier + .tier { margin-top: .8em; }
.js .pricing-pin { position: sticky; top: 0; height: 100vh; height: 100svh; display: flex; flex-direction: column; justify-content: center; padding-bottom: 8vh; }
.js .pricing + .block { margin-top: 0; }
.js .steps .st, .js .steps .st .w { color: var(--lo); }
.js .steps .st .w { transition: color .4s cubic-bezier(0, 0, .58, 1); }
.js .steps .st.is-lit .w { color: var(--ink); transition-duration: .28s; transition-delay: calc(var(--i) * 25ms); }
.say .own { display: inline-block; }      /* (and there too the quiet sentence stays whole: it goes to the next line as one, and only breaks if a line cannot hold it) */
.pricing-pin > .ctas { display: flex; flex-wrap: wrap; gap: 12px; margin-top: clamp(28px, 2.5vw, 44px); }
.pricing-pin > .ctas + .fine { max-width: 60ch; margin-top: 18px; text-wrap: pretty; }
.pricing-pin > .fine + .fine { max-width: 60ch; margin-top: 4px; text-wrap: pretty; }      /* (a second note under the first) */

/* ------------------------------------------------------------------ */
/* Hoy                                                                 */
/* ------------------------------------------------------------------ */
.hoy {
  /* the app's own inks and fills (HoyDesign.Palette) and the system's label colours */
  --hi: rgb(0 0 0 / .88); --hi2: rgb(0 0 0 / .55); --hi3: rgb(0 0 0 / .35);
  --hp: rgb(0 0 0 / .85); --hs2: rgb(0 0 0 / .5); --hs3: rgb(0 0 0 / .26);
  --htile: rgb(255 255 255 / .55); --hrim: rgb(255 255 255 / .75); --hbed: rgb(0 0 0 / .04);
  --htile-solid: #f6f6f5;                     /* what a tile comes to on the glass, for cut-outs */
  --hline: rgb(0 0 0 / .085);
  --hglass: rgb(244 244 243 / .78);           /* what the HUD material comes to over a plain light page */
  --hacc: #08f;                               /* the system's default accent on macOS 26 */
  --hgreen: #34c759;
  --hbar: #000;                               /* marks on the menu bar: pure black or white */
  --hbar-in: #fff;
  --rim: linear-gradient(163deg, rgb(255 255 255 / .45), rgb(255 255 255 / .2) 28%, rgb(255 255 255 / .1) 55%, rgb(255 255 255 / .2));
  /* The card and its tiles on a page, not on a desktop. The app's own numbers (one soft shadow each: the card 12%
     32 wide, a tile 10% 16 wide, the composer 12% 24 wide; a rim of white at 45% to 10%) are made for glass over a
     wallpaper. On a plain light page the wide shadows read as smudges and the white rim as nothing. So here: each
     lift is a close, faint contact shadow and a tighter one pulled in under the thing; the card's rim is about twice
     as bright, with a hairline just outside it for the white to stand against, and its glass catches a little light
     inside its edges, as the composer's does */
  --card-rim: linear-gradient(163deg, rgb(255 255 255 / .95), rgb(255 255 255 / .55) 28%, rgb(255 255 255 / .28) 55%, rgb(255 255 255 / .6));
  --card-lift: 0 0 0 .5px rgb(0 0 0 / .05), 0 2px 6px rgb(0 0 0 / .04), 0 14px 36px -8px rgb(0 0 0 / .14);
  --card-sheen: inset 0 0 26px rgb(255 255 255 / .3), inset 0 1px 0 rgb(255 255 255 / .35);
  --tile-lift: 0 .5px 1.5px rgb(0 0 0 / .06), 0 4px 14px -3px rgb(0 0 0 / .11);
  --glass-lift: 0 1px 2px rgb(0 0 0 / .05), 0 10px 24px -8px rgb(0 0 0 / .16);

  position: absolute;
  z-index: 2;
  left: 0;
  top: 0;
  width: 0;
  height: 0;
  transform-origin: 0 0;
  font: 400 13.5px/17px var(--sans);
  letter-spacing: 0;
  color: var(--hi);
  pointer-events: none;
  -webkit-user-select: none;
  user-select: none;
}
@media (prefers-color-scheme: dark) {
  .hoy {
    --hi: rgb(255 255 255 / .94); --hi2: rgb(255 255 255 / .55); --hi3: rgb(255 255 255 / .35);
    --hp: rgb(255 255 255 / .85); --hs2: rgb(255 255 255 / .55); --hs3: rgb(255 255 255 / .25);
    --htile: rgb(255 255 255 / .12); --hrim: rgb(255 255 255 / .13); --hbed: rgb(255 255 255 / .08);
    --htile-solid: #40403d;
    --hline: rgb(255 255 255 / .085);
    --hglass: rgb(40 40 39 / .74);
    --hacc: #0091ff; --hgreen: #30d158; --hbar: #fff; --hbar-in: #1e1e1e;
    --rim: linear-gradient(163deg, rgb(255 255 255 / .34), rgb(255 255 255 / .08) 28%, rgb(255 255 255 / .03) 55%, rgb(255 255 255 / .08));
    --card-rim: linear-gradient(163deg, rgb(255 255 255 / .42), rgb(255 255 255 / .14) 28%, rgb(255 255 255 / .06) 55%, rgb(255 255 255 / .16));
    --card-lift: 0 0 0 .5px rgb(0 0 0 / .5), 0 2px 6px rgb(0 0 0 / .2), 0 14px 36px -8px rgb(0 0 0 / .45);
    --card-sheen: inset 0 0 26px rgb(255 255 255 / .05), inset 0 1px 0 rgb(255 255 255 / .08);
    --tile-lift: 0 .5px 1.5px rgb(0 0 0 / .16), 0 4px 14px -3px rgb(0 0 0 / .2);
    --glass-lift: 0 1px 2px rgb(0 0 0 / .2), 0 10px 24px -8px rgb(0 0 0 / .4);
  }
}
/* Safari up close (hoy.js, `requant`: Safari paints the scene at its laid-out size and stretches that picture,
   which was soft): the menu bar and the row of faces are laid out --q times bigger and the camera scales them by
   the rest. --q is 1 everywhere else and is never set outside Safari. While it changes, nothing in the scene takes
   the new sizes for a move */
#hoy > .mb, #hoy > .hs { zoom: var(--q, 1); }
#hoy.is-requant, #hoy.is-requant *, #hoy.is-requant *::before, #hoy.is-requant *::after { transition: none !important; }
.hoy img { display: block; width: 100%; height: 100%; object-fit: cover; }
.hoy svg { display: block; width: 100%; height: 100%; fill: currentColor; overflow: visible; }      /* (an outline that touches its frame is not cut there) */
.hoy .on { display: inline-block; width: 6px; height: 6px; margin-right: 5px; border-radius: 50%; background: var(--hgreen); vertical-align: 1px; }

/* the strip: faces 25 across, overlapping by 8, the leftmost in front -------- */
/* the faces part round the open one, which makes the row lopsided when that one is at an end; --cx (hoy.js) moves
   the whole row so it stays in the middle of the menu bar, on the spring the faces part on */
.hs { position: absolute; left: 0; top: 0; height: 32px; translate: calc(-50% + var(--cx, 0px)) 0; display: flex; align-items: center; padding: 0 20px; opacity: 0; visibility: hidden; transition: translate var(--t-part, .5s) var(--e-part, var(--ease)); }
.hs.is-in { opacity: calc(1 - var(--free, 0)); visibility: visible; }
/* the strip comes in already parted: nothing slides at that moment */
.hs.is-snap, .hs.is-snap .hf { transition: none; }
/* a spot beside him, dashed, waiting for one of the crowd to come and take it (the app's own waiting spot). The
   three come out from behind his face as the page scrolls on, fading in: --fx is how far a spot still is from its
   place, --fo how much of it is there (hoy.js). A spot is a disc of the page's own colour with the dashed circle on
   it, so it covers the one behind it as a face does.
   Who takes it flies in as this very face: from the moment they set off, the spot's own picture is out where they
   floated and comes home with the scroll (is-flying; hoy.js places it). So it is under the face on its left and over
   the ones on its right all the way in, as it will be in the row, and nothing changes hands when it lands */
.hf-spot { position: absolute; inset: 0; border-radius: 50%; background: var(--bg); visibility: hidden; }
.hf-spot::before { content: ""; position: absolute; inset: 0; border-radius: 50%; border: .6px dashed var(--hs2); opacity: var(--fo, 1); }
.hf.is-wait .hf-spot, .hf.is-flying .hf-spot { visibility: visible; }
.hf.is-wait .hf-pic { visibility: hidden; }
.hf.is-flying .hf-pic { box-shadow: 0 .5px 1.5px rgb(0 0 0 / calc(.22 * var(--lift, 0))); }      /* (the shadow it had in the crowd goes as it comes down) */

/* the Mac's own menu bar items either side of the faces (SF Symbols), fainter toward the ends, so the row reads
   as what it is. --mb runs 0 to 1 with the scroll: they come in from the sides, the nearest first */
.mb { opacity: calc(1 - var(--free, 0)); }
.mb-l, .mb-r { position: absolute; top: 0; height: 32px; display: flex; align-items: center; gap: 19px; color: var(--hbar); }
.mb-l { right: 72px; --from: -36px; -webkit-mask: linear-gradient(90deg, #0000 -40px, #000 60px); mask: linear-gradient(90deg, #0000 -40px, #000 60px); }
.mb-r { left: 72px; --from: 36px; -webkit-mask: linear-gradient(270deg, #0000 -40px, #000 60px); mask: linear-gradient(270deg, #0000 -40px, #000 60px); }
.mb-i { flex: none; --a: clamp(0, (var(--mb, 0) - var(--k) * .3) / .5, 1); opacity: var(--a); translate: calc((1 - var(--a)) * var(--from)) 0; }
.hoy .mb-hotspot { width: 19.2px; height: 12.7px; }
.hoy .mb-battery { width: 23.1px; height: 10.6px; }
.hoy .mb-control { width: 14.9px; height: 14.75px; }
/* the clock is the visitor's own time, each glyph in a cell of its own so one can roll (hoy.js): kept in one piece,
   or the row, which is as narrow as its narrowest, would end after the first cell and mask the rest away */
.mb-clock { font: 500 13px/16px var(--sans); font-variant-numeric: tabular-nums; white-space: nowrap; }
/* The one on the left lies over the one on its right, all along the row. Each wears a 2pt outline in the page's own
   colour, under everything else it has: on the page it cannot be seen, and over the face behind it is the gap the
   app knocks out there. (A mask on the face behind, moved about to follow the one in front, glitches in
   the browser, so there is no masking in the strip at all.) An open face's ring grows over its own outline */
.hf { position: relative; left: var(--fx, 0px); isolation: isolate; flex: none; width: 25px; height: 25px; margin-left: -8px; border-radius: 50%; box-shadow: 0 0 0 2px var(--bg); translate: var(--dx, 0px) 0; transition: translate var(--t-part, .5s) var(--e-part, var(--ease)); cursor: default; }
.hf:first-child { margin-left: 0; }
.hf:nth-child(1) { z-index: 5; } .hf:nth-child(2) { z-index: 4; } .hf:nth-child(3) { z-index: 3; } .hf:nth-child(4) { z-index: 2; } .hf:nth-child(5) { z-index: 1; }
.hf-pic { position: absolute; inset: 0; border-radius: 50%; overflow: hidden; background: #8e8e93; }
/* the pointer, or a file, right on a face: a wash over it */
.hf-pic::after { content: ""; position: absolute; inset: 0; border-radius: inherit; background: var(--hbar); opacity: 0; }
/* (only the film's own pointer tints a face. The visitor's cannot reach one, but the peek hangs inside its face, so
   a :hover on the face would tint it whenever the pill is under the pointer) */
.hf.is-over .hf-pic::after { opacity: .16; }
/* open, or a file aimed at it: a 2pt ring. It grows out from under the face on a spring and goes back the same way */
.hf::after { content: ""; position: absolute; z-index: -1; inset: 0; border-radius: 50%; background: var(--hbar); scale: .9; visibility: hidden; pointer-events: none; transition: scale var(--t-ring, .4s) var(--e-ring, var(--ease)), visibility 0s var(--t-ring, .4s); }
.hf.is-open::after { scale: 1.16; visibility: visible; transition: scale var(--t-ring, .4s) var(--e-ring, var(--ease)), visibility 0s; }
/* unread: a 6pt dot in the corner, no number. It comes with that face's wiggle: they have dropped something */
.hf::before { content: ""; position: absolute; z-index: 2; right: 0; top: 0; width: 6px; height: 6px; border-radius: 50%; background: var(--hbar); opacity: 0; scale: .2; transition: opacity .15s var(--oe), scale var(--t-ring, .4s) var(--e-ring, var(--ease)); }
.hf.is-unread::before { opacity: 1; scale: 1; }
/* the menu bar's peek (MenuBarPeek): a drop that just arrived, on one line on a small glass card under its face, for
   a moment. Here a note, and a gift: a discount code, HOY30OFF. It is the one thing in the film that answers a
   click: a button, 12 in from its ends as the app's line of words is (peekInset). After the code the app's own sign
   for copying a key (Settings: square.on.square, the secondary ink), which turns into a checkmark for 1.6s once it
   has copied, one going small as the other comes (the symbols' replace) */
.hf-peek { position: absolute; z-index: 3; left: 50%; top: calc(100% + 7px); translate: -50% 0; display: flex; align-items: center; gap: 6px; height: 26px; padding: 0 12px; border: 0; margin: 0; -webkit-appearance: none; appearance: none; cursor: pointer; -webkit-tap-highlight-color: transparent; border-radius: 13px; background: var(--hglass); box-shadow: 0 4px 16px rgb(0 0 0 / .13), 0 0 0 .5px rgb(0 0 0 / .06); font: 400 11px/14px var(--sans); color: var(--hi); white-space: nowrap; transform-origin: 50% 0; opacity: 0; scale: .82; visibility: hidden; transition: opacity .14s var(--oe), scale .18s var(--oe), transform var(--t-lift, .35s) var(--e-lift, var(--ease)), visibility 0s .18s; }
/* (.hoy takes no pointer; while it is up the peek does) */
.hf.is-peek .hf-peek { pointer-events: auto; opacity: 1; scale: 1; visibility: visible; transition: opacity .2s var(--oe), scale var(--t-launch, .5s) var(--e-launch, var(--ease)), transform var(--t-lift, .35s) var(--e-lift, var(--ease)), visibility 0s; }
/* under the pointer it lights and lifts a touch, the app's own way with a pill under a face (hoverLift: the row's
   tint over all of it, 5% of the ink, in .12s, and to 1.05 on its spring; from its middle, though the pill comes
   in from its top). Only where there is a pointer to hover with: a finger would leave it lit */
.hf-peek::before { content: ""; position: absolute; inset: 0; border-radius: inherit; background: var(--hi); opacity: 0; pointer-events: none; transition: opacity .12s var(--oe); }
@media (hover: hover) {
  .hf.is-peek .hf-peek:hover { transform: translateY(-.65px) scale(1.05); }
  .hf.is-peek .hf-peek:hover::before { opacity: .057; }
}
.hf-peek::after { content: ""; position: absolute; inset: -6px -8px -9px; }      /* (a finger's worth of room to hit; short of the face above it, 7 away) */
.hf-peek-ico { position: relative; flex: none; width: 11px; height: 11px; color: var(--hi2); }
.hoy .hf-peek svg { position: absolute; inset: 0; transition: opacity .18s var(--oe), scale .22s var(--oe); }
.hf-peek .pk-tick, .hf-peek.is-copied .pk-copy { opacity: 0; scale: .5; }
.hf-peek.is-copied .pk-tick { opacity: 1; scale: 1; }
/* active now: a thin ring going out from the face, like sonar (the app's ActivityPulseRing: from the face's edge to
   1.22 times its size in 2.5s, strongest, .64, a fifth of the way there, and again). On whoever is active (`is-live`,
   hoy.js) until that face is held or open, as in the app. It is this face's own, so it passes over the face to its
   right and under the one to its left, whose outline cuts it. Not live, the ring stands still and fades with its
   box, and takes up where it was */
.hf-sonar { position: absolute; inset: -4px; pointer-events: none; opacity: 0; transition: opacity .3s var(--oe); }
.hf.is-live .hf-sonar { opacity: 1; }
.hf-sonar i { position: absolute; inset: 4px; border-radius: 50%; border: .5px solid var(--hp); opacity: 0; }      /* (half the app's 1pt: at the film's sizes 1pt reads as a band) */

/* the card: one glass surface, 344 wide, hanging 8 under the strip ----------------- */
.hc { position: absolute; left: -172px; top: 40px; width: 344px; height: var(--h, 168px); visibility: hidden; opacity: 0; scale: .97; transform-origin: 50% -24px; transition: opacity .2s cubic-bezier(0, 0, .58, 1), scale .2s cubic-bezier(0, 0, .58, 1), visibility 0s .2s; }
.hc.is-on { visibility: visible; opacity: 1; scale: 1; transition: none; }
.hc.is-launch, .hc.is-grow { transition: height var(--t-launch, .5s) var(--e-launch, var(--ease)); }   /* growing into a channel, and for a drop of your own; otherwise its height snaps */
.hc-glass { position: absolute; inset: 0; border-radius: 42px; background: var(--hglass); box-shadow: var(--card-lift); opacity: 0; }
/* the light its glass catches inside its edges, over the ambient glow and under the rim */
.hc-glass::after { content: ""; position: absolute; inset: 0; border-radius: inherit; box-shadow: var(--card-sheen); pointer-events: none; }
/* --free runs 0 to 1 as the camera goes in: the glass, the header, the composer and the strip go, the drops stay */
.hc.has-glass .hc-glass { opacity: calc(1 - var(--free, 0)); }
.hc-glass::before { content: ""; position: absolute; inset: 0; z-index: 1; border-radius: inherit; padding: 1px; background: var(--card-rim); -webkit-mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0); mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0); pointer-events: none; }
/* ambient theme (Pro): the glass glows in the four corner colours of the channel's face. The app draws that as a
   mesh; hoy.js paints the same mesh into this small picture (`light`, `paintGlow`), which is stretched over the card
   and takes its strength from there too */
.hc-glow { position: absolute; inset: 0; width: 100%; height: 100%; border-radius: inherit; opacity: 0; }

.hc-in { position: absolute; inset: 0; display: grid; grid-template-rows: auto minmax(0, 1fr) auto; gap: 8px; padding: 12px; }
.hc:not(.has-in) .hc-in { opacity: 0; pointer-events: none; }
/* growing into a channel: the header is there at once, the thread and the composer come a beat later (under a name
   of its own, so it plays even when the card has only just opened as the catcher and that reveal is still on) */
.hc.is-opening .hh, .hc.is-opening .ht, .hc.is-opening .hm { animation: hc-reveal .3s cubic-bezier(0, 0, .58, 1) .2s backwards; }
.hc.is-launch .ht, .hc.is-launch .hm { animation: hc-launch .3s cubic-bezier(0, 0, .58, 1) .2s backwards; }
@keyframes hc-reveal { from { opacity: 0; } }
@keyframes hc-launch { from { opacity: 0; } }
/* a picture let go on a face lands in the thread from under the pointer (hoy.js): for that moment nothing clips it,
   it flies over the composer, and it is there from the first frame, while its time line and the face beside it
   come the beat later */
.hc.is-landing .ht { z-index: 1; overflow: visible; animation: none; }
.hc.is-landing .htm, .hc.is-landing .hd-face { animation: hc-launch .3s cubic-bezier(0, 0, .58, 1) .2s backwards; }

/* the header: the face, the name over its line, and the corners that open the window */
.hh { display: flex; align-items: center; gap: 10px; height: 40px; padding: 0 6px; opacity: calc(1 - var(--free, 0)); }
.hh-face { flex: none; width: 28px; height: 28px; border-radius: 50%; overflow: hidden; background: #8e8e93; }
.hh-who { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.hh-name { font: 600 13px/16px var(--sans); color: var(--hi); }
.hh-line { font: 400 11px/13px var(--sans); color: var(--hi2); }
.hh-btn { flex: none; width: 28px; height: 28px; padding: 6px; border-radius: 50%; color: var(--hp); opacity: .9; }

/* the thread: yours on the right, theirs on the left. While its drops fit they sit from the top, so the card
   growing for a new one never moves the older ones; with more than fit, the newest is on the bottom edge. Its soft
   edges reach 8 past the box, to the header and to the composer, so shadows are never cut in a line.
   It is clipped, never scrollable: as a scroll box Safari keeps the older drops in view when a new one lands
   (it scrolls the box up by the new drop's height), and the newest would arrive out of sight */
.ht { position: relative; display: flex; flex-direction: column; justify-content: flex-start; min-height: 0; margin-block: -8px; padding-block: 8px; overflow: hidden; overflow: clip; }
.ht.is-over { justify-content: flex-end; -webkit-mask: linear-gradient(#0000, rgb(0 0 0 / .043) 4.5px, rgb(0 0 0 / .156) 9px, rgb(0 0 0 / .316) 13.5px, rgb(0 0 0 / .5) 18px, rgb(0 0 0 / .684) 22.5px, rgb(0 0 0 / .844) 27px, rgb(0 0 0 / .957) 31.5px, #000 36px); mask: linear-gradient(#0000, rgb(0 0 0 / .043) 4.5px, rgb(0 0 0 / .156) 9px, rgb(0 0 0 / .316) 13.5px, rgb(0 0 0 / .5) 18px, rgb(0 0 0 / .684) 22.5px, rgb(0 0 0 / .844) 27px, rgb(0 0 0 / .957) 31.5px, #000 36px); }
/* with the glass gone the drops are free of their box: older ones run on up the page */
.hc.is-free .ht { justify-content: flex-end; overflow: visible; -webkit-mask: none; mask: none; }
.ht-list { position: relative; flex: none; display: flex; flex-direction: column; margin: 0; padding: 0; list-style: none; }      /* (a drop on its way out is pinned to it where it stood) */
.ht-list[hidden], .hd[hidden], .hm [hidden] { display: none; }
.hd { display: flex; align-items: flex-start; gap: 10px; max-width: 280px; margin-top: 24px; }
.ht-list > :first-child { margin-top: 0; }
/* a drop that carries on a burst: 10 under the one before it, no face again, the face's gutter kept */
.hd--more { margin-top: 10px; padding-right: 38px; }
.hd--more .hd-body { padding-top: 0; }
/* a time line: when a burst was dropped, centred above it. The day's first names the day; after an hour's pause,
   the time alone. As quiet as the app's: caption, medium, the tertiary label. No time on every drop */
.htm { align-self: stretch; margin-top: 34px; font: 500 12px/15px var(--sans); font-variant-numeric: tabular-nums; text-align: center; color: var(--hs3); }
.hd--me { align-self: flex-end; justify-content: flex-end; }
.hd-face { flex: none; width: 28px; height: 28px; border-radius: 50%; overflow: hidden; background: #8e8e93; }
.hd-body { min-width: 0; display: flex; flex-direction: column; gap: 4px; align-items: flex-start; padding-top: 9.33px; }
.hd--me .hd-body { align-items: flex-end; }

/* a drop: a raised tile */
.hb { position: relative; max-width: 242px; border-radius: 22px; background: var(--htile); box-shadow: var(--tile-lift), inset 0 0 0 .5px var(--hrim); overflow: hidden; transition: color .25s cubic-bezier(.42, 0, .58, 1); }
.hb--note { padding: 7.5px 12px 8.5px; line-height: 20px; }
.hb--note p { margin: 0; }
/* a to-do: the dotted circle, then the tick and a line through it */
.hb--todo p { display: flex; align-items: baseline; gap: 6px; transition: color .2s cubic-bezier(0, 0, .58, 1); }
.ho { flex: none; position: relative; top: 2px; width: 13.5px; height: 13.5px; border-radius: 50%; border: 1.2px dotted currentColor; }
.hb--todo p.is-done { color: var(--hi2); }
.hb--todo p.is-done .ho { border: 0; background: currentColor; }
.ho svg { display: none; position: absolute; left: 50%; top: 50%; width: 7.4px; height: 7.2px; margin: -3.5px 0 0 -3.7px; fill: var(--htile-solid); }
.hb--todo p.is-done .ho svg { display: block; }
.hb--todo p span { background: linear-gradient(currentColor, currentColor) 0 58% / 0 1px no-repeat; transition: background-size .28s cubic-bezier(0, 0, .58, 1) .08s; }
.hb--todo p.is-done span { background-size: 100% 1px; }
/* one photo: its own shape, lit along the top */
/* (the picture: the tiles' lift without the contact shadow, one shadow as hoy.js flies it in with. The picture is
   rounded itself and the tile does not clip: in Safari a square box showed behind its round corners) */
.hb--photo { width: 242px; background: var(--hbed); box-shadow: 0 4px 14px -3px rgb(0 0 0 / .11); overflow: visible; }
.hb--photo picture, .hb--photo img { border-radius: inherit; }
.hb--photo img { aspect-ratio: 3 / 2; }
.hb--photo::after { content: ""; position: absolute; inset: 0; border-radius: inherit; padding: 1px; background: var(--rim); -webkit-mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0); mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0); pointer-events: none; }
/* a take: its picture, with its time on a chip */
.hb--take { width: 242px; }
.hv { position: relative; aspect-ratio: 4 / 3; background: var(--hbed); overflow: hidden; }
.hv-time { position: absolute; right: 8px; bottom: 8px; display: flex; align-items: center; gap: 4px; padding: 3px 7px; border-radius: 99px; background: rgb(0 0 0 / .5); font: 400 10px/13px var(--sans); font-variant-numeric: tabular-nums; color: #fff; transition: opacity .18s; }
/* its glyph: play (SF Symbols play.fill and pause.fill, at the chip's 10pt) while the take rests, with its
   length beside it; pause while it plays (is-run, hoy.js), with the time running. One takes the other's place */
.hv-mark { position: relative; flex: none; width: 7.29px; height: 8.2px; }
.hoy .hv-mark svg { position: absolute; left: 50%; top: 50%; translate: -50% -50%; transition: opacity .2s var(--oe), scale .3s var(--oe); }
.hoy .hv-play { width: 8.49px; height: 9.4px; }
.hoy .hv-pause { width: 7.16px; height: 9.28px; }
.hv:not(.is-run) .hv-pause, .hv.is-run .hv-play { opacity: 0; scale: .4; }
/* a screen take: the desktop he shows (Monocle's, off its own site), the pointer going over it and his face floating
   along, as if he were explaining it. hoy.js moves them with the scroll: --ox/--oy is where the pointer is, and the
   picture is pushed in about that very point, so the pointer never slides off what it points at */
.hv--screen { aspect-ratio: 16 / 10; background: #c9d6d2; }
.sc-desk { position: absolute; inset: 0; transform-origin: var(--ox, 50%) var(--oy, 50%); scale: var(--sk, 1); }
/* what is in the screen sits in one box (.sc-q). In Safari, when the camera shows the screen bigger than it is, that
   box is laid out --qs times bigger and scaled back down as a layer of its own (is-q), so Safari paints it at the
   size it shows at; what is measured in points in it grows with it. Elsewhere --qs is never set and the box is
   simply the screen's own */
.sc-q { position: absolute; left: 0; top: 0; width: calc(100% * var(--qs, 1)); height: calc(100% * var(--qs, 1)); transform-origin: 0 0; }
.sc-q.is-q { transform: scale(calc(1 / var(--qs))); will-change: transform; }
.hv--screen .hv-time { zoom: var(--qs, 1); }
.hoy .sc-cur { position: absolute; left: var(--ox, 50%); top: var(--oy, 50%); width: calc(7px * var(--qs, 1)); height: calc(9.8px * var(--qs, 1)); margin: calc(-.4px * var(--qs, 1)) 0 0 calc(-.4px * var(--qs, 1)); filter: drop-shadow(0 calc(.5px * var(--qs, 1)) calc(1px * var(--qs, 1)) rgb(0 0 0 / .35)); }
.sc-me { position: absolute; left: var(--mx, 62%); top: var(--my, 62%); width: 15%; aspect-ratio: 1; margin: -7.5% 0 0 -7.5%; border-radius: 50%; overflow: hidden; background: #8e8e93; box-shadow: 0 0 0 calc(1.2px * var(--qs, 1)) rgb(255 255 255 / .92), 0 calc(3px * var(--qs, 1)) calc(10px * var(--qs, 1)) rgb(0 0 0 / .32); }
.hv--screen .hv-time b { font-weight: 400; }
/* while it plays, filling the stage (--near), it is alone there: the other drops, the time lines and the face
   beside it make way, and come back as the camera does. Its time chip stays, counting; it is part of the drop and
   grows with it as the camera goes in */
.ht-list > :not([data-id="screen"]), .hd[data-id="screen"] .hd-face { opacity: calc(1 - var(--near, 0)); }
.hv--screen .hv-time { right: auto; left: 8px; }

/* the composer: a glass tile with a note field, the chips and Drop ----------------- */
/* (its shadow stays inside the card: the composer sits 12 from the card's foot and sides, and what fell past them
   lay on the card's own shadow, a dark band under it) */
.hm { position: relative; opacity: calc(1 - var(--free, 0)); clip-path: inset(-48px -12px -12px round 0 0 42px 42px); }
.hm-bed { position: relative; display: flex; flex-direction: column; padding: 20px; border-radius: 30px; background: rgb(255 255 255 / .62); box-shadow: var(--glass-lift), inset 0 0 24px rgb(255 255 255 / .3), inset 0 0 0 .75px rgb(255 255 255 / .6), 0 0 0 .5px rgb(0 0 0 / .05); }
@media (prefers-color-scheme: dark) {
  .hm-bed { background: rgb(255 255 255 / .15); box-shadow: var(--glass-lift), inset 0 0 24px rgb(255 255 255 / .1), inset 0 0 0 .75px rgb(255 255 255 / .2), 0 0 0 .5px rgb(0 0 0 / .18); }
}
.hm-field { position: relative; margin: 0 0 12px; padding: 0 10px; min-height: 16px; font: 400 13.5px/16px var(--sans); color: var(--hi); }
.hm-ph { color: var(--hs2); }
.hm-text { white-space: pre-wrap; }                  /* a space just typed keeps the caret after it */
.hc[data-channel="new"] .hm-ph { opacity: .5; }
.hm.is-typed .hm-ph { display: none; }
.hm-caret { display: none; position: absolute; left: 9px; top: .5px; width: 1.5px; height: 15px; background: var(--hp); border-radius: 1px; animation: hm-blink 1.1s steps(1) infinite; }
.hm.is-focus .hm-caret { display: block; }
/* with words in the field the caret stands after the last of them, and holds still while they are being typed */
.hm.is-typed .hm-caret { position: relative; left: auto; top: auto; display: none; vertical-align: top; margin: .5px 0 0 1px; }
.hm.is-typed.is-focus .hm-caret { display: inline-block; }
.hm.is-typing .hm-caret { animation: none; }
@keyframes hm-blink { 50% { opacity: 0; } }
.hm-row { display: flex; align-items: center; gap: 4px; height: 28px; }
.hm-chip { flex: none; display: grid; place-items: center; width: 28px; height: 28px; border-radius: 50%; color: var(--hp); opacity: .9; }
/* its glyph is an SF Symbol at 13pt, Semibold: each at its own outline's size (drawn at 100pt, so x .13), the
   outline's room round it included */
.hoy .hm-wave { width: 14.39px; height: 12.48px; }
.hoy .hm-rec { width: 15.32px; height: 15.32px; }
.hoy .hm-plus { width: 12.82px; height: 12.82px; }
.hoy .hm-video { width: 18.13px; height: 12.81px; }
.hoy .hm-trash { width: 13px; height: 13px; }
.hc[data-channel="new"] .hm-chip { opacity: .4; }
.hm-chip--trash, .hc[data-channel="me"] .hm-chip--video { display: none; }
.hm-drop { margin-left: auto; display: flex; align-items: center; gap: 6px; height: 28px; padding: 0 10px; border-radius: 14px; background: rgb(0 0 0 / .068); font: 400 13px/16px var(--sans); color: rgb(0 0 0 / .34); transition: background-color .12s cubic-bezier(0, 0, .58, 1), color .12s cubic-bezier(0, 0, .58, 1), scale .12s cubic-bezier(0, 0, .58, 1); }
@media (prefers-color-scheme: dark) { .hm-drop { background: rgb(255 255 255 / .068); color: rgb(255 255 255 / .34); } }
.hm-drop b { font-weight: 400; }
.hm-drop u { font-size: 11px; text-decoration: none; }
.hm.is-ready .hm-drop, .hc[data-channel="new"] .hm-drop { background: var(--hacc); color: rgb(255 255 255 / .9); }
.hm.is-ready .hm-drop u { color: rgb(255 255 255 / .4); }
.hc[data-channel="new"] .hm-drop u { display: none; }
.hm-drop.is-down { scale: .97; }

/* a take while it is being said (hold a face): the card is only its bars, the time and the words as they come.
   The app's also has the language and Stop; left out here */
.tk { position: absolute; inset: 0 0 auto; padding: 24px 32px 26px; opacity: 0; visibility: hidden; }
.hc.is-take .tk { opacity: 1; visibility: visible; transition: opacity .2s cubic-bezier(0, 0, .58, 1) .15s; }
.tk-row { display: flex; align-items: center; gap: 14px; height: 28px; }
.tk-bars { flex: 1; min-width: 0; height: 20px; display: flex; align-items: center; justify-content: space-between; -webkit-mask: linear-gradient(90deg, #0000, #000 28px calc(100% - 28px), #0000); mask: linear-gradient(90deg, #0000, #000 28px calc(100% - 28px), #0000); }
.tk-bars i { flex: none; width: 2px; height: 2px; border-radius: 1px; background: var(--hs2); transition: height .12s linear; }
.tk-time { flex: none; font: 400 13px/16px var(--sans); font-variant-numeric: tabular-nums; color: var(--hp); opacity: .9; }
/* its words sharpen in from a blur as they are said, the live transcript's own reveal */
.tk-words { margin: 10px 0 0; font: 400 13px/18px var(--sans); color: var(--hi2); }
.tk-words span { display: inline-block; white-space: pre; opacity: 0; filter: blur(2.2px); translate: 0 1.5px; transition: opacity .5s var(--oe), filter .5s var(--oe), translate .5s var(--oe); }
.tk-words span.is-said { opacity: 1; filter: none; translate: 0 0; }

/* under a drop: its reactions (ReactionChips: someone else's is a hairline capsule, 22 high, in from .6 on its
   spring), and its reminder (ReminderLine: a bell and "Reminder tomorrow, 9:00", only yours to see). Both have their
   room from the start, so nothing in the thread moves as they come */
.rx { display: flex; gap: 4px; height: 22px; margin: 0; }
.rx-chip { display: grid; place-items: center; height: 22px; padding: 0 7px; border-radius: 11px; box-shadow: inset 0 0 0 1px var(--hline); font: 400 12px/1 var(--sans); opacity: 0; scale: .6; transition: opacity .12s var(--oe), scale .12s var(--oe); }
.rx-chip.is-on { opacity: 1; scale: 1; transition: opacity .15s var(--oe), scale var(--t-rx, .4s) var(--e-rx, var(--ease)); }
.rl { display: flex; align-items: center; gap: 6px; height: 15px; margin: 0; padding: 0 6px; font: 400 12px/15px var(--sans); color: var(--hi2); opacity: 0; translate: 0 -3px; transition: opacity .25s var(--oe), translate .3s var(--oe); }
.rl.is-on { opacity: 1; translate: 0 0; }
.hoy .rl svg { flex: none; width: 10.5px; height: 11.5px; }
/* a number changing, as in the app (numericText on the snappy spring): only the glyph that changed rolls, out one
   way and in from the other through a blur; up when it counts up, down when it counts down (hoy.js) */
.rd { position: relative; display: inline-block; }
.rd > i { display: inline-block; font-style: normal; }
.rd > .is-out { position: absolute; left: 0; top: 0; }

/* the catcher: a grille of dots and one small label ------------------------------ */
.hk { position: absolute; inset: 0 0 auto; height: 168px; border-radius: 42px; overflow: hidden; opacity: 0; visibility: hidden; transition: opacity .22s, visibility 0s .22s; }
.hc.is-catch .hk { opacity: 1; visibility: visible; transition: opacity .2s cubic-bezier(0, 0, .58, 1) .15s; }
/* the field is drawn at the screen's own pixels, at the closest the camera comes (--kz): sized up here and scaled
   back, so the dots stay sharp */
.hk-field { position: absolute; left: 0; top: 0; width: calc(344px * var(--kz)); height: calc(168px * var(--kz)); transform: scale(calc(1 / var(--kz))); transform-origin: 0 0; color: var(--hi); }
.hk-label { position: absolute; left: 24px; right: 24px; top: 50%; height: 15px; margin-top: -7.5px; display: grid; justify-items: center; font: 500 12px/15px var(--sans); color: var(--hi2); transition: color .12s cubic-bezier(0, 0, .58, 1); }
.hk.is-armed .hk-label { color: var(--hi); }
.hk-name { grid-area: 1 / 1; white-space: nowrap; }

/* scrolling back ------------------------------------------------------------------ */
/* a card goes back into the dot it grew from: what it holds fades first (hoy.js shrinks the glass) */
.hc.is-closing .tk, .hc.is-closing .hk { opacity: 0; transition: opacity .1s cubic-bezier(0, 0, .58, 1); }
/* over the drop, the channel folds into the catcher again: what it held fades at once, but the thread stays for that
   moment, unclipped and over everything, while its picture flies back under the pointer (hoy.js); until it is there,
   the pointer carries nothing */
.hc.is-folding .hc-in { opacity: 1; }
.hc.is-folding .hh, .hc.is-folding .hm, .hc.is-folding .htm, .hc.is-folding .hd-face { opacity: 0; transition: opacity .15s cubic-bezier(0, 0, .58, 1); }
.hc.is-folding .ht { z-index: 1; overflow: visible; -webkit-mask: none; mask: none; }
.fly.is-back .fly-pic { visibility: hidden; }

/* things in the air: the picture that gets dropped, and the pointer carrying it ------ */
.fly { position: absolute; z-index: 5; left: 0; top: 0; width: 0; height: 0; pointer-events: none; opacity: 0; transition: opacity .25s; will-change: transform; }
.fly.is-on { opacity: 1; }
.fly.is-hold .fly-pic { display: none; }
.fly-pic, .fly-ptr { position: absolute; left: 0; top: 0; }
.fly-pic { width: calc(66px * var(--kz, 1.3)); padding: 3px; margin: calc(-28px * var(--kz, 1.3)) 0 0 calc(-42px * var(--kz, 1.3)); border-radius: 6px; background: #fff; box-shadow: 0 0 0 .5px rgb(0 0 0 / .12), 0 16px 32px -8px rgb(0 0 0 / .35); rotate: -4deg; }
.fly-pic img { display: block; width: 100%; height: auto; border-radius: 3.5px; }
.fly-ptr { width: 17px; height: 24px; margin: -1px 0 0 -1px; transform-origin: 2px 2px; filter: drop-shadow(0 1px 2px rgb(0 0 0 / .3)); }
.fly.is-press .fly-ptr { scale: .88; }      /* pressed: holding a face, or carrying the file (hoy.js adds the dip and the release) */

/* ------------------------------------------------------------------ */
/* phone                                                               */
/* ------------------------------------------------------------------ */
@media (max-width: 720px) {
  .film-pin { padding-top: 96px; }
  .js .hello { top: 45%; }
}

/* ------------------------------------------------------------------ */
/* motion                                                              */
/* ------------------------------------------------------------------ */
@media (prefers-reduced-motion: no-preference) {
  .hf-sonar i { animation: hf-sonar-s 2.5s cubic-bezier(0, 0, .58, 1) infinite paused, hf-sonar-o 2.5s infinite paused; }
  .hf.is-live .hf-sonar i { animation-play-state: running; }
}
@media (prefers-reduced-motion: reduce) {
  .hf-sonar i { scale: 1.11; opacity: .32; }
}
/* his own face at the hello is alive too, from the moment it is up: the same ring at that face's size (a 50th of it
   wide, as the bar's half point is of a 25pt face), until it is the highlighted face in the menu bar (the hello's is hidden
   then, and its ring stands still) */
.js .hello-sonar { display: block; position: absolute; inset: 0; border-radius: 50%; border: calc(var(--fs) * .059) solid var(--ink); opacity: 0; pointer-events: none; }
@media (prefers-reduced-motion: no-preference) {
  .js .hello-sonar { animation: hf-sonar-s 2.5s cubic-bezier(0, 0, .58, 1) 1.6s infinite, hf-sonar-o 2.5s 1.6s infinite; }
  .js .hello.is-landed .hello-sonar { animation-play-state: paused; }
}
