#text {
    padding-bottom: 0;
}

.plugin-hero {
    padding-top: 20px;
    padding-bottom: 40px;
    position: relative;

    background: whitesmoke;
    background-size: 20px 20px;
    background-image:
        linear-gradient(to right, #eee 1px, transparent 1px),
        linear-gradient(to bottom, #eee 1px, transparent 1px);

    border-bottom: 1px solid #bbb;
}

.plugin-hero .pattern-bg {
    background-size: 150px 150px;
    opacity: 0.075;
    opacity: 0;
}

.plugin-hero h1 {
    max-width: 400px;
    margin: auto auto;
    margin-bottom: -40px;
    padding: 0;
}

.plugin-hero img.nameplate {
    display: block;
    width: 100%;
}

.interface-holder {
    margin: auto auto;
    margin-top: 40px;
    /* box-shadow: 0 0 30px rgb(0 0 0 / 30%); */
    /* border-radius: 20px; */
}

.interface-holder img {
    display: block;
}

/* The step to the plugin either side of this one, alphabetically. Pinned to
   the edges of the band above and centred on the picture.

   The arrows are the font's own — PolymathWeb has ← and →, which is what the
   rest of the site steps with — rather than drawn marks, so they keep the
   page's hand.

   Whether there is room for them at all is decided in the page's own <style>
   block, which knows how wide this plugin's picture is. */
/* The band the arrows are pinned to: 1200px, centred on the window, and kept
   16px clear of each edge on anything narrower. It is wider than the picture
   inside it, which is why it is centred by hand — a block wider than its
   parent does not centre on auto margins. The transform is also what makes it
   the containing block the arrows are positioned against. */
.plugin-hero-image {
    position: relative;
    left: 50%;
    width: min(1200px, calc(100vw - 32px));
    transform: translateX(-50%);
}

/* The picture keeps its own width in the middle of that band. A grid of one
   cell rather than a plain block, because changing the language or the look
   puts the new picture in the same cell as the old one and fades it up over
   it — see plugin-switches.js. */
.plugin-hero-image {
    display: grid;
}

.plugin-hero-image picture {
    grid-area: 1 / 1;
    display: block;
    max-width: var(--shot);
    margin: 0 auto;
    /* out of both eases together, so the picture is at its full size at the
       moment it becomes fully opaque */
    transition: opacity 0.32s ease, transform 0.32s ease;
}

/* the new one comes up a little under size and settles into place, and the
   one it replaces goes out under it over the same beat */
.plugin-hero-image picture.is-arriving {
    opacity: 0;
    transform: scale(0.9);
}

.plugin-hero-image picture.is-leaving {
    opacity: 0;
}

@media (prefers-reduced-motion: reduce) {
    .plugin-hero-image picture {
        transition: none;
    }

    .plugin-hero-image picture.is-arriving {
        transform: none;
    }
}

.plugin-hero-step {
    position: absolute;
    top: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border: 1px solid #d5d5d5;
    border-radius: 50%;
    background: white;
    box-shadow: 0 2px 7px rgba(0, 0, 0, 0.11);
    color: #555;
    font-size: 21px;
    line-height: 1;
    text-decoration: none;
    box-sizing: border-box;
    transition: transform 0.16s, box-shadow 0.16s, border-color 0.16s, color 0.16s;
}

/* The arrow rides low in the disc rather than on its centre: the glyph sits
   high in its em box, so centring the box leaves the mark looking lifted.
   Nudged on the glyph rather than with padding, which would move the disc's
   centre and take the hover lean with it. */
.plugin-hero-step span {
    /* transform: translateY(2px); */
}

/* The translate has to carry the -50% that centres it: a transform replaces
   the one before it rather than adding to it. */
.plugin-hero-step.is-prev {
    left: 0;
    transform: translate(0, -50%);
}

.plugin-hero-step.is-next {
    right: 0;
    transform: translate(0, -50%);
}

.plugin-hero-step:hover {
    color: #333;
    border-color: #c2c2c2;
    box-shadow: 0 5px 13px rgba(0, 0, 0, 0.17);
}

/* each leans the way it goes */
.plugin-hero-step.is-prev:hover {
    transform: translate(-3px, -50%);
}

.plugin-hero-step.is-next:hover {
    transform: translate(3px, -50%);
}

@media (prefers-reduced-motion: reduce) {
    .plugin-hero-step,
    .plugin-hero-step.is-prev:hover,
    .plugin-hero-step.is-next:hover {
        transition: none;
        transform: translate(0, -50%);
    }
}

/* The two switches under the picture, on the hero's own ground. The track and
   the pills come from view-switches.css, which /plugins and /collections use;
   what is here is where they sit, and the list the languages drop into. */
.plugin-hero-switches {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: center;
    gap: 18px;
    margin-top: 18px;
}

/* The language control is a track like the one beside it holding a single
   pill, rather than a pill of its own — that is what makes the two stand the
   same height and wear the same edge without either being described twice. */
.plugin-hero .plugin-lang {
    position: relative;
}

.plugin-hero .plugin-lang > summary {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    list-style: none;
}

/* the marker the browser draws of its own accord, in both of the places it
   is reachable from */

.plugin-hero .plugin-lang > summary::-webkit-details-marker {
    display: none;
}

.plugin-hero .plugin-lang > summary::marker {
    content: "";
}

.plugin-lang-caret {
    flex: none;
    /* sits on the text's centre rather than its baseline */
    margin-top: 1px;
    opacity: 0.75;
    transition: transform 0.18s ease;
}

.plugin-hero .plugin-lang[open] > summary {
    border-color: rgba(255, 255, 255, 0.85);
    background: rgba(255, 255, 255, 0.82);
    color: #222;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);
}

.plugin-hero .plugin-lang[open] .plugin-lang-caret {
    transform: rotate(180deg);
}

/* While the list is down, the hero has to paint over what follows it. Both it
   and the quotes below are position: relative at z-index auto, so without
   this the later one in the page simply covers the open list. Only while it
   is open, so the paint order is otherwise left alone. */
.plugin-hero:has(.plugin-lang[open]) {
    z-index: 2;
}

/* The list, over the page rather than pushing it down — a menu that moved the
   picture every time it opened would be worse than the row of links this
   replaced. Two columns, because ten languages in one make a column taller
   than the picture it belongs to. */
.plugin-lang-menu {
    position: absolute;
    top: calc(100% + 8px);
    left: 50%;
    z-index: 5;
    transform: translateX(-50%);
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 2px 4px;
    padding: 7px;
    border: 1px solid rgba(0, 0, 0, 0.07);
    border-radius: 16px;
    background: rgba(252, 252, 252, 0.97);
    backdrop-filter: blur(10px) saturate(1.3);
    -webkit-backdrop-filter: blur(10px) saturate(1.3);
    box-shadow:
        0 1px 2px rgba(0, 0, 0, 0.06),
        0 10px 28px rgba(0, 0, 0, 0.16);
}

.plugin-hero .plugin-lang-menu a {
    padding: 6px 14px;
    border-radius: 100px;
    color: rgba(0, 0, 0, 0.55);
    font-size: 14px;
    /* as on the pill: one line height whatever script the name is in, so the
       rows of the list stay level with each other */
    line-height: 1.25;
    font-variation-settings: "wght" 650, "ital" 0;
    text-decoration: none;
    white-space: nowrap;
    transition: background 0.12s, color 0.12s;
}

.plugin-hero .plugin-lang-menu a:hover {
    background: rgba(0, 0, 0, 0.055);
    color: rgba(0, 0, 0, 0.9);
}

/* the one in use, marked the way the track marks its own */
.plugin-hero .plugin-lang-menu a[aria-current="true"] {
    background: rgba(0, 0, 0, 0.06);
    color: #222;
}




.plugin-big-nav-links {
    position: relative;
    /* border-left: 1px solid #ddd; */
    padding-left: 10px;
}

#content .plugin-big-nav-links ul {
    list-style: none;
    margin: 0; padding: 0;
}

#content .plugin-big-nav-link {
    text-align: right;
    font-variation-settings: "wght" 650, "opsz" 38;
    display: block;
    font-size: 1.2em;
    text-decoration: none;
    border-bottom: 1px solid #eee;
}

/* The manual, as a pill in no colour at all: the two buttons above it are the
   plugin's green and its own colour, and this is somewhere to read rather
   than something to press. Hung on the right as they are. */
/* ------------------------------------------------- the sidebar's buttons */

/* Buying, boxed as a collection's page boxes it (collection_detail.css): a
   white card with the two ways to buy in it, full width and centred, and
   nothing else inside. */
.plugin-buy-box {
    margin-top: 20px;
    padding: 18px;
    border: 1px solid #e8e8e8;
    border-radius: 12px;
    background: white;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
    text-align: center;
}

#content .plugin-buy-now,
#content .plugin-cart-button {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    width: 100%;
    box-sizing: border-box;
    padding: 11px 16px;
    border-radius: 100px;
    font-size: 16px;
    line-height: 24px;
    text-decoration: none;
    transition: box-shadow 0.15s, transform 0.15s, filter 0.15s,
                border-color 0.15s, color 0.15s;
}

#content .plugin-buy-now {
    border: 1px solid seagreen;
    background: seagreen;
    color: white;
    font-variation-settings: "wght" 700, "ital" 0;
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.18),
        0 1px 2px rgba(0, 0, 0, 0.18);
}

#content .plugin-buy-now:hover {
    filter: brightness(1.12);
}

/* the quieter of the two, as .collection-add-all is on a collection's page:
   white with a grey outline, and seagreen only on the way in */
#content .plugin-cart-button {
    margin-top: 8px;
    border: 1px solid #ddd;
    background: white;
    color: #333;
    font-variation-settings: "wght" 600, "ital" 0;
}

#content .plugin-cart-button:hover {
    border-color: seagreen;
    color: seagreen;
}

/* the glyph's own margin is from the nav, where it stands beside text with no
   gap of its own; here the gap above does that work */
#content .plugin-cart-button .nav-cart {
    margin-right: 0;
    vertical-align: 0;
}

/* what the purchase brings with it: VCME Soft Clip with VCME */
#content .plugin-cart-includes {
    display: block;
    margin-top: 8px;
    color: #555;
    font-size: 13px;
    line-height: 1.4;
    font-variation-settings: "wght" 500, "ital" 0;
}

#content .plugin-buy-trials {
    margin: 12px 0 0;
    color: #888;
    font-size: 13px;
    line-height: 1.4;
}

/* The plugins with nothing to buy — free, or not out yet. This is the news on
   such a page, so it is given the room a purchase would have had and the
   plugin's own colour, tinted rather than filled: it is worth seeing, but
   there is nowhere for it to go and it should not read as pressable. */
.plugin-status-box {
    margin-top: 20px;
    padding: 16px;
    border: 1px solid var(--accent, #ddd);
    border-radius: 12px;
    background: color-mix(in srgb, var(--accent, #999) 9%, white);
    color: var(--accent, #333);
    font-size: 1.3em;
    line-height: 1.25;
    font-variation-settings: "wght" 780, "opsz" 24;
    text-align: center;
}

/* The manual gets a box of its own, built like the one above it, and the link
   in it runs the full width as the buttons there do. It is still the quiet
   one — grey rather than coloured — but it is shaped like its neighbours.
   Named twice over because #content .plugin-big-nav-links ul further up sets
   margin and padding to nothing and would otherwise win. */
#content .plugin-big-nav-links ul.plugin-big-nav-list {
    margin: 12px 0 0;
    padding: 18px;
    /* border: 1px solid #e8e8e8; */
    /* border-radius: 12px; */
    /* background: white; */
    /* box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05); */
    text-align: center;
}

#content .plugin-big-nav-links ul.plugin-big-nav-list li + li {
    margin-top: 8px;
}

#content .plugin-manual-link {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    width: 100%;
    box-sizing: border-box;
    padding: 11px 16px;
    border-radius: 100px;
    background: #efeff1;
    color: #45454c;
    font-size: 16px;
    line-height: 24px;
    font-variation-settings: "wght" 650, "ital" 0;
    text-decoration: none;
    transition: background 0.15s, color 0.15s;
}

#content .plugin-manual-link:hover {
    background: #e4e4e7;
    color: #1d1d20;
}

#content .plugin-manual-mark {
    flex: none;
    opacity: 0.75;
}

#content .plugin-big-nav-link p {
    margin-bottom: 0px !important;
}

/* The page's two columns. A plugin with a featured video hands this same
   arrangement to each .plugin-half instead, so the halves and an unsplit page
   are laid out by one rule rather than by two that have to be kept in step. */
#content,
.plugin-half {
    display: grid;
    grid-template-columns: auto 30px minmax(30%, 260px);
    grid-template-areas: "text x menu";
}

@media (max-width:850px) {
    #content,
    .plugin-half {
        grid-template-columns: auto;
        grid-template-rows: auto auto;
        grid-template-areas: "menu" "text";
    }
    .plugin-big-nav-links {
        border: none;
        margin-bottom: 20px;
    }

    #other-plugins {
        display: none;
    }
}

.plugin-big-nav-links {
    grid-area: menu;
    margin-top: 20px;
}

#text {
    grid-area: text;
    max-width: 650px;
    padding-top: 0px;
    margin-top: 20px;
}

#content #text h2 {
    font-size: 2em;
}

/* What this is, over what it is called, as a collection's page opens. The
   hero above carries the name in the plugin's own lettering; this is the
   plain-text answer to "what am I looking at", at the top of the reading. */
.plugin-page-head {
    margin-bottom: 26px;
    margin-top: 20px;
}

#content .plugin-page-head .plugin-eyebrow {
    margin: 0 0 6px;
    color: #999;
    font-size: 12px;
    font-variation-settings: "wght" 700, "ital" 0;
    letter-spacing: 0.22em;
    text-transform: uppercase;
}

#content .plugin-page-head h2 {
    margin: 0;
    color: var(--accent-deep, inherit);
    font-size: 2.85em;
    line-height: 1.05;
    font-variation-settings: "wght" 800, "opsz" 40;
}

/* The tagline as the hero used to carry it: the plugin's own darker colour,
   set large and bold rather than as a grey aside. Only the type is taken from
   there — the hero's right alignment and padding belonged to the hero. */
#content .plugin-page-head .plugin-page-tagline {
    margin: 10px 0 0;
    color: var(--accent-deep, #666);
    font-size: 1.35em;
    line-height: 1.2;
    font-variation-settings: "wght" 370, "opsz" 36, "ital" 1;
}

/* ------------------------------------------- what people say about it */

/* Under the plugin's picture, a rail of what people have said about it: three
   abreast at most, with the rest scrolled to. It scrolls and snaps on its own,
   so there is nothing to press and nothing to load. */

/* The section stands on its own ground, edge to edge: whitesmoke under the
   plugin's own pattern.

   --pattern is set inline by the page: this is drawn in the banner block,
   above and outside #content, so the custom properties declared there do not
   reach it.

   The shadow is inset along the top alone, so the hero above reads as sitting
   on this rather than beside it. */
.plugin-says {
    /* the pattern below is laid in with inset: 0, and this is what that 0 is
       measured from — without it the pattern is sized against the page and
       tiles the whole of it */
    position: relative;
    width: 100vw;
    max-width: 100vw;
    margin: 0 calc(50% - 50vw);
    padding: 8px 0 18px;
    /* The ground and the type, stated here rather than inherited so the
       whole section is set from one place. All three come from the plugin's
       own colour and are handed in by the page: --wash is it taken up to a
       tint, --ink is it desaturated down to something to write in, and
       --rule is it at half strength, which every line in here is drawn in.
       The greys are for a plugin whose colour did not come through. */
    background-color: var(--wash, whitesmoke);
    color: var(--ink, #333);
    /* the same shadow along both edges, so the sections above and below it
       both read as sitting on this one */
    box-shadow:
        inset 0 9px 5px -9px rgba(0, 0, 0, 0.15),
        inset 0 -9px 5px -9px rgba(0, 0, 0, 0.15);
}

/* The ground runs the width of the window; what is on it keeps to the width
   of the page below, so the first quote starts where the writing does.

   The inset is on this wrapper rather than on the scroller itself: a scroller
   with padding scrolls it away, because scroll-snap-align: start snaps to the
   scrollport edge inside the padding and the rail simply moves the 10px out
   of view. */
/* The plugin's own pattern, as it comes: pattern_dark.png is marks on
   transparency, which is what a light ground wants. It is a layer of its own
   rather than a background on the section, so its opacity is its own and does
   not take the writing down with it.

   The file is 250px square and drawn at half that, so on a 2x screen one
   image pixel lands on one device pixel: the tile at its own size rather
   than resampled. */
.plugin-says::before {
    content: "";
    position: absolute;
    inset: 0;
    background-image: var(--pattern);
    background-size: 125px 125px;
    opacity: 0.05;
    pointer-events: none;
}

/* over the pattern rather than under it */
.plugin-says-inner {
    position: relative;
    z-index: 1;
}

.plugin-says-inner {
    max-width: 1300px;
    margin: 0 auto;
    padding: 0 10px 0 60px;
    box-sizing: border-box;
}

.plugin-says-rail {
    display: flex;
    gap: 16px;
    margin: 0;
    /* The top padding is room for the opening quotation mark, which is
       pinned above the first line: overflow-x: auto forces overflow-y to auto
       as well, so anything outside the scrollport is clipped rather than
       hanging free. The section gave up the same 20px, so the band is the
       height it always was. Inline padding is what must not go here —
       scroll-snap-align: start snaps to the scrollport edge inside it, and
       the rail would simply scroll it out of view. */
    padding: 20px 0 12px;
    list-style: none;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    overscroll-behavior-x: contain;
    scrollbar-width: thin;
}

@media (prefers-reduced-motion: reduce) {
    .plugin-says-rail {
        scroll-behavior: auto;
    }
}

/* Three is what the rail shows at once, so anything up to three is all of
   them: they sit in the middle rather than starting at the left edge, which
   would leave a space on the right that reads as another one waiting to be
   scrolled to. Hung on there being no fourth, so one and two centre as three
   does. */
.plugin-says-rail:not(:has(> :nth-child(4))) {
    justify-content: center;
}

/* The right edge fades while there is more along there. Masked rather than
   covered by a gradient: the ground here is a pattern, and no flat colour
   would match it.

   Without the script, a fourth quote is the tell — three is what fits — and
   the fade simply stays. With it, plugin-says.js sets data-scrolls and then
   says outright whether there is more, so the fade goes at the far end. */
.plugin-says-rail:has(> :nth-child(4)),
.plugin-says-rail[data-scrolls].has-more {
    -webkit-mask-image: linear-gradient(to right,
        #000 calc(100% - 110px), transparent calc(100% - 6px));
    mask-image: linear-gradient(to right,
        #000 calc(100% - 110px), transparent calc(100% - 6px));
}

.plugin-says-rail[data-scrolls]:not(.has-more) {
    -webkit-mask-image: none;
    mask-image: none;
}

/* Three across, with the edge of a fourth showing when there is one. Sized
   border-box: the basis is a share of the rail, and the padding has to come
   out of that share rather than be added to it, or only two and a half fit.
   No box of its own — the section's ground is the background now, and a card
   on top of it would be a box inside a box. */
.plugin-said {
    position: relative;
    flex: 0 0 clamp(240px, 30%, 360px);
    box-sizing: border-box;
    min-width: 0;
    margin: 0;
    padding: 0 6px;
    background: none;
    scroll-snap-align: start;
}

/* A hairline between one quote and the next, and never before the first,
   which has nothing to its left.

   Drawn in the gap rather than as a border on the card: the gap is 16px and
   each card carries 6px of padding, so a border on the edge would sit 6px
   from the writing on its right and 22px from the writing on its left. At
   half the gap it is 14px from both.

   Full height on purpose — the cards in a row all stretch to the tallest of
   them, so the lines rule the whole band rather than stopping under whichever
   quote is shortest. */
.plugin-said + .plugin-said::before {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    left: -8px;
    width: 1px;
    background: var(--rule, rgba(0, 0, 0, 0.14));
}

@media (max-width: 700px) {
    .plugin-said {
        flex-basis: 80%;
    }
}

/* A pair of quotation marks pinned to the opening and closing corners of the
   quotation — barely there, and out of the flow, so they mark it without
   taking a line from it or shifting a word of it.

   Hung on the quotation and not on the whole card: the cards in a row all
   stretch to the tallest of them, so the card's bottom is wherever the
   longest quote in the rail happens to end, and a mark pinned there would
   float away from the end of a short one.

   Kept inside the box rather than off its corners: the rail scrolls on its
   overflow, and anything reaching past the edge would widen what there is to
   scroll. The `/ ""` gives them empty alternative text, so a screen reader
   passes over them instead of reading the glyph out.

   The face is stated outright with a display instance to go with it. It is
   the same PolymathWeb the writing is in either way, but a pseudo-element
   inherits no variation settings, so these were drawn at the font's default
   instance — thin, and at an optical size meant for text, at 58px. */
/* The quotation marks, which the in_quotation_marks filter spans into the
   first and last block of the quote. In the line with the words rather than
   pinned to the corners, so they set the text in quotation marks the way a
   printed page would — and, being real elements, they can be sized, weighted
   and coloured apart from the writing they sit in. */
.said-mark {
    font-variation-settings: "wght" 800, "opsz" 40, "ital" 1;
    opacity: 0.3;
    display: inline-block;
    padding: 0 3px;
}

.plugin-said-quote p {
    margin: 0 0 10px;
    color: var(--ink, #333);
    font-size: 15px;
    line-height: 1.5;
}

/* A short quote set in the same type as a long one looks lost in its column,
   so it is given more of it. Which band a quote is in is decided in the model
   (Testimonial.quotation_band) and written on as a class, since the length
   that matters is the cut being shown and CSS cannot count characters.

   The leading tightens as the type grows: 1.5 is right for 15px and too airy
   for 22px. The quotation marks are spans inside the paragraph, so they come
   up with it. */
.plugin-said-quote.is-medium p {
    font-size: 17px;
    line-height: 1.45;
}

.plugin-said-quote.is-short p {
    font-size: 22px;
    line-height: 1.3;
}

.plugin-said-quote p:last-child {
    margin-bottom: 0;
}

.plugin-said-who {
    margin: 12px 0 0 !important;
    padding-top: 12px;
    border-top: 1px solid var(--rule, rgba(0, 0, 0, 0.16));
    font-size: 16px;
    line-height: 1.4;
}

.plugin-said-name {
    display: block;
    color: var(--ink, #333);
    font-variation-settings: "wght" 700, "ital" 0;
    /* text-align: right; */
}

/* Not prefixed with #content: this section is drawn in the banner block,
   above and outside it, so a rule hung on #content never reaches it — which
   is how these came out the browser's default blue. */
.plugin-said-name a {
    color: var(--ink, #333);
    text-decoration: underline;
}

.plugin-said a {
    color: var(--ink, #333);
}

.plugin-said-name a:hover {
    text-decoration: underline;
    text-underline-offset: 2px;
}

.plugin-said-bio {
    display: block;
    margin-top: 2px;
    color: var(--ink, #333);
    opacity: 0.62;
    font-variation-settings: "wght" 400, "ital" 1;
    /* text-align: right; */
    font-size: 0.8em;
}

/* ------------------------------------------------- the featured video */

/* Every plugin page is made of .plugin-half: one of them on its own, or two
   with a video cut across between them. #content stops being the column grid
   and becomes a plain stack of halves, so both kinds are laid out and
   measured by the same rule rather than by two that can drift apart. Each half is its own column grid
   (above), and the measure lives on .plugin-half — change it there and both
   halves move together. What is at the seam is a sibling rather than a child
   of a half, so it is not held to that measure.

   Hung on .plugin-half rather than on either thing at the seam, since either
   one alone is enough to split the page. */
#content:has(.plugin-half) {
    display: block;
}

.plugin-half {
    max-width: 1000px;
    margin: 0 auto;
}

/* The lower half of the writing is not #text, so it is given what #text has:
   the place in the grid, the measure, the 10px of side padding that sets
   where the column actually starts, and the auto side margins that centre it
   in the column once that measure binds. */
#content .plugin-text-b {
    grid-area: text;
    max-width: 650px;
    padding: 0 10px 40px;
    margin-left: auto;
    margin-right: auto;
}

/* the advanced pages start their own half rather than carrying on from the
   downloads, which are now above the band */
#content .plugin-side-b {
    margin-top: 0;
}

/* The band itself: edge to edge, on its own dark ground, with the picture
   capped so it does not become a billboard on a wide screen. */
.plugin-feature {
    width: 100vw;
    max-width: 100vw;
    margin: 36px calc(50% - 50vw);
    padding: 24px 0;

    /* The same ground the quotes stand on — a tint of the plugin's colour
       under the plugin's pattern — so the two full-width panels on the page
       read as the same thing twice rather than two different stripes. The
       pattern itself is the shared ::before further up. position: relative
       is what that pattern's inset: 0 is measured from; without it, it is
       measured against the page. */
    position: relative;
    /* background-color: var(--wash, whitesmoke); */

    /* box-shadow:
        inset 0 9px 5px -9px rgba(0, 0, 0, 0.15),
        inset 0 -9px 5px -9px rgba(0, 0, 0, 0.15); */
    
    /* border-top: 1px solid #eee;
    border-bottom: 1px solid #eee; */

    background: black;
    box-shadow: 0 0 10px rgb(0, 0, 0, 0.3);
}

.plugin-feature::before {
    content: "";
    position: absolute;
    inset: 0;
    background-image: var(--pattern);
    background-size: 125px 125px;
    opacity: 0.25;
    pointer-events: none;
    filter: invert(1);
}

/* The ground runs the width of the window; the picture stops where the
   writing above it stops. These are #main's own measurements, so the video
   lines up with the column rather than merely being near it. */
.plugin-feature-inner {
    position: relative;  /* over the pattern rather than under it */
    z-index: 1;
    box-sizing: border-box;
    max-width: 800px;
    margin: 0 auto;
    padding: 20px 10px;
}

/* the player: the band's inner box is the measure, and the frame holds the
   shape so the iframe has something to fill */
.plugin-feature-frame {
    position: relative;
    aspect-ratio: 16 / 9;
}

.plugin-feature-frame iframe {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border: 0;
}

#plugin-text .product-copy {
    margin-bottom: 30px;
}

#plugin-text .beta-warning {
    font-size: 0.9emem;
    background: lightyellow;
    border: 1px solid gold;
    padding: 20px;
    margin-top: 0px;
    margin-bottom: 30px;
}

#plugin-text .introduction {
    font-size: 1.2em;
}

#plugin-text .features {
    font-family: var(--accent-font);
    font-size: 1.1em;
    border: 1px solid #ddd;
    background: #eee;
    border-radius: 2px;
    padding: 26px 30px 16px 30px;
    margin: 0px -10px 30px;
    position: relative;
    overflow: hidden;
}

/* The word itself, standing on end in the top right corner of the box and
   barely there — a label on the panel rather than a heading in it.

   writing-mode rather than a rotate: it turns the line to run top to bottom
   and lays the box out tall and narrow to match, so the corner it is pinned
   to is the corner it actually occupies. A transform would leave a wide, flat
   box behind and have to be nudged back into place by hand. */
#plugin-text .features::before {
    content: "features";
    position: absolute;
    top: -5px;
    right: -6px;
    z-index: 0;
    writing-mode: vertical-rl;
    color: rgba(0, 0, 0, 0.05);
    font-family: var(--accent-font);
    font-size: 47px;
    font-variation-settings: "wght" 800, "opsz" 36;
    /* letter-spacing: 0.22em; */
    text-transform: lowercase;
    pointer-events: none;
    user-select: none;
}

/* the writing sits over it; the pattern behind it stays behind */
#plugin-text .features > *:not(.pattern-bg) {
    position: relative;
    z-index: 1;
}

#plugin-text .features .pattern-bg {
    background-size: 300px;
    opacity: 0.55;
}

#plugin-text .features li strong {
    font-variation-settings: "wght" 750, "opsz" 12;
}

#plugin-text .features ul li ul {
    font-size: 0.9em;
    margin-top: 4px;
}

#content .features ul > li > p {
    margin-bottom: 0px;
}

#plugin-text .examples {
    /* background: whitesmoke; */
    padding: 20px 0px 1px 0px;
}

#plugin-text .examples p {
    max-width: 400px;
    font-variation-settings: 'wght' 400, 'ital' 1;
}

#plugin-text .examples ul {
    padding: 0;
}

#plugin-text .examples li {
    display: grid;
    grid-template-columns: 85% auto;
    background: whitesmoke;
}

#plugin-text .examples li .audio-span {
    display: block;
}

#plugin-text .examples li .audio-span .webaudio {
    display: block;
    border-radius: 10px;
    padding: 10px 14px;
}

#plugin-text .examples a {
    display: block;
    text-align: center;
    font-family: var(--text-font-condensed);
    display: grid;
    align-items: center;
    justify-items: center;
    text-decoration: none;
    padding: 10px;
}

#plugin-text .about {
    /* border-left: 10px solid #eee; */
    /* padding-left: 20px; */
    font-size: 1.1em;
    /* border-top: 1px solid #ddd; */
    /* padding-top: 30px; */
    /* margin-top: 30px; */
}

#plugin-text .about p,
#plugin-text .documentation p {
    /* max-width: 500px; */
    /* margin-left: auto; */
    /* margin-right: auto; */
}

#plugin-text h3 {
    margin-top: 50px;
}

#plugin-text .about > h3:first-of-type {
    margin-top: 0px;
}

#plugin-text .about h3.top {
    font-size: 1.5em;
    color: #555;
    text-align: center;
    font-family: var(--text-font-condensed);
    border-top: 4px solid #eee;
    border-bottom: 4px solid #eee;
    padding: 10px;
}

#plugin-text .documentation {
    font-size: 0.95em;
    margin-top: 30px;
    padding-top: 20px;
    border-top: 1px solid #ccc;
}

#plugin-text .documentation h4.top {
    font-size: 1.5em;
    font-variation-settings: 'wght' 500;
    color: #555;
    text-align: left;
    padding: 10px;
    border-top: 4px solid #eee;
    border-bottom: 4px solid #eee;
}

/* ------------------------------------------------------- <plugin> in use */

/* A contact sheet: a square and a title apiece, three across. The section used
   to be a column of live embeds several thousand pixels tall; everything that
   is not the picture and the name now lives in the modal a card opens. */

#plugin-text .plugin-uses {
    border-top: 1px solid #ddd;
    padding-top: 20px;
    margin-top: 40px;
}

#plugin-text .plugin-uses h4.top {
    font-size: 2em;
    font-variation-settings: "wght" 750, "opsz" 36;
    color: #555;
    margin-bottom: 18px;
}

#plugin-text .plugin-uses-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 18px 16px;
    margin: 0;
    padding: 0;
    list-style: none;
}

@media (max-width: 520px) {
    #plugin-text .plugin-uses-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

#plugin-text .plugin-use {
    margin: 0;
    padding: 0;
    background: none;
}

#plugin-text .plugin-use-card {
    display: block;
    color: inherit;
    text-decoration: none;
    cursor: pointer;
}

#plugin-text .plugin-use-thumb {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    /* square, whatever shape the picture behind it is: a YouTube poster frame
       is 4:3, a reel is 9:16 and a blog image is anything, and a sheet of
       these reads as a sheet only if they agree on a shape */
    aspect-ratio: 1 / 1;
    border: 1px solid #e8e8e8;
    border-radius: 8px;
    background: #f3f3f5;
}

#plugin-text .plugin-use-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    transition: transform 0.3s;
}

#plugin-text .plugin-use-card:hover .plugin-use-thumb img {
    transform: scale(1.04);
}

/* a reel is portrait: filling a square takes the middle of it, and a little
   above the middle is where the subject of one usually is */
#plugin-text .plugin-use-thumb-ig img {
    object-position: center 38%;
}

/* The mark and the name are two columns rather than one run of text, so a
   title that wraps keeps its later lines under the first word instead of
   sliding back under the mark. */
#plugin-text .plugin-use-title {
    display: flex;
    align-items: flex-start;
    gap: 6px;
    margin-top: 8px;
    color: #333;
    font-family: var(--text-font-condensed);
    font-size: 15px;
    line-height: 1.25;
    font-variation-settings: "wght" 700, "ital" 0;
}

#plugin-text .plugin-use-name {
    min-width: 0;
}

#plugin-text .plugin-use-card:hover .plugin-use-name {
    text-decoration: underline;
    text-underline-offset: 2px;
}

/* The service mark sits on the text baseline and is drawn quieter than the
   name it introduces: it is there to be recognised at a glance, not read. It
   takes the plugin's colour on hover, as the rest of the card does. */
#plugin-text .plugin-use-mark {
    flex: none;
    /* nudged down to sit on the first line's centre rather than its top */
    margin-top: 2px;
    color: #9a9aa2;
    transition: color 0.15s;
}

#plugin-text .plugin-use-card:hover .plugin-use-mark {
    /* --accent is the plugin's own colour, set on #content by the page;
       --plugin-theme is the collections pages' name for the same idea and is
       not defined here */
    color: var(--accent, #333);
}

/* --------------------------------------------------- the one a card opens */

/* The scrolling belongs here rather than on the panel: the arrows sit outside
   the panel on a wide window, and a panel that scrolls clips whatever hangs
   over its edge — they vanished behind the backdrop. Centring is `margin:
   auto` on the panel for the same reason it usually is, that centring a flex
   item taller than its container puts the top of it out of reach. */
.use-modal {
    position: fixed;
    inset: 0;
    /* the level the site's other two modals sit at (style_2024.css) */
    z-index: 3000;
    display: flex;
    padding: 24px;
    overflow-y: auto;
}

.use-modal[hidden] {
    display: none;
}

/* the page behind does not scroll while this is over it */
body.use-modal-open {
    overflow: hidden;
}

/* fixed, not absolute: the modal it sits in scrolls, and an absolute backdrop
   would only cover the first screenful of a tall one */
.use-modal-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.72);
    backdrop-filter: blur(3px);
    -webkit-backdrop-filter: blur(3px);
}

.use-modal-panel {
    position: relative;
    margin: auto;
    width: 100%;
    max-width: 720px;
    padding: 16px;
    border-radius: 14px;
    background: white;
    box-shadow: 0 24px 70px rgba(0, 0, 0, 0.45);
}

/* The stage the embed stands on: dark, and running to the edges of the panel
   over its padding, so the top of the modal is one dark field whatever shape
   the thing in it is. A portrait reel and a 16:9 player both sit on it rather
   than each bringing their own ground. */
.use-modal-stage {
    display: flex;
    align-items: center;
    justify-content: center;
    margin: -16px -16px 0;
    padding: 16px;
    border-radius: 14px 14px 0 0;
    background: #131315;
}

.use-modal-stage[data-kind="youtube"] {
    position: relative;
    aspect-ratio: 16 / 9;
    padding: 0;
    overflow: hidden;
}

.use-modal-frame {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border: 0;
}

/* Instagram's own stylesheet sets a max-width on this and its script an inline
   width; both are left alone */
.use-modal-stage .instagram-media {
    margin: 0 auto !important;
}

/* What stands in while Instagram's script does its work. The blockquote has no
   size until then, so without this the modal opened as a sliver and jumped to
   the height of a reel a moment later. This is a reel's shape, with the still
   on it if the use has one, and it goes when the embed is rendered. */
.use-modal-holding {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    width: 328px;
    max-width: 100%;
    aspect-ratio: 9 / 16;
    max-height: 70vh;
    border-radius: 9px;
    background: rgba(255, 255, 255, 0.05);
}

.use-modal-holding img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    opacity: 0.55;
}

/* a slow breath, so it reads as waiting rather than as the finished thing */
.use-modal-holding::after {
    content: "";
    position: absolute;
    width: 28px;
    height: 28px;
    border: 2px solid rgba(255, 255, 255, 0.35);
    border-top-color: white;
    border-radius: 100px;
    animation: use-modal-turning 0.9s linear infinite;
}

@keyframes use-modal-turning {
    to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
    .use-modal-holding::after { animation: none; }
}

/* once the embed is there the stand-in is taken away and the real thing fades
   up, which is gentler than a swap */
.use-modal-stage[data-kind="instagram"] .instagram-media {
    opacity: 0;
    transition: opacity 0.25s ease-out;
}

.use-modal-stage.is-ready .use-modal-holding {
    display: none;
}

.use-modal-stage.is-ready .instagram-media {
    opacity: 1;
}

.use-modal-words {
    padding: 14px 4px 2px;
}

.use-modal .use-modal-title {
    margin: 0 0 8px;
    font-size: 1.3em;
    font-variation-settings: "wght" 780, "opsz" 24;
}

.use-modal .use-modal-about {
    color: #555;
    font-size: 15px;
    line-height: 1.5;
}

.use-modal .use-modal-about p {
    margin: 0 0 10px;
}

.use-modal .use-modal-about p:last-child {
    margin-bottom: 0;
}

.use-modal .use-modal-out {
    display: inline-block;
    margin-top: 12px;
    color: royalblue;
    font-size: 15px;
    font-variation-settings: "wght" 650, "ital" 0;
    text-decoration: none;
}

.use-modal .use-modal-out:hover {
    text-decoration: underline;
    text-underline-offset: 3px;
}

/* the way out, and the way along */

.use-modal-close,
.use-modal-step {
    position: absolute;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 1px solid rgba(0, 0, 0, 0.1);
    border-radius: 100px;
    background: rgba(255, 255, 255, 0.92);
    color: #333;
    font-family: var(--text-font);
    line-height: 1;
    cursor: pointer;
    transition: background 0.15s, transform 0.15s;
}

.use-modal-close:hover,
.use-modal-step:hover {
    background: white;
    transform: scale(1.06);
}

/* Against the window rather than the panel: the stage runs to the panel's top
   corners now, and a close button in that corner sits on top of whatever the
   embed keeps there — on a YouTube player, its settings. */
.use-modal-close {
    position: fixed;
    top: 16px;
    right: 16px;
    z-index: 2;
    width: 34px;
    height: 34px;
    font-size: 21px;
}

/* Outside the panel on a wide window, where they are clear of the video, and
   tucked back inside it once there is no room for that. */
.use-modal-step {
    top: 50%;
    width: 40px;
    height: 40px;
    margin-top: -20px;
    /* ← and → as Polymath draws them, the arrows the rest of the site uses */
    font-size: 17px;
    font-variation-settings: "wght" 600;
}

.use-modal-step[data-use-step="-1"] { left: -54px; }
.use-modal-step[data-use-step="1"] { right: -54px; }

@media (max-width: 860px) {
    .use-modal-step[data-use-step="-1"] { left: 8px; }
    .use-modal-step[data-use-step="1"] { right: 8px; }
}

.use-modal .use-modal-count {
    margin: 10px 0 0;
    color: #999;
    font-size: 12px;
    text-align: center;
}

#plugin-text .plugin-merch {
    margin-top: 100px;
}

#plugin-text .plugin-merch h4.top {
    font-size: 1.5em;
    font-variation-settings: 'wght' 800, 'opsz' 36;
    letter-spacing: 4px;
    color: #555;
    font-family: var(--text-font-condensed);
    text-transform: uppercase;
    /* text-align: center; */
    padding: 10px 0;
    border-top: 1px solid #ddd;
    /* border-bottom: 1px solid #ddd; */
}

#plugin-text .plugin-merch-item {
    display: block;
    background: white;
    border: 4px solid #eee;
    padding: 10px;
    text-align: center;
    /* max-width: 300px; */
    margin: auto auto;
}

#plugin-text .plugin-merch-item:hover {
    border-color: #aaa;
}

#plugin-text .plugin-merch-item h3 {
    margin: 0;
    margin-bottom: 20px;
    color: royalblue;
}

#content .settings-explanation {
    background: rgba(255, 255, 255, 0.95);
    padding: 20px;
    /* border: 4px solid #eee; */
    /* border-radius: 10px; */
    padding-bottom: 10px;
}

#content button.copy {
    font-family: var(--text-font);
    padding: 4px 7px;
    font-variation-settings: 'wght' 700;
    font-size: 1em;
}

.plugin-settings {
    margin-top: 20px;
    padding-top: 20px;
    /* border-top: 10px solid #eee; */
}

.plugin-settings h2 {
    font-variation-settings: 'wght' 800, 'ital' 1 !important;
    text-align: left;
    padding-bottom: 10px;
    /* border-bottom: 1px solid #eee; */
}

.parameter-setting.header {
    font-variation-settings: 'wght' 700;
}

.parameter-setting {
    display: grid;
    padding: 10px;
    grid-template-columns: 40px 1.5fr .75fr 1fr .5fr;
    border-bottom: 1px solid #eee;
}

.parameter-setting .parameter-value {
    text-align: center;
}

.parameter-setting .parameter-id {
    text-align: center;
    border-left: 1px solid #eee;
    border-right: 1px solid #eee;
}

.parameter-setting .parameter-unit {
    text-align: right;
    font-variation-settings: 'wght' 400, 'ital' 1;
}

.parameter-setting.modified {
    background: lightgoldenrodyellow;
}

.parameter-setting.modified .parameter-value {
    font-variation-settings: 'wght' 700;
}

#content figure {
    width: 100%;
    margin-top: 30px;
    margin-bottom: 30px;
}

#content figure img {
    width: 100%;
}

#content figcaption {
    text-align: right;
    font-variation-settings: "wght" 400, "opsz" 12, "ital" 1;
    font-size: 0.85em;
}

#content .inline-figure {
    display: block;
    text-decoration: none;
    /* border: 1px solid #eee; */
}

#content .inline-figure img {
    display: block;
    border-bottom: 1px solid #eee;
}

#content .inline-figure-title {
    text-decoration: none;
    text-align: right;
    font-size: 0.9em;
    line-height: 1.2em;
    font-variation-settings: 'wght' 400, 'ital' 1;
    padding: 10px 0;
    display: block;
    /* max-width: 500px; */
    /* margin: auto auto; */
}

/* OWNERSHIP */

#ownership {
    margin-top: 0px;
    margin-bottom: 30px;
    /* text-align: center; */
}

#ownership .sign-in-for-downloads {
    margin-bottom: 6px;
}

#ownership .free-plugin-account-required {
    font-variation-settings: 'wght' 400, 'ital' 1;
    color: #333;
    font-size: 90%;
}

#ownership .how-to-unlock h5 {
    font-family: var(--text-font-condensed);
    margin-top: 20px;
    margin-bottom: 10px;
    font-size: 20px;
    color: #222;
}

/* The downloads, boxed as the buying above them is and as a collection's
   purchase box is: white, a hairline, a soft corner. It used to be fenced in
   six pixels of the plugin's colour, which made it the loudest thing in the
   column when it is the quietest thing in it. */
#ownership .owners-only {
    padding: 18px 18px 8px 18px;
    border: 1px solid #e8e8e8;
    border-radius: 12px;
    background: white;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
}

#ownership .owners-only .ownership-message {
    font-size: 1.15em;
    margin-bottom: 0;
    text-align: center;
}

#ownership .owners-only .ownership-explanation {
    font-family: var(--text-font-condensed);
    margin-top: 10px;
    margin-bottom: 0;
    font-size: 18px;
    color: #555;
}

/* said the way the collection box says "4 PLUGINS": small, spaced, grey */
#ownership .owners-only h2.downloads {
    margin: 3px 0 12px 0;
    padding: 0;
    border: none;
    color: #777;
    font-size: 13px;
    font-variation-settings: "opsz" 12, "wght" 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    text-align: center;
}

#ownership .owners-only h3 {
    margin-top: 0px;
}

#ownership .owners-only em {
    /* font-size: 0.9em; */
    font-variation-settings: "opsz" 12, "wght" 350, "ital" 0.5;
}

#ownership .owners-only .oob-download-notice {
    padding: 10px 0;
    font-size: 0.9em;
}

#ownership .owners-only .oob-download-notice p:last-child {
    margin-bottom: -6px !important;
}

#ownership .owners-only .oob-download-link {
    position: relative;
    display: block;
    /* border: 5px solid rgba(255, 255, 255, 0.3); */
    font-variation-settings: 'wght' 700;
    font-size: 1.1em;
    margin-bottom: 5px;
    text-decoration: none;
}

#ownership .owners-only .oob-download-link .inner {
    display: inline-block;
    background: royalblue;
    color: white;
    padding: 2px 6px;
    border: 2px solid rgba(255,255,255,0.5);
    /* box-shadow: 0 0 10px rgba(0,0,0,0.2); */
}

#ownership .owners-only .oob-download-message {
    border-top: 1px solid white;
    margin-top: 16px;
    /* padding: 20px 10px 0; */
    /* margin-top: 20px; */
    /* margin-bottom: -20px; */
}

#ownership .free-trial-box h5 {
    font-size: 24px;
    font-family: var(--text-font);
    font-variation-settings: 'wght' 400, 'ital' 1;
    margin-bottom: 2px;
}

#ownership .free-trial-box a {
    font-variation-settings: 'wght' 700;
    text-decoration: none;
}

#adv-pages {
    text-align: right;
    /* border-top: 1px solid #ddd; */
    /* margin-top: 20px; */
    margin-bottom: 60px;
    /* padding-top: 20px; */
    padding-bottom: 20px;
}

#adv-pages p {
    font-size: 0.9em !important;
}

#adv-pages .adv-page-images {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
}

#adv-pages .adv-page a {
    display: block;
    max-width: 250px;
}

#adv-pages .adv-page img {
    max-width: 100%;
}

#other-plugins {
    margin-top: 60px;
    margin-bottom: 60px;
}

#content #other-plugins li {
    margin-bottom: 0px;
    text-align: right;
}

#other-plugins .plugin-ligature {
    text-align: right;
    display: inline-block;
    border: none !important;
    text-decoration: none;
    padding: 4px 0;
}

#other-plugins .plugin-ligature span {
    color: var(--custom-color);
    font-size: 1.5em;
    padding: 2px 6px;
    font-variation-settings: "wght" 730, "opsz" 36;
}

#other-plugins span.plugin-ligature span {
    background-color: var(--custom-color);
    color: white;
}

#other-plugins a.plugin-ligature:hover span {
    background-color: var(--custom-color);
    color: white;
}