/* One sheet for every page. Nothing from another host and no script written into a page:
   the security headers allow neither. The scripts are player.js, for the clips, shots.js,
   for the pictures, and support.js, for the support form. Plain
   pages: one column of text, a rule where a part ends, nothing drawn for its own sake. */
:root {
    color-scheme: dark light;
    --bg: #0e1116;
    --text: #d8dce3;
    --dim: #8f97a5;
    --rule: #2a313c;
    --accent: #6aa5ff;
    --mark: #8fe0a8;
    --mark-bg: #16301f;
    --sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --mono: ui-monospace, "Cascadia Mono", "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
}
@media (prefers-color-scheme: light) {
    :root {
        --bg: #ffffff;
        --text: #1d2229;
        --dim: #5f6873;
        --rule: #dde1e7;
        --accent: #1f62d0;
        --mark: #17642f;
        --mark-bg: #dcf3e3;
    }
}

* { box-sizing: border-box; }
/* No grey flash from the browser on what is pressed, as links already have none. */
button, input { -webkit-tap-highlight-color: transparent; }
button { user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; }
.clip img { -webkit-user-drag: none; pointer-events: none; }
/* The page stays where it is while a clip is open over it; the gutter is kept, so nothing
   moves sideways when its scrollbar goes. */
html { -webkit-text-size-adjust: 100%; scrollbar-gutter: stable; }
html:has(.player:popover-open, .shot:popover-open) { overflow: hidden; }
body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
    font: 16px/1.55 var(--sans);
}
.wrap { max-width: 720px; margin: 0 auto; padding: 0 20px 40px; }
a { color: var(--accent); text-decoration: none; -webkit-tap-highlight-color: transparent; }
a:hover, a:focus-visible { text-decoration: underline; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

header.top {
    padding: 20px 0;
}
.brand { display: block; color: var(--text); }
.brand svg { display: block; }

main { padding: 24px 0 0; }
h1, h2, h3 { line-height: 1.25; margin: 0; font-weight: 600; }
h1 { font-size: 22px; margin-bottom: 8px; }
h2 { font-size: 21px; margin: 36px 0 16px; padding-bottom: 8px; border-bottom: 1px solid var(--rule); }
h3 { font-size: 17px; margin: 24px 0 4px; }
p, ul { margin: 0 0 1em; }
ul { padding-left: 1.2em; }
li { margin-bottom: 0.35em; }
.when { color: var(--dim); font-size: 15px; font-style: italic; margin-bottom: 20px; }
code { font: 0.92em var(--mono); }

/* The list of apps on the home page: the whole of an entry is its link. */
.apps { list-style: none; padding: 0; margin: 28px 0 0; }
.apps li { padding: 0 0 20px; }
.apps a { display: flex; gap: 16px; align-items: flex-start; color: var(--text); text-decoration: none; }
.apps a:hover b, .apps a:focus-visible b { text-decoration: underline; }
.apps img { display: block; width: 48px; height: 48px; flex: none; }
.apps b { display: block; font-size: 18px; font-weight: 400; line-height: 1; margin-top: -2px; }
/* The name's top on the icon's top edge: trimmed to the cap height where the browser can,
   nudged up by the usual leading where it cannot. */
@supports (text-box-trim: trim-start) {
    .apps b { text-box-trim: trim-start; text-box-edge: cap alphabetic; margin-top: 0; }
}
/* What an app runs on, marked at the entry's right end, on its name's line. Taller than the
   trimmed name, so it gives its extra height back and the name stays on the icon's top edge. */
.apps a > div { flex: 1; min-width: 0; }
.apps .name { display: flex; align-items: center; gap: 10px; }
.apps .name b { margin-right: auto; }
.apps .on {
    font-size: 12px;
    font-weight: 600;
    line-height: 1;
    color: var(--mark);
    background: var(--mark-bg);
    padding: 3px 6px;
    margin: -4px 0;
}
/* Its price, after them: outlined, so it does not read as one more thing it runs on. */
.apps .price { background: none; box-shadow: inset 0 0 0 1px var(--mark); margin-left: -2px; }
.apps p { margin: 6px 0 0; color: var(--dim); font-size: 15px; line-height: 1.5; }

/* A product's name beside its icon. */
/* The same shape as an entry on the home page: icon, name, one line. */
.product { display: flex; gap: 16px; align-items: flex-start; }
.product img { display: block; width: 48px; height: 48px; flex: none; }
.product h1 { font-size: 18px; font-weight: 400; line-height: 1; margin: -2px 0 0; }
@supports (text-box-trim: trim-start) {
    .product h1 { text-box-trim: trim-start; text-box-edge: cap alphabetic; margin-top: 0; }
}
.product p { margin: 6px 0 0; color: var(--dim); font-size: 15px; line-height: 1.5; }
/* The version that is out and its day, under the line that says what the product is. */
.product .version { margin-top: 2px; font-size: 14px; }

/* What the product is, under its name: plain paragraphs before the features. */
.about { margin-top: 28px; }
.about p:last-child { margin-bottom: 0; }
/* Under them, four pictures of a phone's screen, each a part of it cut to one shape: in a
   row on a wide screen, two by two on a narrow one. A press opens them at their own size
   over the page, as a popover: one row of pictures, a screen wide each, swiped sideways
   from one to the next. shots.js opens the row at the picture that was pressed and moves
   it with the arrow keys; without it the row opens at the first and is still swiped. */
.shots { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin-top: 20px; }
.shots button { display: block; padding: 0; border: 0; background: #000; box-shadow: 0 0 0 1px var(--rule); cursor: zoom-in; }
.shots img { display: block; width: 100%; height: auto; -webkit-user-drag: none; }
@media (max-width: 520px) {
    .shots { grid-template-columns: repeat(2, 1fr); }
}
.shot { width: min(92vw, 720px); padding: 0; border: 0; background: #181d25; color: #d8dce3; box-shadow: 0 24px 70px rgb(0 0 0 / 0.7); }
.shot::backdrop { background: rgb(0 0 0 / 0.72); backdrop-filter: blur(3px); }
.reel {
    display: flex;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
    user-select: none;
    -webkit-user-select: none;
}
.reel::-webkit-scrollbar { display: none; }
.reel:focus { outline: none; }
.reel figure { flex: 0 0 100%; margin: 0; scroll-snap-align: start; scroll-snap-stop: always; }
.reel img { display: block; width: 100%; height: auto; -webkit-user-drag: none; }
.reel figcaption { padding: 12px 14px; font-size: 14px; }

/* The features: a column of names as wide as the widest, each marked over its own letters
   alone, and what each says beside it. On a narrow screen a name sits over its paragraph. */
/* The features follow the paragraph with no heading: they rule themselves off. */
.about ~ .points { margin-top: 36px; }
.points { display: grid; grid-template-columns: max-content 1fr; gap: 14px 16px; align-items: baseline; }
.points > b {
    justify-self: start;
    font-weight: 600;
    line-height: 1.3;
    color: var(--mark);
    background: var(--mark-bg);
    padding: 0 7px 2px;
    /* Out by its own padding, so its letters stand level with the paragraph above. */
    margin-left: -7px;
}
.points > p { margin: 0; }
/* On a screen with room beside the column the names stand out in the margin, and what each
   says is as wide as the paragraph above and starts on its left edge: the second column
   takes the whole width, and the grid, held to its right end, runs out to the left. */
@media (min-width: 1040px) {
    .points { grid-template-columns: max-content 100%; justify-content: end; }
    .points > b { margin-left: 0; }
}
/* A feature shown on a phone: a still under its paragraph, which opens the clip over the
   page. A popover, since no script may run here: the browser opens it, and closes it on
   Esc, on Back and on a press outside. */
.points .clip {
    grid-column: -2;
    position: relative;
    display: block;
    width: 100%;
    padding: 0;
    border: 0;
    margin-bottom: 10px;
    background: #000;
    cursor: pointer;
}
/* The still is softened and dimmed a little: it reads as what is behind the play mark, not
   as a screenshot cut off mid-line. Scaled a touch, so its blurred edges are out of the box. */
.points .clip { overflow: hidden; }
.clip img { display: block; width: 100%; height: auto; filter: blur(0.5px) brightness(0.8); transform: scale(1.01); }
/* The play mark over the still. */
.clip::before, .clip::after { content: ""; position: absolute; top: 50%; left: 50%; z-index: 1; }
.clip::before {
    width: 56px;
    height: 56px;
    margin: -28px 0 0 -28px;
    border-radius: 50%;
    background: rgb(0 0 0 / 0.62);
    box-shadow: 0 0 0 1.5px rgb(255 255 255 / 0.85);
}
.clip::after {
    margin: -10px 0 0 -6px;
    border: solid transparent;
    border-width: 10px 0 10px 17px;
    border-left-color: #fff;
}
@media (hover: hover) {
    .clip:hover::before { background: rgb(0 0 0 / 0.8); }
}
.clip:focus-visible::before { background: rgb(0 0 0 / 0.8); }
/* A feature's clips, under its paragraph. One clip is a single button, PLAY. A feature with
   parts gets a table of them: PLAY first, filled, for the feature as a whole, then a cell
   for each part that has a clip of its own; cells of one width in as many columns as fit,
   ruled apart, each tall enough to press and taller where a finger does the pressing.
   Written on one line in the page, so a feature with no clip leaves a box that is empty
   and takes no room. */
.points .parts { grid-column: -2; display: flex; margin: -4px 0 10px; }
.points .parts:empty { display: none; }
.parts button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-height: 30px;
    margin: 0;
    padding: 0 12px;
    border: 0;
    font: 600 13px/1.2 var(--sans);
    text-align: center;
    color: var(--mark);
    background: none;
    box-shadow: 0 0 0 1px var(--rule);
    cursor: pointer;
}
.parts button::before {
    content: "";
    flex: none;
    border: solid transparent;
    border-width: 5px 0 5px 8px;
    border-left-color: currentColor;
}
.parts .play:not(.part) { font-size: 12px; letter-spacing: 0.04em; background: var(--mark-bg); }
/* One play mark for a feature, on PLAY: the cells beside it are its parts by name alone. */
.parts .part::before { content: none; }
/* Hover is for a pointer that hovers. A finger leaves hover behind on what it pressed, which
   would show, and then go, as the player it opened closes. */
@media (hover: hover) {
    .parts button:hover { background: var(--mark-bg); }
}
.parts button:focus-visible { background: var(--mark-bg); }
/* The cells stand apart, inside a pixel of room for their outlines. On a wide screen each
   is as wide as its name, in as many rows as they need. */
.points .parts:has(.part) { gap: 8px; padding: 1px; }
@media (min-width: 521px) {
    .points .parts:has(.part) { flex-wrap: wrap; }
}
@media (pointer: coarse) {
    .parts button { min-height: 36px; padding: 0 14px; font-size: 14px; }
    .parts .play:not(.part) { font-size: 13px; }
}
/* On a narrow screen the row is swiped sideways, three whole cells in view at a time and
   none cut at the edge; a swipe stops on a cell's edge. An end of the row fades while there
   are more cells past it, left or right, where the browser can tell. */
@media (max-width: 520px) {
    .points .parts:has(.part) {
        display: flex;
        overflow-x: auto;
        overscroll-behavior-x: contain;
        scroll-snap-type: x mandatory;
        scrollbar-width: none;
    }
    .points .parts:has(.part)::-webkit-scrollbar { display: none; }
    .parts:has(.part) button {
        flex: 0 0 calc((100% - 16px) / 3);
        padding: 4px 8px;
        scroll-snap-align: start;
    }
    @supports (animation-timeline: scroll()) {
        .points .parts:has(.part) {
            mask-image: linear-gradient(to right, transparent, #000 var(--fade-left),
                #000 calc(100% - var(--fade-right)), transparent);
            animation: more linear both;
            animation-timeline: scroll(self inline);
        }
    }
}
@property --fade-left { syntax: "<length>"; inherits: false; initial-value: 0px; }
@property --fade-right { syntax: "<length>"; inherits: false; initial-value: 0px; }
@keyframes more {
    from { --fade-left: 0px; --fade-right: 28px; }
    8%, 92% { --fade-left: 28px; --fade-right: 28px; }
    to { --fade-left: 28px; --fade-right: 0px; }
}
/* Dark in both themes, as the clips are, and marked in the features' green. */
.player {
    --bg: #181d25;
    --text: #d8dce3;
    --dim: #8f97a5;
    --rule: #2a313c;
    --accent: #8fe0a8;
    /* How tall the clip may be: most of the window, when it plays without player.js. */
    --room: 86vh;
    /* Every clip plays in a frame of one shape, the tallest clip's, so every player is the
       same size; a shorter clip stands in the middle of it. */
    --frame-wide: 720;
    --frame-high: 1402;
    /* How wide it may be. */
    --across: 92vw;
    /* As wide as the clip's shape allows in the room there is, in whole pixels: the clip
       and what is under it then end on the same edge, where a clip sized by itself ends
       a fraction of a pixel off it. */
    width: min(var(--across), calc(var(--room) * var(--frame-wide) / var(--frame-high)));
    width: round(down, min(var(--across), calc(var(--room) * var(--frame-wide) / var(--frame-high))), 1px);
    padding: 0;
    border: 0;
    overflow: visible;
    background: var(--bg);
    color: var(--text);
    box-shadow: 0 24px 70px rgb(0 0 0 / 0.7);
}
/* Nothing in the player is text to select or a picture to drag or hold: a press there
   plays, pauses or moves the clip, and must not leave a selection or call up a menu. */
.player, .player * { user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; }
.player video, .player .again { -webkit-user-drag: none; }
.player, .player * { -webkit-tap-highlight-color: transparent; }
.player:focus { outline: none; }
.player::backdrop { background: rgb(0 0 0 / 0.72); backdrop-filter: blur(3px); }
.player video {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: var(--frame-wide) / var(--frame-high);
    object-fit: contain;
    background: #000;
    cursor: pointer;
}
/* With player.js: nearly the whole window, less what is under the clip: the feature's
   name, the notes and the bar. */
.player.live { --room: calc(94vh - 154px); }
/* A phone's browser counts its own bars into `vh` while they hide and show; `dvh` is what
   can be seen now, so the player never reaches past the top. */
@supports (height: 1dvh) {
    .player { --room: 86dvh; }
    .player.live { --room: calc(94dvh - 154px); }
}
/* Which feature the clip is of, marked as its name is on the page. */
.player .label { display: none; margin: 0; padding: 12px 14px 0; border-top: 1px solid var(--rule); line-height: 1; }
.live .label { display: block; }
.label b { display: inline-block; padding: 3px 7px; font-size: 12px; font-weight: 600; color: var(--accent); background: #16301f; }
/* What a clip shows, said under it: one note at a time, the one for where the clip is.
   Its place keeps one height, so the bar does not move as notes change. */
.notes {
    display: none;
    position: relative;
    height: 74px;
    margin: 0;
    padding: 0;
    list-style: none;
}
.live .notes { display: block; }
.notes li {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    margin: 0;
    padding: 0 14px;
    font-size: 14px;
    line-height: 1.45;
    color: #b4bcc8;
    opacity: 0;
    transition: opacity 0.2s;
}
.notes li.on { opacity: 1; }
/* What a note is about stands out a little; what it quotes from the screen, a name or a
   state, is italic and in the bar's green. */
.notes b { font-weight: 600; color: #f2f4f7; }
.notes i { color: var(--accent); }
/* The bar player.js puts last: play or pause, where the clip is, how long it is. */
.player .bar {
    display: flex;
    align-items: center;
    gap: 10px;
    height: 46px;
    padding: 0 14px 0 6px;
    border-top: 1px solid var(--rule);
    /* A tone darker than the notes over it, so the two read as two things. */
    background: #0e1116;
}
.bar .toggle {
    flex: none;
    position: relative;
    width: 34px;
    height: 34px;
    padding: 0;
    border: 0;
    background: none;
    color: var(--text);
    cursor: pointer;
}
@media (hover: hover) {
    .bar .toggle:hover { color: var(--accent); }
}
.bar .toggle:focus-visible { color: var(--accent); }
/* Pause is two bars and play a triangle, each drawn as two halves of one box, so one turns
   into the other: the bars lean into the triangle's halves and back. */
.toggle::before, .toggle::after {
    content: "";
    position: absolute;
    top: 9px;
    left: 10px;
    width: 14px;
    height: 16px;
    background: currentColor;
    transition: clip-path 0.22s ease;
}
.toggle::before { clip-path: polygon(0 0, 30% 0, 30% 100%, 0 100%); }
.toggle::after { clip-path: polygon(70% 0, 100% 0, 100% 100%, 70% 100%); }
.paused .toggle::before { clip-path: polygon(0 0, 50% 25%, 50% 75%, 0 100%); }
.paused .toggle::after { clip-path: polygon(50% 25%, 100% 50%, 100% 50%, 50% 75%); }
/* While a clip waits at a note the button still says pause, and a ring closes around it:
   the clip goes on when the ring is whole. player.js sets how long that takes. */
.toggle svg { position: absolute; inset: 0; width: 34px; height: 34px; transform: rotate(-90deg); opacity: 0; }
.toggle circle { fill: none; stroke: var(--accent); stroke-width: 2; stroke-dasharray: 88; stroke-dashoffset: 88; }
.holding .toggle svg { opacity: 1; }
.holding .toggle circle { animation: hold var(--hold) linear forwards; }
@keyframes hold { to { stroke-dashoffset: 0; } }
/* A clip that has ended stays on its last picture, dimmed, under the offer to play it again.
   The offer covers the clip and nothing under it: the same width and the same shape. */
.player .again {
    position: absolute;
    top: 0;
    left: 0;
    display: none;
    width: 100%;
    aspect-ratio: var(--frame-wide) / var(--frame-high);
    padding: 0;
    border: 0;
    font: 600 12px/1 var(--sans);
    letter-spacing: 0.08em;
    color: #f2f4f7;
    background: rgb(0 0 0 / 0.55);
    cursor: pointer;
}
.ended .again { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; }
.again svg { width: 56px; height: 56px; fill: none; stroke: currentColor; stroke-width: 2; }
@media (hover: hover) {
    .again:hover { color: var(--accent); }
}
.again:focus-visible { color: var(--accent); }
/* The line the clip runs along, with a mark where each note begins. Three layers: the line
   itself, the marks over it, and over both the slider, of which only the handle is drawn. */
.bar .line { --at: 0%; flex: 1; min-width: 0; position: relative; height: 34px; }
.line::before {
    content: "";
    position: absolute;
    top: 15.5px;
    left: 0;
    right: 0;
    height: 3px;
    background: linear-gradient(to right, var(--accent) var(--at), var(--rule) var(--at));
}
.line .tick {
    position: absolute;
    top: 12px;
    width: 2px;
    height: 10px;
    margin-left: -1px;
    background: var(--dim);
    pointer-events: none;
    z-index: 1;
}
.line .tick.done { background: var(--accent); }
.bar .seek {
    /* Over the marks, so the handle is never under one. */
    position: relative;
    z-index: 2;
    display: block;
    width: 100%;
    height: 34px;
    margin: 0;
    padding: 0;
    background: none;
    -webkit-appearance: none;
    appearance: none;
    cursor: pointer;
}
.seek::-webkit-slider-runnable-track { height: 3px; background: none; }
.seek::-moz-range-track { height: 3px; background: none; }
.seek::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 11px;
    height: 11px;
    margin-top: -4px;
    border: 0;
    border-radius: 0;
    background: var(--accent);
}
.seek::-moz-range-thumb { width: 11px; height: 11px; border: 0; border-radius: 0; background: var(--accent); }
.bar .count { flex: none; font: 12px var(--mono); color: var(--dim); white-space: nowrap; }
/* For a screen reader alone: the note that shows, said as it changes. */
.player .spoken { position: absolute; width: 1px; height: 1px; margin: 0; overflow: hidden; clip-path: inset(50%); }
/* Closing: a round button beside the clip's top right corner, outside the player, so it
   is not taken for one of the player's own. */
.player .close {
    position: absolute;
    top: 0;
    left: calc(100% + 10px);
    width: 36px;
    height: 36px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: rgb(0 0 0 / 0.62);
    box-shadow: 0 0 0 1.5px rgb(255 255 255 / 0.85);
    cursor: pointer;
}
/* An upright phone: the clip is narrower by the button's width on each side, so the button
   still stands beside it, whole, and the clip stays in the middle. */
@media (max-aspect-ratio: 3/4) {
    .player { --across: calc(100vw - 92px); }
    .player .close { left: calc(100% + 5px); }
}
/* There it is the screen's height that sets the clip's size, so the player takes all of it:
   the feature's name, which the page behind has just said, is left out, and the clip is
   that much taller and wider. */
@supports (height: 1dvh) {
    @media (max-aspect-ratio: 3/4) {
        .player.live { --room: calc(100dvh - 131px); }
        .live .label { display: none; }
        .live .notes { border-top: 1px solid var(--rule); }
    }
}
.close::before, .close::after {
    content: "";
    position: absolute;
    top: 17px;
    left: 9px;
    width: 18px;
    height: 2px;
    background: #fff;
    transform: rotate(45deg);
}
.close::after { transform: rotate(-45deg); }
/* On a narrow screen there is no column for the names: each feature is a short section
   with its name as the heading over its paragraph, and a rule running from the name to
   the screen's edge at the middle of its height. */
@media (max-width: 520px) {
    .points { grid-template-columns: 1fr; gap: 0; }
    .points > b {
        justify-self: stretch;
        display: flex;
        align-items: center;
        gap: 12px;
        margin: 14px 0 0;
        padding: 0;
        font-size: 18px;
        line-height: 1.25;
        background: none;
    }
    .points > b::after { content: ""; flex: 1; height: 1px; background: var(--rule); }
    .points > b:first-child { margin-top: 0; }
    .points > p { margin: 6px 0 16px; }
    .points .parts { margin: -4px 0 18px; }
    .points .clip { margin-bottom: 18px; }
}

/* The licenses: each group of dependencies closed until it is opened. */
details { border-top: 1px solid var(--rule); }
details:last-of-type { border-bottom: 1px solid var(--rule); }
/* A group's heading is pressed to open it, so it is not text to select. */
summary { padding: 12px 0; cursor: pointer; font-weight: 600; user-select: none; -webkit-user-select: none; }
summary span { float: right; color: var(--dim); font-weight: 400; }
table { border-collapse: collapse; width: 100%; margin: 0 0 16px; font-size: 15px; }
td { padding: 5px 16px 5px 0; border-top: 1px solid var(--rule); vertical-align: top; }
td:last-child { color: var(--dim); padding-right: 0; }

/* The support form: one column, each field under its name, ruled as the page is. */
.write { display: grid; gap: 6px; max-width: 520px; margin: 0 0 20px; }
.write label { font-size: 15px; color: var(--dim); }
.write input, .write textarea {
    width: 100%;
    margin: 0 0 12px;
    padding: 8px 10px;
    border: 1px solid var(--rule);
    border-radius: 0;
    font: inherit;
    color: var(--text);
    background: none;
}
.write textarea { display: block; resize: vertical; min-height: 120px; }
/* A field being written in is marked in the site's green, as the form's button is. */
.write input:focus-visible, .write textarea:focus-visible { outline: 1px solid var(--mark); outline-offset: 0; border-color: var(--mark); }
.write button:focus-visible { outline-color: var(--mark); }
.write input, .write textarea { caret-color: var(--mark); accent-color: var(--mark); }
/* A field no person sees or fills in: what fills it is not a person. */
.write .trap { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.write button {
    justify-self: start;
    min-height: 36px;
    padding: 0 18px;
    border: 0;
    font: 600 14px/1.2 var(--sans);
    color: var(--mark);
    background: var(--mark-bg);
    cursor: pointer;
}
.write button:disabled { opacity: 0.6; cursor: default; }
/* Whether it was sent, over the button; it takes no room until it says something. */
.write .said { margin: 0 0 6px; font-size: 15px; color: var(--mark); }
.write .said:empty { display: none; }
.write .said.wrong { color: var(--text); }
.note { color: var(--dim); font-size: 14px; }

/* The footer stands as far under the page as the page stands under the wordmark: what a
   page ends with gives up its own room below, so that distance is the same on every page. */
main > p:last-child, main > table:last-child, main > ul:last-child { margin-bottom: 0; }
.apps li:last-child { padding-bottom: 0; }
.points > .parts:last-child, .points > p:has(+ .parts:empty:last-child) { margin-bottom: 0; }
footer { padding: 44px 0 0; font-size: 14px; }
footer:empty { display: none; }
footer a { color: var(--dim); margin-right: 16px; }
footer a:hover { color: var(--text); }

/* A phone on its side: too low for the notes and the bar to go under an upright clip, which
   would leave it a sliver. They go beside it, and the clip has the screen's whole height. */
@media (orientation: landscape) and (max-height: 540px) {
    .player.live { --room: calc(100vh - 12px); width: fit-content; }
    @supports (height: 1dvh) {
        .player.live { --room: calc(100dvh - 12px); }
    }
    .player.live:popover-open {
        display: grid;
        grid-template-columns: auto minmax(220px, 340px);
        grid-template-rows: 1fr auto;
    }
    .live video {
        grid-row: 1 / span 2;
        width: calc(var(--room) * var(--frame-wide) / var(--frame-high));
        height: var(--room);
    }
    .live .label { display: none; }
    .live .notes { height: auto; border-top: 0; border-left: 1px solid var(--rule); }
    .live .notes li { padding: 0 18px; font-size: 15px; }
    .live .bar { border-left: 1px solid var(--rule); }
    .live .again { width: calc(var(--room) * var(--frame-wide) / var(--frame-high)); }
}

/* For whoever asked their system for less motion: notes and icons change at once, and the
   ring around a waiting clip is whole from the start. */
@media (prefers-reduced-motion: reduce) {
    .notes li, .toggle::before, .toggle::after { transition: none; }
    .holding .toggle circle { animation: none; stroke-dashoffset: 0; }
}
