/*
 * Transposh v1.4.0 - front end language switcher
 * https://transposh.org/
 *
 * Copyright 2025, Team Transposh
 * Licensed under the GPL Version 2 or higher.
 * https://transposh.org/license
 */

/* ==================================================================== *
 * 0. what this file is
 *
 * One stylesheet for four switcher styles, a landing page and the floating
 * button. Everything is scoped to .tp-sw / .tp-sw-fab / .tp-sw__modal,
 * nothing touches a bare tag, and no rule reaches outside those three
 * roots - a language switcher that restyles a theme is worse than no
 * switcher.
 *
 * The other half of that promise is this file's real job: the component
 * must not be restyled *by* the theme either. It carries its own palette,
 * its own font, its own size, and it says so at the root instead of
 * inheriting whatever the page did to body text. The values are variables,
 * the admin screen writes different ones into an inline stylesheet, and a
 * theme that wants to override them sets them on any ancestor - so the
 * look has one owner and it is not "whatever loaded last".
 *
 * Inside the root, sizes are in em relative to --tp-sw-size. That makes
 * the font size setting a scale factor for the whole component rather
 * than a number that has to be repeated in nine places.
 * ==================================================================== */

/* -------------------------------------------------------------------- *
 * 1. tokens
 * -------------------------------------------------------------------- */

/* The dialog is moved to the end of the body by the script, because a
   wrapper with a transform drags a fixed position element along with it.
   That move takes it out of .tp-sw, so the tokens and the reset below are
   written for the dialog as well - a portalled dialog that inherits nothing
   is a dialog with a transparent background and blue links. */
.tp-sw,
.tp-sw-fab,
.tp-sw__modal {
    /* ---- the palette ------------------------------------------------
       Three colours carry the design: the accent (the language you are
       reading, the focus ring), the surface behind the component and the
       text on it. Everything else is derived from those three, so a
       colour setting is one setting and not six that have to agree.

       The admin screen replaces this block with an inline stylesheet
       carrying the saved colours; these are the values a site that never
       opened that screen gets. Every derived colour is written twice: a
       plain value first, then a color-mix() of the same name. A browser
       that cannot mix colours drops the second line at parse time and
       keeps the first, so the component is never colourless. */
    --tp-sw-accent: #2563eb;
    --tp-sw-surface: #ffffff;
    --tp-sw-fg: #16181d;

    --tp-sw-muted: #6b7280;
    --tp-sw-muted: color-mix(in srgb, var(--tp-sw-fg) 58%, var(--tp-sw-surface));
    --tp-sw-border: #e2e5ea;
    --tp-sw-border: color-mix(in srgb, var(--tp-sw-fg) 15%, transparent);
    --tp-sw-strong: #c6ccd7;
    --tp-sw-strong: color-mix(in srgb, var(--tp-sw-fg) 32%, transparent);
    --tp-sw-line: #eceef2;
    --tp-sw-line: color-mix(in srgb, var(--tp-sw-fg) 10%, transparent);
    --tp-sw-hover: #f3f4f7;
    --tp-sw-hover: color-mix(in srgb, var(--tp-sw-fg) 6%, transparent);
    --tp-sw-current: #e9effc;
    --tp-sw-current: color-mix(in srgb, var(--tp-sw-accent) 13%, transparent);

    /* ---- the geometry -----------------------------------------------
       One size drives everything: the row padding, the flag, the gap.
       A theme that wants a different size sets --tp-sw-size on any
       ancestor, and the admin screen sets it for the whole site. */
    --tp-sw-size: 15px;
    --tp-sw-font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial,
        "Noto Sans", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
    --tp-sw-radius: 12px;
    --tp-sw-item-radius: 8px;
    --tp-sw-trigger-radius: calc(var(--tp-sw-radius) * 1.6);
    --tp-sw-pad-y: 0.45em;
    --tp-sw-pad-x: 0.6em;
    --tp-sw-gap: 0.3em;
    --tp-sw-row: calc(1.45em + var(--tp-sw-pad-y) * 2);
    --tp-sw-flag-radius: 3px;
    --tp-sw-shadow: 0 18px 40px -20px rgba(12, 16, 24, 0.42), 0 2px 8px rgba(12, 16, 24, 0.06);
    --tp-sw-speed: 140ms;

    /* ---- the lock ---------------------------------------------------
       What follows is the difference between a component and a fragment
       of the page's own markup. A language switcher is dropped into a
       header, a footer, a sidebar and the middle of an article; in all
       four places it should look the same, because it is the same
       control. Inheriting a theme's font, size, line height, letter
       spacing and text alignment made it look like whatever the theme
       did to body text that day - one theme's 15px/1.4 became another's
       18px/2.1, and a control built for one line grew to two.

       So the root states all of it. The values are the component's own,
       and the admin screen writes different ones into the variables
       above, which is the only way they change. */
    color: var(--tp-sw-fg);
    font-family: var(--tp-sw-font);
    font-size: var(--tp-sw-size);
    font-weight: 400;
    font-style: normal;
    font-variant: normal;
    line-height: 1.45;
    letter-spacing: normal;
    word-spacing: normal;
    text-transform: none;
    text-align: start;
    text-indent: 0;
    text-shadow: none;
    white-space: normal;
    background: none;
    border: 0;
    margin: 0;
    padding: 0;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

/* ---- the guard -----------------------------------------------------
 *
 * The root can state its own font and colour, but the elements inside it
 * are still anchors, buttons, lists and images, and a theme styles those
 * by tag and by container: `.entry-content a`, `li`, `ul li a:hover`. A
 * themed link is a coloured, underlined, often bold piece of text, and
 * every language in the switcher is a link - so the one thing this file
 * must win is "how a link looks".
 *
 * Zero specificity (:where) is the right tool for everything the theme
 * does not set. It is the wrong tool for colour and text decoration: a
 * theme's `.entry-content a` is one class and one tag, which beats every
 * single-class rule here, and a reset that ties with it is decided by
 * which file the browser read last. Those four properties are therefore
 * declared important, and everything a component legitimately varies is
 * read from a variable the component sets on itself: --tp-sw-el-fg for the
 * colour, --tp-sw-el-pad, --tp-sw-el-border, --tp-sw-el-radius and
 * --tp-sw-el-bg for the rest. A variable has no specificity, so the guard
 * reads it without needing to know which component it is guarding, and a
 * theme's `.entry-content button` cannot outrank a value that is not
 * competing with it.
 *
 * That last part is not theoretical: a theme that sets a button's padding
 * and border paints a red 2px frame around the trigger, and 12px of padding
 * on each side of a control built for 7. Through the variable the frame is
 * whatever the component says it is.
 *
 * What is left at normal weight is what no theme sets on a link. */
:where(.tp-sw, .tp-sw-fab, .tp-sw__modal) :where(a, button) {
    color: var(--tp-sw-el-fg, inherit) !important;
    padding: var(--tp-sw-el-pad, 0) !important;
    border: var(--tp-sw-el-border, 0) !important;
    border-radius: var(--tp-sw-el-radius, 0) !important;
    background-color: var(--tp-sw-el-bg, transparent) !important;
    text-decoration: none !important;
    text-transform: none !important;
    text-shadow: none !important;
    /* a theme that underlines links with a gradient paints it as a
       background image, which survives "text-decoration: none" */
    background-image: none !important;
    font: inherit;
    letter-spacing: inherit;
    word-spacing: normal;
    text-align: inherit;
    margin: 0;
    box-shadow: none;
    cursor: pointer;
    -webkit-appearance: none;
    appearance: none;
}

:where(.tp-sw, .tp-sw-fab, .tp-sw__modal) :where(a):hover,
:where(.tp-sw, .tp-sw-fab, .tp-sw__modal) :where(a):focus,
:where(.tp-sw, .tp-sw-fab, .tp-sw__modal) :where(a):visited {
    text-decoration: none !important;
    background-image: none !important;
}

/* A list with a bullet next to every language, and a list indented by
   two em, is the single most common way a theme breaks this component -
   `.entry-content ul` outranks a bare class, so the three properties
   that carry the damage insist. No rule below gives a list a margin, a
   padding or a marker, so nothing here is taken away from the design. */
:where(.tp-sw, .tp-sw-fab, .tp-sw__modal) :where(ul, ol) {
    list-style: none !important;
    margin: 0 !important;
    padding: 0 !important;
}

:where(.tp-sw, .tp-sw-fab, .tp-sw__modal) :where(li) {
    margin: 0 !important;
    padding: 0 !important;
    list-style: none !important;
}

:where(.tp-sw, .tp-sw-fab, .tp-sw__modal) :where(p) {
    margin: 0;
    padding: 0;
}

:where(.tp-sw, .tp-sw-fab, .tp-sw__modal) :where(img, svg) {
    display: block;
    border: 0;
    box-shadow: none;
    vertical-align: middle;
}

:where(.tp-sw, .tp-sw-fab, .tp-sw__modal) :where(svg) {
    inline-size: 1em;
    block-size: 1em;
}

/* the root and everything in it count the same way, whatever the theme
   does with box-sizing */
.tp-sw,
.tp-sw-fab,
.tp-sw__modal,
.tp-sw *,
.tp-sw-fab *,
.tp-sw__modal * {
    box-sizing: border-box;
}

/* every switcher is a positioning context for its own panel */
.tp-sw {
    position: relative;
    display: inline-block;
    max-width: 100%;
    vertical-align: middle;
}

/* -------------------------------------------------------------------- *
 * 2. the pieces every style shares
 * -------------------------------------------------------------------- */

.tp-sw__flag {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 1.5em;
    block-size: 1.05em;
    overflow: hidden;
    border-radius: var(--tp-sw-flag-radius);
    /* the flags are 16x11 pngs; a hairline keeps a white flag (jp, pl)
       from dissolving into a white panel - and on a dark surface it is
       what keeps a dark flag from dissolving into that */
    box-shadow: 0 0 0 1px #eceef2;
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--tp-sw-fg) 10%, transparent);
}

.tp-sw__flag-img {
    inline-size: 100%;
    block-size: 100%;
    object-fit: cover;
    display: block;
}

/* a language with no picture file: two letters, same footprint */
.tp-sw__mono {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 100%;
    block-size: 100%;
    font-size: 0.7em;
    font-weight: 700;
    letter-spacing: 0.02em;
    color: var(--tp-sw-muted);
    background: var(--tp-sw-hover);
}

.tp-sw__text {
    display: inline-flex;
    align-items: baseline;
    gap: 0.4em;
    /* without this a long native name sets the floor for the whole row, and
       in a grid track it silently spills over the card it belongs to */
    min-inline-size: 0;
}

/* "azərbaycan dili" is one word of nineteen characters, and a card is 150
   pixels wide. Every name can be cut with an ellipsis - the title attribute
   and the link itself still say what it is. */
.tp-sw__native,
.tp-sw__en {
    min-inline-size: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* the English name is the translation aid, not the label: smaller, and
   never the thing that pushes a row to two lines */
.tp-sw__en {
    font-size: 0.84em;
    color: var(--tp-sw-muted);
}

.tp-sw__check {
    flex: 0 0 auto;
    display: inline-flex;
    margin-inline-start: auto;
    color: var(--tp-sw-muted);
}

.tp-sw__check svg {
    inline-size: 1em;
    block-size: 1em;
}

.tp-sw__code {
    margin-inline-start: auto;
    font-size: 0.7em;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--tp-sw-muted);
}

/* one language in a list */
.tp-sw__item {
    --tp-sw-el-pad: var(--tp-sw-pad-y) var(--tp-sw-pad-x);
    --tp-sw-el-radius: var(--tp-sw-item-radius);
    display: flex;
    align-items: center;
    gap: var(--tp-sw-gap);
    min-inline-size: 0;
    cursor: pointer;
}

.tp-sw__item:hover {
    --tp-sw-el-bg: var(--tp-sw-hover);
}

/* the browser's default ring is a black rectangle on a rounded card, and
   inside a grid it reads as a selected state rather than a focused one */
.tp-sw__item:focus-visible {
    --tp-sw-el-bg: var(--tp-sw-hover);
    outline: 2px solid var(--tp-sw-accent);
    outline-offset: -2px;
}

.tp-sw__item.is-current {
    --tp-sw-el-bg: var(--tp-sw-current);
    font-weight: 600;
}

.tp-sw__item.is-current .tp-sw__check {
    color: var(--tp-sw-accent);
}

.tp-sw__item.is-current .tp-sw__en {
    color: var(--tp-sw-muted);
    font-weight: 400;
}

/* -------------------------------------------------------------------- *
 * 3. the trigger (dropdown and modal both open with one)
 * -------------------------------------------------------------------- */

.tp-sw__trigger {
    --tp-sw-el-pad: calc(var(--tp-sw-pad-y) * 0.9) calc(var(--tp-sw-pad-x) * 1.15);
    --tp-sw-el-border: 1px solid var(--tp-sw-border);
    --tp-sw-el-radius: var(--tp-sw-trigger-radius);
    --tp-sw-el-bg: var(--tp-sw-surface);
    display: inline-flex;
    align-items: center;
    gap: 0.5em;
    max-inline-size: 100%;
    color: var(--tp-sw-fg);
    cursor: pointer;
    transition: border-color var(--tp-sw-speed) ease, box-shadow var(--tp-sw-speed) ease;
}

.tp-sw__trigger:hover {
    --tp-sw-el-border: 1px solid var(--tp-sw-strong);
    --tp-sw-el-border: 1px solid color-mix(in srgb, var(--tp-sw-accent) 45%, var(--tp-sw-border));
}

.tp-sw__trigger:focus-visible {
    outline: 2px solid var(--tp-sw-accent);
    outline-offset: 2px;
}

.tp-sw__trigger-text {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.tp-sw__caret {
    flex: 0 0 auto;
    display: inline-flex;
    color: var(--tp-sw-muted);
    transition: transform var(--tp-sw-speed) ease;
}

.tp-sw.is-open .tp-sw__caret {
    transform: rotate(180deg);
}

.tp-sw__globe {
    flex: 0 0 auto;
    display: inline-flex;
}

/* -------------------------------------------------------------------- *
 * 4. dropdown panel
 * -------------------------------------------------------------------- */

.tp-sw__pop {
    position: absolute;
    z-index: 90;
    inset-inline-start: 0;
    inset-block-start: calc(100% + 0.45em);
    min-inline-size: 100%;
    inline-size: max-content;
    max-inline-size: min(22em, calc(100vw - 2em));
    padding: calc(var(--tp-sw-gap) + 0.05em);
    border: 1px solid var(--tp-sw-border);
    border-radius: var(--tp-sw-radius);
    background: var(--tp-sw-surface);
    color: var(--tp-sw-fg);
    box-shadow: var(--tp-sw-shadow);
    opacity: 0;
    transform: translateY(-0.25em);
    transition: opacity var(--tp-sw-speed) ease, transform var(--tp-sw-speed) ease;
}

.tp-sw.is-open .tp-sw__pop {
    opacity: 1;
    transform: none;
}

.tp-sw__list {
    max-inline-size: 100%;
    overscroll-behavior: contain;
}

/* The scroll mode: the panel stops at N rows and scrolls inside. One row is
   the row padding twice plus a line of text, which is exactly what
   --tp-sw-row is, so N rows is a multiplication at any size and in any
   density. The script overwrites it with the measured height, which is
   exact even when a theme has changed something this file does not know
   about. */
.tp-sw[data-overflow="scroll"] .tp-sw__list,
.tp-sw-fab[data-overflow="scroll"] .tp-sw__list {
    overflow-y: auto;
    scrollbar-width: thin;
    max-block-size: calc(var(--tp-sw-rows, 6) * var(--tp-sw-row));
}

.tp-sw__list .tp-sw__item {
    white-space: nowrap;
}

/* -------------------------------------------------------------------- *
 * 5. inline row
 * -------------------------------------------------------------------- */

.tp-sw--inline {
    display: block;
}

/* A grid and a landing page are widths, not inline tokens. As inline blocks
   they shrank to the width of their own content, and `auto-fill` then had
   room for exactly one column - eight languages in a single file, which is
   what a grid is for. They take the width of the place they are put. */
.tp-sw--grid,
.tp-sw--landing {
    display: block;
    inline-size: 100%;
}

.tp-sw__inline-wrap {
    max-inline-size: 100%;
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: thin;
}

.tp-sw__inline {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.15em 0;
}

.tp-sw__inline li {
    display: flex;
    align-items: center;
}

/* "English Afrikaans Shqip" reads as one long word. A hairline of the
   current text colour separates the names without adding a decoration a
   theme would have to agree with. */
.tp-sw__inline li + li::before {
    content: "";
    flex: 0 0 auto;
    inline-size: 1px;
    block-size: 1em;
    background: currentColor;
    opacity: 0.18;
}

.tp-sw__inline .tp-sw__item {
    --tp-sw-el-pad: calc(var(--tp-sw-pad-y) * 0.66) calc(var(--tp-sw-pad-x) * 0.92);
    gap: calc(var(--tp-sw-gap) * 0.75);
}

/* With the fold mode the row wraps and the rest is behind the more button.
   With scroll it becomes one strip that slides sideways - and a strip needs
   a fade at the edge to say so, because a scrollbar under a two line high
   row takes as much room as the row itself. */
.tp-sw[data-overflow="scroll"] .tp-sw__inline-wrap {
    -webkit-mask-image: linear-gradient(to right, transparent 0, #000 0.5em, #000 calc(100% - 1.6em), transparent 100%);
    mask-image: linear-gradient(to right, transparent 0, #000 0.5em, #000 calc(100% - 1.6em), transparent 100%);
}

.tp-sw[data-overflow="scroll"] .tp-sw__inline {
    flex-wrap: nowrap;
}

.tp-sw[data-overflow="scroll"] .tp-sw__inline .tp-sw__item {
    white-space: nowrap;
}

/* -------------------------------------------------------------------- *
 * 6. modal
 * -------------------------------------------------------------------- */

.tp-sw__modal {
    position: fixed;
    inset: 0;
    z-index: 100000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1.5em;
}

.tp-sw__modal[hidden] {
    display: none;
}

.tp-sw__scrim {
    position: absolute;
    inset: 0;
    /* a plain translucent sheet, not a blurred one. Backdrop blur is pretty
       on a still photo and expensive on a page that scrolls under a thumb;
       worse, a browser that composites it on the cpu (any phone from before
       about 2019) redraws the whole page behind the dialog on every frame. */
    background: rgba(12, 16, 24, 0.56);
}

.tp-sw__dialog {
    position: relative;
    display: flex;
    flex-direction: column;
    /* wide enough for three columns of cards, which is what makes a long
       list scannable instead of a scroll with two words per row */
    inline-size: min(40em, 100%);
    max-block-size: min(78vh, 40em);
    border-radius: 16px;
    background: var(--tp-sw-surface);
    color: var(--tp-sw-fg);
    box-shadow: 0 40px 80px -30px rgba(9, 12, 20, 0.6);
    overflow: hidden;
}

.tp-sw__dialog-head {
    display: flex;
    align-items: center;
    gap: 1em;
    padding: 1.05em 1.1em 0.85em;
    border-block-end: 1px solid var(--tp-sw-line);
}

/* the dialog's title is an h2, and a theme's `.entry-content h2` is 2em
   uppercase serif - the type of a heading is insisted on for the same
   reason the landing page's label is */
.tp-sw__dialog-title {
    margin: 0 !important;
    font-family: inherit !important;
    font-size: 1.06em !important;
    font-weight: 650 !important;
    line-height: 1.3 !important;
    letter-spacing: normal !important;
    text-transform: none !important;
    color: inherit !important;
}

.tp-sw__close {
    --tp-sw-el-fg: var(--tp-sw-muted);
    --tp-sw-el-radius: 50%;
    margin-inline-start: auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 2em;
    block-size: 2em;
    color: var(--tp-sw-muted);
    cursor: pointer;
}

.tp-sw__close:hover {
    --tp-sw-el-fg: var(--tp-sw-fg);
    --tp-sw-el-bg: var(--tp-sw-hover);
}

.tp-sw__dialog-body {
    padding: 0.9em;
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: thin;
}

/* cards inside the dialog: two columns on a phone, three on a desk */
.tp-sw__cards {
    display: grid;
    grid-template-columns: repeat(var(--tp-sw-cols, auto-fill), minmax(11em, 1fr));
    gap: var(--tp-sw-gap);
}

.tp-sw__cards .tp-sw__item {
    --tp-sw-el-border: 1px solid transparent;
    --tp-sw-el-pad: calc(var(--tp-sw-pad-y) * 1.2) var(--tp-sw-pad-x);
}

/* two lines in a card, one line in a row: a card has the height to spare and
   the two names are easier to compare stacked than side by side in 150px */
.tp-sw__cards .tp-sw__text {
    flex-direction: column;
    align-items: flex-start;
    gap: 0;
}

.tp-sw__cards .tp-sw__item.is-current {
    --tp-sw-el-border: 1px solid var(--tp-sw-strong);
    --tp-sw-el-border: 1px solid color-mix(in srgb, var(--tp-sw-accent) 45%, var(--tp-sw-border));
    --tp-sw-el-bg: var(--tp-sw-current);
    font-weight: 500;
}

/* The modal in scroll mode: the grid is cut to the number of languages the
   settings ask for and scrolls inside. The height is set in pixels by the
   script, because a card grid has as many rows as the column count makes of
   the count - an em guess here would be wrong on every width. Without the
   script the grid is simply not cut, which is the honest fallback. */
.tp-sw[data-overflow="scroll"] .tp-sw__cards {
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: thin;
    padding-inline-end: 0.2em;
}

/* -------------------------------------------------------------------- *
 * 7. grid on the page
 * -------------------------------------------------------------------- */

/* a landing page may title the list, and that title is a heading. A
   theme's h2 is 2em, serif and spaced for an article - the properties
   that make it one are therefore insisted on, or the label arrives twice
   the size of the names it labels */
.tp-sw__title {
    margin: 0 0 0.5em !important;
    font-family: inherit !important;
    font-size: 0.95em !important;
    font-weight: 650 !important;
    line-height: 1.3 !important;
    letter-spacing: normal !important;
    text-transform: none !important;
    color: var(--tp-sw-muted) !important;
}

.tp-sw__grid {
    display: grid;
    grid-template-columns: repeat(var(--tp-sw-cols, auto-fill), minmax(10em, 1fr));
    gap: calc(var(--tp-sw-gap) * 1.15);
    max-inline-size: 100%;
}

.tp-sw__grid .tp-sw__item {
    --tp-sw-el-border: 1px solid var(--tp-sw-border);
    --tp-sw-el-pad: calc(var(--tp-sw-pad-y) * 1.2) calc(var(--tp-sw-pad-x) * 1.08);
    /* a card on the page draws its own surface. On a white page that is
       white and changes nothing; on a dark palette it is the only thing
       between the light text and the paper. */
    --tp-sw-el-bg: var(--tp-sw-surface);
}

.tp-sw__grid .tp-sw__item.is-current {
    font-weight: 600;
}

.tp-sw[data-overflow="scroll"] .tp-sw__grid {
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: thin;
}

/* -------------------------------------------------------------------- *
 * 8. the landing page list
 * -------------------------------------------------------------------- */

.tp-sw--landing.tp-sw--page {
    display: block;
    inline-size: 100%;
}

.tp-sw__cards--page {
    display: grid;
    grid-template-columns: repeat(var(--tp-sw-cols, auto-fill), minmax(10.5em, 1fr));
    gap: calc(var(--tp-sw-gap) * 2.4);
}

.tp-sw__card {
    --tp-sw-el-pad: 0.95em 1em;
    --tp-sw-el-border: 1px solid var(--tp-sw-border);
    --tp-sw-el-radius: var(--tp-sw-radius);
    --tp-sw-el-bg: var(--tp-sw-surface);
    display: flex;
    align-items: center;
    gap: 0.75em;
    block-size: 100%;
    color: var(--tp-sw-fg);
    transition: border-color var(--tp-sw-speed) ease, transform var(--tp-sw-speed) ease, box-shadow var(--tp-sw-speed) ease;
}

.tp-sw__card:hover,
.tp-sw__card:focus-visible {
    --tp-sw-el-border: 1px solid var(--tp-sw-strong);
    --tp-sw-el-border: 1px solid color-mix(in srgb, var(--tp-sw-accent) 45%, var(--tp-sw-border));
    box-shadow: 0 10px 24px -18px rgba(12, 16, 24, 0.5);
    transform: translateY(-1px);
}

.tp-sw__card:focus-visible {
    outline: 2px solid var(--tp-sw-accent);
    outline-offset: 2px;
}

.tp-sw__card .tp-sw__flag {
    inline-size: 1.9em;
    block-size: 1.33em;
}

.tp-sw__card-text {
    display: flex;
    flex-direction: column;
    gap: 0.1em;
    min-inline-size: 0;
}

/* A landing card is the page's content, not a control in a header: a name
   that needs two lines gets two lines, and the cards in the row grow to
   match. An ellipsis here would hide the one thing the visitor is looking
   for. */
.tp-sw__card .tp-sw__native {
    font-size: 1.02em;
    font-weight: 600;
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
}

.tp-sw__card .tp-sw__en {
    font-size: 0.82em;
}

.tp-sw__card.is-current,
.tp-sw__card[aria-current="true"] {
    --tp-sw-el-border: 1px solid var(--tp-sw-strong);
    --tp-sw-el-border: 1px solid color-mix(in srgb, var(--tp-sw-accent) 45%, var(--tp-sw-border));
    --tp-sw-el-bg: var(--tp-sw-current);
}

/* -------------------------------------------------------------------- *
 * 9. "show all"
 * -------------------------------------------------------------------- */

.tp-sw__more {
    --tp-sw-el-fg: var(--tp-sw-muted);
    --tp-sw-el-pad: 0.55em 0.6em;
    --tp-sw-el-radius: 0 0 var(--tp-sw-item-radius) var(--tp-sw-item-radius);
    display: block;
    inline-size: 100%;
    margin-block-start: 0.3em;
    /* the hairline above it is a shadow and not a border: a border here
       would be cancelled by the guard, which owns that property now */
    box-shadow: inset 0 1px 0 var(--tp-sw-line);
    color: var(--tp-sw-muted);
    font-size: 0.9em;
    text-align: center;
    cursor: pointer;
}

.tp-sw__more:hover,
.tp-sw__more:focus-visible {
    --tp-sw-el-fg: var(--tp-sw-fg);
    --tp-sw-el-bg: var(--tp-sw-hover);
}

.tp-sw--inline .tp-sw__more,
.tp-sw--grid .tp-sw__more,
.tp-sw--landing .tp-sw__more {
    --tp-sw-el-pad: 0.5em 0.9em;
    --tp-sw-el-border: 1px solid var(--tp-sw-border);
    --tp-sw-el-radius: var(--tp-sw-trigger-radius);
    inline-size: auto;
    margin-block-start: 0.6em;
    box-shadow: none;
    font-size: 0.88em;
}

/* -------------------------------------------------------------------- *
 * 10. the floating button
 * -------------------------------------------------------------------- */

.tp-sw-fab {
    position: fixed;
    z-index: 9990;
    display: flex;
    flex-direction: column;
    gap: 0.6em;
    font-size: var(--tp-sw-size, 15px);
    color: var(--tp-sw-fg);
}

.tp-sw-fab--bottom-right {
    inset-block-end: 1.25em;
    inset-inline-end: 1.25em;
    align-items: flex-end;
}

.tp-sw-fab--bottom-left {
    inset-block-end: 1.25em;
    inset-inline-start: 1.25em;
    align-items: flex-start;
}

.tp-sw-fab--top-right {
    inset-block-start: 1.25em;
    inset-inline-end: 1.25em;
    align-items: flex-end;
}

.tp-sw-fab--top-left {
    inset-block-start: 1.25em;
    inset-inline-start: 1.25em;
    align-items: flex-start;
}

.tp-sw-fab__btn {
    --tp-sw-el-border: 1px solid var(--tp-sw-border);
    --tp-sw-el-radius: 50%;
    --tp-sw-el-bg: var(--tp-sw-surface);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 3em;
    block-size: 3em;
    color: var(--tp-sw-fg);
    box-shadow: 0 14px 30px -14px rgba(15, 23, 42, 0.5), 0 2px 6px rgba(15, 23, 42, 0.08);
    cursor: pointer;
    transition: transform var(--tp-sw-speed) ease, box-shadow var(--tp-sw-speed) ease;
}

.tp-sw-fab__btn:hover {
    transform: translateY(-1px);
    box-shadow: 0 18px 34px -14px rgba(15, 23, 42, 0.55), 0 2px 6px rgba(15, 23, 42, 0.1);
}

.tp-sw-fab__btn:focus-visible {
    outline: 2px solid currentColor;
    outline-offset: 3px;
}

.tp-sw-fab__btn .tp-sw__flag {
    inline-size: 1.75em;
    block-size: 1.24em;
    border-radius: 3px;
}

.tp-sw-fab__btn .tp-sw__mono {
    border-radius: 50%;
}

.tp-sw-fab__btn svg {
    inline-size: 1.35em;
    block-size: 1.35em;
    color: var(--tp-sw-muted);
}

.tp-sw-fab__panel {
    order: -1;
    min-inline-size: 12.5em;
    max-inline-size: min(20em, calc(100vw - 2.5em));
    padding: 0.4em;
    border: 1px solid var(--tp-sw-border);
    border-radius: var(--tp-sw-radius);
    background: var(--tp-sw-surface);
    color: var(--tp-sw-fg);
    box-shadow: var(--tp-sw-shadow);
    opacity: 0;
    transform: translateY(0.35em);
    transition: opacity var(--tp-sw-speed) ease, transform var(--tp-sw-speed) ease;
}

.tp-sw-fab--top-left .tp-sw-fab__panel,
.tp-sw-fab--top-right .tp-sw-fab__panel {
    order: 1;
    transform: translateY(-0.35em);
}

.tp-sw-fab.is-open .tp-sw-fab__panel {
    opacity: 1;
    transform: none;
}

.tp-sw-fab__head {
    margin: 0.2em 0.5em 0.45em;
    font-size: 0.8em;
    font-weight: 650;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--tp-sw-muted);
}

.tp-sw-fab__panel .tp-sw__list {
    max-block-size: min(52vh, 21em);
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: thin;
}

/* the two switches that retire the button on a kind of screen. 782px is
   the breakpoint wordpress itself uses for "the admin bar is narrow now",
   so a site that already reasons about that number agrees with this one */
@media (min-width: 783px) {
    .tp-sw-fab.is-hide-desktop {
        display: none;
    }
}

@media (max-width: 782px) {
    .tp-sw-fab.is-hide-mobile {
        display: none;
    }
}

/* -------------------------------------------------------------------- *
 * 11. small screens
 * -------------------------------------------------------------------- */

@media (max-width: 600px) {
    .tp-sw__modal {
        padding: 0;
        align-items: flex-end;
    }

    .tp-sw__dialog {
        inline-size: 100%;
        max-block-size: 82vh;
        border-end-start-radius: 0;
        border-end-end-radius: 0;
    }

    .tp-sw__cards {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .tp-sw__cards--page {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 0.5em;
    }

    .tp-sw__card {
        padding: 0.8em;
    }
}

/* -------------------------------------------------------------------- *
 * 12. respect the visitor
 * -------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
    .tp-sw *,
    .tp-sw-fab * {
        transition-duration: 0.01ms !important;
        animation-duration: 0.01ms !important;
    }
}

/* The fold, and every panel, is hidden with the hidden attribute. Our own
   display rules are more specific than the browser's [hidden] {display:none}
   - .tp-sw__inline li is a flex row - so the attribute loses unless it is
   allowed to insist. One !important here beats sprinkling it on every
   display rule that might one day collide. */
.tp-sw [hidden],
.tp-sw-fab [hidden],
.tp-sw__modal[hidden] {
    display: none !important;
}

/* a page that carries the switcher sets this on the modal while it is open */
body.tp-sw-locked {
    overflow: hidden;
}
