/* ==========================================================================
   Shared "YoRHa" design system, loaded on every page. Page stylesheets
   (home.css, events.css, ...) read these variables and must not redefine them.

   The look is a flat blue-white paper desktop in the spirit of the
   NieR:Automata UI: a faint line-art layer, a row of equal flat tabs on top,
   thin dashed chevron bands, windows with a dark blue title strip and a pale
   body, hairline borders, no shadows, no gradients, no radius. Everything
   sits on an 8px grid with one gutter (--yh-g).

   Palette (one token set, six section tints):
     paper / ink       the bluish white-grey base and the dark blue ink
     light blue        sky / video tint            (--yh-blue)
     green             sage from the video hills   (--yh-green)
     ONE contrast      --yh-accent, a vibrant blue (hue 215-230, never violet);
                       swap this single variable (and --yh-accent-ink /
                       --yh-accent-hi / -deep) to recolour every active mark and
                       primary button.
     ONE alarm         --yh-danger (+ -ink / -hi / -wash / -deep), a brick red:
                       errors, destructive buttons and danger states only.
   Pure CSS and inline SVG; the only bundled
   assets are the fonts in /fonts (OFL, see public/fonts/LICENSES.md), the sig
   pictogram sprite and the home video: no CDNs.
   ========================================================================== */

/* ---------- type: Inter Tight (a tight neo-grotesk, one variable file per subset, light to semibold for titles) and
   JetBrains Mono, each as a latin + cyrillic subset, so Russian text never falls back ---------- */

@font-face {
  font-family: "Inter Tight";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/fonts/inter-tight-cyrillic-wght-normal.woff2") format("woff2");
  unicode-range: U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116;
}

@font-face {
  font-family: "Inter Tight";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/fonts/inter-tight-latin-wght-normal.woff2") format("woff2");
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}

/* the ruble sign (the donation totals), one glyph cut from Inter Tight's latin-ext subset, so it matches the letters */
@font-face {
  font-family: "Inter Tight";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/fonts/inter-tight-currency-wght-normal.woff2") format("woff2");
  unicode-range: U+20BD;
}

@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/jetbrains-mono-cyrillic-400-normal.woff2") format("woff2");
  unicode-range: U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116;
}

@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/jetbrains-mono-latin-400-normal.woff2") format("woff2");
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}

@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("/fonts/jetbrains-mono-cyrillic-700-normal.woff2") format("woff2");
  unicode-range: U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116;
}

@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("/fonts/jetbrains-mono-latin-700-normal.woff2") format("woff2");
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}

:root {
  /* ---- YoRHa palette ---- */
  --yh-paper: #e3e9ef;          /* the page */
  --yh-paper-hi: #f4f7fa;       /* a window lying on it, input fill */
  --yh-paper-bright: #f8fafc;   /* /account: the page lifted towards white */
  --yh-dots-quiet: #e6ebf0;     /* /account: the dotted texture, a tone off the bright paper (1.15:1) */
  --yh-ink-deep: #2d4059;       /* /account: soft text, 10:1 on the plates */
  --yh-plate-note: #eef2f6;     /* /account: a note's plate */
  --yh-paper-lo: #d0d9e2;       /* list rows, tabs, bars */
  --yh-paper-deep: #b8c4d1;     /* hairline fills, track of a scrollbar */
  --yh-paper-top: #fafcfd;      /* an input under the pointer */
  --yh-ink: #1e3049;            /* text, borders, title strips */
  --yh-ink-soft: #3f5272;       /* secondary text (>= 5:1 on paper and on the rows) */
  --yh-ink-mute: #71819b;       /* hairlines and quiet icons (>= 3:1 on paper) */
  --yh-blue: #bcd3e6;           /* sky tint */
  --yh-blue-deep: #5f8fc0;
  --yh-green: #a9bd98;          /* sage tint */
  --yh-green-deep: #6f8c5e;
  --yh-green-ink: #3a5a30;
  --yh-accent: #1f5cf0;         /* THE contrast colour: change it here (+ the two below) */
  --yh-accent-ink: #1a4bc8;     /* the accent as small text on paper (>= 4.5:1) */
  --yh-accent-hi: #6f9bff;      /* the accent as a mark on the dark ink (>= 3:1) */
  --yh-on-accent: #ffffff;      /* text on a filled accent (>= 5:1) */
  --yh-accent-deep: #10286a;    /* the deepest blue: the dark end of the glossy picker */
  --yh-accent-lit: #8cadff;     /* the vivid blue the home chrome turns while the big button is lit: tabs, status strip (ink on it >= 5:1) */
  --yh-accent-wash: #d3e0ff;    /* its pale wash: the paper round the footer and the account tab, the frame plate */
  /* the DANGER family: a clear brick / signal red (hue 8-12, orange-leaning: never pink or magenta). Only errors, destructive
     buttons and danger states use it (the error rows, a field that failed validation, the admin delete, "убрать"):
     tests/palette.test.js checks both the hues and where it is used. The accent blue stays "active / primary". */
  --yh-danger: #c4361f;         /* the mark / border / fill of a danger state (white on it 5.4:1) */
  --yh-danger-ink: #a82a15;     /* danger as small text on paper, panels and rows (>= 4.9:1) */
  --yh-danger-hi: #ff8466;      /* danger as a mark on the dark ink (>= 5:1) */
  --yh-danger-wash: #fbe6e1;    /* the error row's fill */
  --yh-danger-deep: #6a1608;    /* error text on that wash (>= 10:1) */
  --yh-g: clamp(12px, 2.2vw, 32px);   /* the one gutter */

  /* ---- motion: the NieR vocabulary. Stepped (steps()) or short snappy curves, 120-260ms, never bouncy ---- */
  --yh-t-fast: 140ms;           /* a bullet flips, a bar slides */
  --yh-t-mid: 240ms;            /* a button's fill sweep */
  --yh-t-wipe: 360ms;           /* a title strip or a window wipes open */
  --yh-stagger: 50ms;           /* the delay between the rows of a cascade (40-60ms) */
  --yh-snap: cubic-bezier(0.2, 0.9, 0.25, 1);

  /* ---- pixel texture: 4x4 Bayer ordered dither, baked into three small SVG tiles (pixels on the grid) ----
     edge   8x6   ink pixels hanging under a title strip, dissolving into the window body (2px pixels)
     fade   16x32 paper pixels fading the top of the scene into the page (4px pixels, the video's own grain)
     ramp   64x8  a left-to-right ramp of accent-blue pixels on an ink strip (2px pixels) */
  --yh-dz-edge: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='6' viewBox='0 0 8 6' shape-rendering='crispEdges'%3E%3Cpath fill='%231e3049' d='M0 0h2v2h-2zM2 0h2v2h-2zM4 0h2v2h-2zM6 0h2v2h-2zM2 2h2v2h-2zM6 2h2v2h-2zM4 4h2v2h-2z'/%3E%3C/svg%3E");
  --yh-dz-fade: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='32' viewBox='0 0 16 32' shape-rendering='crispEdges'%3E%3Cpath fill='%23e3e9ef' d='M0 0h4v4h-4zM4 0h4v4h-4zM8 0h4v4h-4zM12 0h4v4h-4zM0 4h4v4h-4zM4 4h4v4h-4zM12 4h4v4h-4zM0 8h4v4h-4zM8 8h4v4h-4zM12 8h4v4h-4zM4 12h4v4h-4zM12 12h4v4h-4zM0 16h4v4h-4zM8 16h4v4h-4zM4 20h4v4h-4zM8 24h4v4h-4z'/%3E%3C/svg%3E");

  /* ---- type ---- */
  --yh-font: "Segoe UI", "Frutiger", "Frutiger Linotype", "Myriad Pro", "Trebuchet MS", Tahoma, sans-serif;
  --hud-display: "Inter Tight", "Helvetica Neue", Arial, "Segoe UI", sans-serif;
  --hud-mono: "JetBrains Mono", "Cascadia Mono", Consolas, "Courier New", monospace;

  /* the three tiny window controls (minimise, maximise, close) as one drawn SVG:
     hairline glyphs, no boxes, for title strips that are plain headings */
  --ax-controls: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='69' height='21' viewBox='0 0 69 21'%3E%3Cg fill='none' stroke='%23f4f7fa' stroke-width='1.200' shape-rendering='crispEdges'%3E%3Cpath d='M9 14h8'/%3E%3Crect x='32.500' y='6.500' width='8' height='8'/%3E%3Cpath d='M52 6l9 9M61 6l-9 9'/%3E%3C/g%3E%3C/svg%3E");

  /* the line-art layer: two pairs of huge circle arcs and long diagonal
     hairlines crossing the whole screen, ~8% ink, structural not decorative */
  --yh-lineart: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1600 900' preserveAspectRatio='xMidYMid slice'%3E%3Cg fill='none' stroke='%231e3049' stroke-width='1.200'%3E%3Cg stroke-opacity='.13'%3E%3Ccircle cx='-60' cy='380' r='560'/%3E%3Ccircle cx='1720' cy='1010' r='780'/%3E%3C/g%3E%3Cg stroke-opacity='.08'%3E%3Ccircle cx='-60' cy='380' r='576'/%3E%3Ccircle cx='1720' cy='1010' r='796'/%3E%3Cpath d='M-140 150L1010 1010M-40 -60L1210 880M330 -90L1600 760M820 -80L1600 520'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
  /* a dashed chevron band: dots on a line, a small V between them (tile 28x12) */
  --yh-band: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='28' height='12' viewBox='0 0 28 12'%3E%3Cg fill='none' stroke='%231e3049' stroke-width='1' shape-rendering='crispEdges'%3E%3Cpath d='M0 1.500h28' stroke-dasharray='1 3' stroke-opacity='.75'/%3E%3Cpath d='M10.500 5l3.500 4 3.500-4'/%3E%3C/g%3E%3Cpath d='M0 7.500h1M27 7.500h1' stroke='%231e3049' stroke-opacity='.6'/%3E%3C/svg%3E");
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  font-family: var(--yh-font);
  line-height: 1.6;
  color: var(--th-ink);
  background-color: var(--th-bg);
}

/* the line-art layer: fixed to the viewport, under everything, click-through */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  background: var(--yh-lineart) center / cover no-repeat;
  pointer-events: none;
}

/* Keyboard focus: a square 2px ink ring (>= 3:1 on every paper tone); dark
   surfaces switch to paper below. */
:focus-visible {
  outline: 2px solid var(--yh-ink);
  outline-offset: 2px;
}

/* No entrance animation of <body> any more (it was a 320 ms fade + 14px slide): it is the page transition's job (the rise below, or its
   fallback cover), and a second motion on the body ran again the moment the browser's own transition ended - the page "came in twice".
   Never give <body> an animation or a transform that stays: a filled-forwards transform (even an identity) would make <body> the containing
   block of position:fixed (the events modal would be page-sized). */

/* ==========================================================================
   Colour themes. <body class="theme-NAME"> (head-open.ejs) switches one small
   set of custom properties. Every theme shares the blue-white base and the ink; a
   theme only changes the section TINT (the status strip, the title-strip
   bullet, the dark fill of the active tab) and nudges the paper:
     sky (home) blue . meadow (events) green . sign (transparency) plain
     slate . cobalt (submit / vote / my submissions / edit) deeper blue .
     cyan (contact + auth) blue-green . classic (admin) plain blue-grey
   --th-bg / --th-bg2      page paper / lighter paper
   --th-panel              window body fill               --th-soft   list rows, tabs, bars
   --th-ink / -soft        text on the paper and panels   --th-accent-ink  tint as text
   --th-accent             hover fill of a tab            --th-on-accent   text on the ink / accent
   --th-chrome-a / ink     title strip fill and its text
   --th-tint / --th-tint-deep   status strip fill / bullets and rules
   --th-rule               hairline
   Every text pair is >= 4.5:1 (checked in tests/hud-header.test.js).
   ========================================================================== */

:root,
body.theme-sky {
  --th-bg: #e3e9ef;
  --th-bg2: #f4f7fa;
  --th-panel: #eef2f6;
  --th-soft: #d3dde8;
  --th-ink: #1e3049;
  --th-ink-soft: #3f5272;
  --th-accent: #2b4f9e;
  --th-accent-ink: #1a4bc8;
  --th-on-accent: #f4f7fa;
  --th-chrome-a: #1e3049;
  --th-chrome-ink: #f4f7fa;
  --th-tint: #bcd3e6;
  --th-tint-deep: #5f8fc0;
  --th-rule: rgba(30, 48, 73, 0.34);
}

body.theme-meadow {
  --th-bg: #e3ebe9;
  --th-bg2: #f3f7f5;
  --th-panel: #edf3f0;
  --th-soft: #d2dfd8;
  --th-ink: #1e3049;
  --th-ink-soft: #3f5272;
  --th-accent: #3a5a30;
  --th-accent-ink: #2f5a24;
  --th-on-accent: #f4f7fa;
  --th-chrome-a: #1e3049;
  --th-chrome-ink: #f4f7fa;
  --th-tint: #a9bd98;
  --th-tint-deep: #6f8c5e;
  --th-rule: rgba(30, 48, 73, 0.34);
}

body.theme-sign {
  --th-bg: #e4e9ee;
  --th-bg2: #f4f6f9;
  --th-panel: #eef1f5;
  --th-soft: #d5dce6;
  --th-ink: #1e3049;
  --th-ink-soft: #3f5272;
  --th-accent: #2c4268;
  --th-accent-ink: #2c4268;
  --th-on-accent: #f4f7fa;
  --th-chrome-a: #1e3049;
  --th-chrome-ink: #f4f7fa;
  --th-tint: #cbd5e2;
  --th-tint-deep: #7387a3;
  --th-rule: rgba(30, 48, 73, 0.34);
}

body.theme-cobalt {
  --th-bg: #e1e8f0;
  --th-bg2: #f2f6fa;
  --th-panel: #ecf1f7;
  --th-soft: #d0dbe8;
  --th-ink: #1e3049;
  --th-ink-soft: #3f5272;
  --th-accent: #2b4f9e;
  --th-accent-ink: #1a4bc8;
  --th-on-accent: #f4f7fa;
  --th-chrome-a: #1e3049;
  --th-chrome-ink: #f4f7fa;
  --th-tint: #b3cdea;
  --th-tint-deep: #5a8bc4;
  --th-rule: rgba(30, 48, 73, 0.34);
}

body.theme-cyan {
  --th-bg: #e2eaee;
  --th-bg2: #f3f7f9;
  --th-panel: #edf2f5;
  --th-soft: #d1dee3;
  --th-ink: #1e3049;
  --th-ink-soft: #3f5272;
  --th-accent: #2c5a62;
  --th-accent-ink: #22565e;
  --th-on-accent: #f4f7fa;
  --th-chrome-a: #1e3049;
  --th-chrome-ink: #f4f7fa;
  --th-tint: #b4d4d6;
  --th-tint-deep: #5f9aa0;
  --th-rule: rgba(30, 48, 73, 0.34);
}

body.theme-classic {
  --th-bg: #e3e8ed;
  --th-bg2: #f4f6f8;
  --th-panel: #eef1f4;
  --th-soft: #d2d9e1;
  --th-ink: #1e3049;
  --th-ink-soft: #3f5272;
  --th-accent: #1e3049;
  --th-accent-ink: #1e3049;
  --th-on-accent: #f4f7fa;
  --th-chrome-a: #1e3049;
  --th-chrome-ink: #f4f7fa;
  --th-tint: #d0d9e2;
  --th-tint-deep: #8696ab;
  --th-rule: rgba(30, 48, 73, 0.38);
}

/* themed page scrollbar (the viewport takes it from <html>) */
html:has(body.theme-sky) { scrollbar-color: #5f8fc0 #d3dde8; }
html:has(body.theme-meadow) { scrollbar-color: #6f8c5e #d2dfd8; }
html:has(body.theme-sign) { scrollbar-color: #7387a3 #d5dce6; }
html:has(body.theme-cobalt) { scrollbar-color: #5a8bc4 #d0dbe8; }
html:has(body.theme-cyan) { scrollbar-color: #5f9aa0 #d1dee3; }
html:has(body.theme-classic) { scrollbar-color: #8696ab #d2d9e1; }

/* the portfolio one-pager (/events, <body class="theme-meadow page-portfolio">): the tones of its five sections. Four of them
   are palette tones (white, dark grey, the grey-blue of LORE and, inside it, the Win9x light blue); two are the owner's named
   section colours: SUNCYCLE yellow (hue ~54) and DISCORD blurple (hue ~235). tests/palette.test.js allows exactly
   those four tokens (--pf-bg-yellow, --pf-dots-yellow, --pf-bg-blurple, --pf-dots-blurple) outside the blue / green family and
   keeps everything else forbidden. events.css reads them; tests/portfolio-page.test.js checks that neighbours differ and that
   the text on each tone is >= 4.5:1 (white on the blurple is 4.61:1: the text there is white, never lighter or thinner).
   --pf-soft-* is the quiet text / rule colour on a tone, --pf-dots-* the tone of the dot texture (portfolio-dots.js lays it over
   the section; the dots keep text and quiet text readable, worst case included, see tests/portfolio-effects.test.js). The dark
   section's dots are LIGHTER than its ground (a light dot on #2b2b2b), the others darker. */
body.page-portfolio {
  --pf-bg-yellow: #eeda41;
  --pf-hdr-blue: #017eff;         /* the blue of the SUNCYCLE 3 text (dates, the "no registration" line) */
  --pf-hdr-sky: #7da9d9;          /* the header of /events: the owner's swatch (the sky blue of the art's top edge) */
  --pf-hdr-ink: #08121f;          /* the ink on the header: 7.7:1 */
  --pf-bg-white: var(--yh-paper-hi);
  --pf-bg-blurple: #5865f2;
  --pf-bg-dark: #2b2b2b;
  --pf-bg-lore: #c3cad2;
  --pf-fg-blurple: #ffffff;
  --pf-soft-dark: #c4ccd6;
  --pf-dots-yellow: #d9c537;
  --pf-dots-white: #c5cbd3;
  --pf-dots-blurple: #505de0;
  --pf-dots-dark: #4a4a4a;
  --pf-dots-lore: #aeb7c3;
  /* the old-Windows taskbar of /events (events.css, "the footer"): the face, bevel and light-blue strip tones of the LORE window (.pf-win) */
  --pf-task-face: #dfe5ec;
  --pf-task-hi: #ffffff;
  --pf-task-shade: #8493a4;
  --pf-task-lo: #5d6a79;
  --pf-task-lit: #b3c5db;
  /* the bar itself: a dusty steel blue (grey-leaning, not the site's bright accent) with a lit top edge of the same hue family */
  --pf-task-bar: #98abc3;
  --pf-task-edge: #d0dbe8;
}

/* ==========================================================================
   The header: one slim frame on every page (the portfolio look of /events, /contact and /submit). The wordmark is the link home,
   in the top row before the tabs; the tabs are pxpush link buttons (a thin rule on top, the label at the left, an arrow at the
   right, a fill that rises on hover, a quick letter scramble: public/js/header-roll.js or the page's own script); under them the
   status strip (hairline rules, no fill) and the account chip. There is no title / subtitle / back row and no dashed band: the
   page's own <h1> carries its title. Markup: views/partials/header.ejs, hud-top.ejs, nav.ejs. <header> is a grid of:
   logo | tabs / status strip | account chip; .hud-top and .hud-main only group the markup (display: contents).

   The header takes the colour of the page it sits on, so header and page read as ONE surface. It reads these custom properties
   of <body>; the defaults below are the theme's page paper, a page that sits on another colour sets them on its body class
   (events.css: the yellow of SUNCYCLE; contact.css: the navy; submit.css: the dark band of the picker; home.css: the scene's sky):
     --hdr-bg        the colour of the page under the header (what every text below is measured against)
     --hdr-paint     what the header actually paints: transparent on the paper pages (so the line-art layer runs on
                     behind it), the page colour itself where the page is a flat colour
     --hdr-fg        wordmark, tab labels, account name, status text, focus ring (>= 4.5:1 on --hdr-bg)
     --hdr-soft      the quiet text (the account chip; >= 4.5:1 on --hdr-bg)
     --hdr-line      the hairlines: the tabs' top rules, the strip's rules, the chip's rule
     --hdr-fill / --hdr-fill-fg   the fill that rises behind a hovered tab and the current tab, and the text over it
     --hdr-hover     the wordmark on hover (>= 4.5:1 on --hdr-bg)
     --hdr-led       the lit square of an open status
     --hdr-cta-ring  a hairline round the bright-blue call-to-action tab where the blue would melt into the page (dark headers)
   tests/header-colours.test.js computes every pair for every page. ========================================================================== */

/* The header's METRICS: the one place that sizes it (tests/header-geometry.test.js: no page stylesheet sets a size, a gap, a padding or a margin
   on a header selector, nor redefines these tokens; the pages only choose COLOURS, in the --hdr-* custom properties below). The home page's
   header (home.css) lays the same parts out on its stage grid with these same tokens. */
:root {
  --hdr-pad-t: 10px;          /* above the tab row */
  --hdr-pad-b: 12px;          /* under the status strip */
  --hdr-col-gap: 12px;        /* between the wordmark, the tabs / strip and the chip */
  --hdr-tab-h: 34px;          /* a tab */
  --hdr-tab-gap: 4px;         /* between two tabs */
  --hdr-tab-px: 10px;
  --hdr-tab-fs: 11.52px;       /* px, not rem: the home page scales the root size on big screens, the header must not change with it */
  --hdr-logo-fs: clamp(1rem, 1.6vw, 1.25rem);
  --hdr-row-gap: 6px;         /* between the tab row and the strip / the chip */
  --hdr-strip-h: 28px;        /* the status strip and the chip: one height, one centre line */
  --hdr-bar-py: 4px;
  --hdr-bar-gap: 2px 14px;
  --hdr-bar-fs: 11.2px;
  --hdr-chip-w: 360px;        /* the account chip: the same width for a guest, a member and an admin; a long address is clipped */
  --hdr-chip-gap: 10px;
  --hdr-chip-pl: 12px;
  --hdr-chip-fs: 11.52px;
  --hdr-btn-px: 12px;         /* the logout button */
  --hdr-gap: 8px;             /* the header's lower edge to the page's own first block (.hud-fill, auth, ledger) */
}

body {
  --hdr-bg: var(--th-bg);
  --hdr-paint: transparent;
  --hdr-fg: var(--th-ink);
  --hdr-soft: var(--th-ink-soft);
  --hdr-line: var(--th-ink);
  --hdr-fill: var(--th-ink);
  --hdr-fill-fg: var(--th-on-accent);
  --hdr-hover: var(--th-accent-ink);
  --hdr-led: var(--yh-accent);
  --hdr-cta-ring: transparent;
  /* The footer takes the page's colour the same way (see "The footer" below). By default it reads the header's own properties (a var() on
     <body> resolves against the body's computed values, so a page that sets --hdr-* gets its footer for free); a page whose footer is
     not the header's colour (home, /events) sets --ftr-* itself. */
  --ftr-bg: var(--hdr-bg);
  --ftr-paint: var(--hdr-paint);
  --ftr-fg: var(--hdr-fg);
  --ftr-soft: var(--hdr-soft);
  --ftr-edge: var(--yh-ink-mute);
  --ftr-plate: var(--ftr-bg);
  --ftr-fill: var(--hdr-fill);
  --ftr-fill-fg: var(--hdr-fill-fg);
  --ftr-mark: var(--hdr-hover);
}

.site-header {
  position: relative;
  z-index: 10; /* below the lightbox of /events and the pop-ups */
}
.hud-top,
.hud-main {
  display: contents;
}

.site-header--compact {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) var(--hdr-chip-w);
  grid-template-areas:
    "logo nav nav"
    "bar bar chip";
  align-items: start;
  column-gap: var(--hdr-col-gap);
  width: 100%;
  max-width: none;
  margin: 0;
  padding: var(--hdr-pad-t) var(--yh-g) var(--hdr-pad-b);
  background: var(--hdr-paint);
  color: var(--hdr-fg);
}

/* the wordmark, in the top row */
.header-logo {
  grid-area: logo;
  align-self: center;
  margin-right: 4px;
  padding: 0 16px 0 0;
  color: var(--hdr-fg);
  font-family: var(--hud-display);
  font-size: var(--hdr-logo-fs);
  font-weight: 300;
  letter-spacing: 0.01em;
  line-height: 1.2;
  text-decoration: none;
  white-space: nowrap;
}
.header-logo:hover {
  color: var(--hdr-hover);
}

/* tabs: pxpush link buttons. From 1100px up the row never wraps (guest, member and admin: up to 7 tabs): the tabs shrink together
   and clip if they ever must. Below that the row wraps into more rows. */
.header-nav {
  grid-area: nav;
  display: flex;
  flex-wrap: wrap;
  gap: var(--hdr-tab-gap);
  min-width: 0;
}
@media (min-width: 1100px) {
  .header-nav {
    flex-wrap: nowrap;
  }
}
.header-nav a {
  position: relative;
  flex: 0 1 9rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-width: 0;
  min-height: var(--hdr-tab-h);
  padding: 0 var(--hdr-tab-px);
  border-top: 1px solid var(--hdr-line);
  background: var(--hdr-plate, none);
  color: var(--hdr-fg);
  font-family: var(--hud-mono);
  font-size: var(--hdr-tab-fs);
  letter-spacing: 0.04em;
  line-height: 1.2;
  text-decoration: none;
  text-transform: uppercase;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: clip;
  isolation: isolate;
  transition: color 0.12s ease;
}
.header-nav a::before {
  content: "";
  position: absolute;
  inset: 0 0 -1px;
  z-index: -1;
  background: var(--hdr-fill);
  transform: scaleY(0);
  transform-origin: 50% 0;
  transition: transform 0.1s ease-in-out;
}
.header-nav a::after {
  content: "\2197\FE0E";
  content: "\2197\FE0E" / "";
  flex: none;
  margin-left: 8px;
  transition: transform 0.2s ease;
}
.header-nav a:hover,
.header-nav a:focus-visible {
  color: var(--hdr-fill-fg);
}
.header-nav a:hover::before,
.header-nav a:focus-visible::before {
  transform: scaleY(1);
  transform-origin: 50% 100%;
  transition: transform 0.2s cubic-bezier(0.22, 0.61, 0.36, 1);
}
.header-nav a:hover::after,
.header-nav a:focus-visible::after {
  transform: translate(2px, -2px);
}
.header-nav a[aria-current="page"] {
  background: var(--hdr-fill);
  color: var(--hdr-fill-fg);
}
.header-nav a[aria-current="page"]::before {
  background: var(--hdr-fill);
}
/* keyboard focus on any header control: a 2px ring in the header's text colour (>= 4.5:1 on its own colour, whatever the page) */
.site-header--compact :focus-visible {
  outline: 2px solid var(--hdr-fg);
  outline-offset: 1px;
}

/* the account chip: avatar mark + "welcome, name" + logout, at the right end of the status strip's row */
.hud-chip {
  grid-area: chip;
  display: flex;
  align-items: center;
  gap: var(--hdr-chip-gap);
  box-sizing: border-box;
  width: var(--hdr-chip-w);
  min-width: 0;
  min-height: var(--hdr-strip-h);
  margin-top: var(--hdr-row-gap);
  padding: 0 0 0 var(--hdr-chip-pl);
  border-left: 1px solid var(--hdr-line);
  background: var(--hdr-plate, none);
  color: var(--hdr-soft);
  font-family: var(--hud-mono);
  font-size: var(--hdr-chip-fs);
  line-height: 1.2;
}
.hud-chip__avatar {
  flex: none;
  width: 22px;
  height: 22px;
}
.hud-chip__avatar .av-ring { fill: none; stroke: var(--hdr-fg); stroke-width: 1.6; }
.hud-chip__avatar .av-body { fill: var(--hdr-fg); stroke: none; }
.hud-chip--guest .hud-chip__avatar .av-body { fill: var(--hdr-soft); }
/* logged in: the account button, a compact square-edged link to /account: a small avatar circle (the e-mail's first letter, filled with the
   header's fill colour) and the word «аккаунт»; hover / current page: the same fill sweep colours as the tabs and the logout button (the
   circle inverts). The address stays beside it as quiet text. */
.hud-chip__account {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: var(--hdr-strip-h);
  padding: 0 10px 0 3px;
  border: 1px solid var(--hdr-fg);
  background: transparent;
  color: var(--hdr-fg);
  font-family: var(--hud-mono);
  font-size: var(--hdr-chip-fs);
  line-height: 1.2;
  text-decoration: none;
  text-transform: uppercase;
  transition: background-color 0.12s ease, color 0.12s ease;
}
.hud-chip__avatar--initial .av-ring { fill: var(--hdr-fill); stroke: var(--hdr-fg); stroke-width: 1.6; }
.hud-chip__avatar .av-initial {
  fill: var(--hdr-fill-fg);
  font-family: var(--hud-mono);
  font-size: 16px;
  font-weight: 700;
}
.hud-chip__account + .hud-chip__text .header-account { color: var(--hdr-soft); font-weight: 400; }
.hud-chip__account:hover,
.hud-chip__account:focus-visible,
.hud-chip__account[aria-current="page"] {
  background: var(--hdr-fill);
  color: var(--hdr-fill-fg);
}
.hud-chip__account:hover .av-ring,
.hud-chip__account:focus-visible .av-ring,
.hud-chip__account[aria-current="page"] .av-ring { fill: var(--hdr-fill-fg); stroke: var(--hdr-fill-fg); }
.hud-chip__account:hover .av-initial,
.hud-chip__account:focus-visible .av-initial,
.hud-chip__account[aria-current="page"] .av-initial { fill: var(--hdr-fill); }
.hud-chip__text {
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.header-account {
  color: var(--hdr-fg);
  font-weight: 700;
}
.header-logout-form {
  display: inline;
  flex: none;
}
.header-logout-btn {
  min-height: var(--hdr-strip-h);
  padding: 0 var(--hdr-btn-px);
  border: 1px solid var(--hdr-fg);
  border-radius: 0;
  background: transparent;
  color: var(--hdr-fg);
  font-family: var(--hud-mono);
  font-size: var(--hdr-chip-fs);
  line-height: 1.2;
  cursor: pointer;
  transition: background-color 0.12s ease, color 0.12s ease;
}
.header-logout-btn:hover,
.header-logout-btn:focus-visible {
  background: var(--hdr-fill);
  color: var(--hdr-fill-fg);
}

/* admins only: the small square button at the very end of the tabs, a wrench (nav.ejs). It keeps the tab's top rule and fill, loses the
   arrow, and sits at the right end of the row. */
.header-nav a.header-nav__admin {
  flex: none;
  justify-content: center;
  width: 34px;
  margin-left: auto;
  padding: 0;
  border: 1px solid var(--hdr-line);
}
.header-nav a.header-nav__admin::after { display: none; }
.header-nav__admin svg {
  display: block;
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linejoin: miter;
}

/* status strip: real data, date at the right, between two hairlines (no fill unless a page gives --hdr-plate: it is the page's own colour) */
.hud-bar {
  grid-area: bar;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--hdr-bar-gap);
  box-sizing: border-box;
  min-height: var(--hdr-strip-h);
  margin: var(--hdr-row-gap) 0 0;
  padding: var(--hdr-bar-py) 0;
  border-top: 1px solid var(--hdr-line);
  border-bottom: 1px solid var(--hdr-line);
  background: var(--hdr-plate, none);
  color: var(--hdr-fg);
  font-family: var(--hud-mono);
  font-size: var(--hdr-bar-fs);
  letter-spacing: 0.04em;
  line-height: 1.5;
}
.hud-bar__sep {
  color: var(--hdr-fg);
}
.hud-bar__item {
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
  white-space: nowrap;
}
.hud-bar__led {
  flex: none;
  width: 7px;
  height: 7px;
  border: 1px solid var(--hdr-fg);
  background: transparent;
}
.hud-bar__item--on .hud-bar__led {
  background: var(--hdr-led);
}
.hud-bar__date {
  margin-left: auto;
  white-space: nowrap;
}

/* tablets and phones: the account chip gets its own row above the status strip */
@media (max-width: 899px) {
  .site-header--compact {
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-areas:
      "logo nav"
      "chip chip"
      "bar bar";
  }
  .hud-chip {
    width: auto;
    padding: 0;
    border-left: 0;
  }
}

/* phones: the wordmark, the tab grid, the chip and the strip stack */
@media (max-width: 719px) {
  .site-header--compact {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      "logo"
      "nav"
      "chip"
      "bar";
    padding-top: 8px;
  }
  .header-logo {
    padding-bottom: 4px;
  }
  .header-nav {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr));
  }
  .header-nav a.header-nav__admin {
    grid-column: 1 / -1;
    justify-self: end;
    margin-left: 0;
  }
  .hud-bar {
    gap: 2px 10px;
  }
  .hud-bar__date {
    margin-left: 0;
  }
}

/* dashed chevron band, above the footer */
.site-footer::before {
  content: "";
  display: block;
  height: 12px;
  background: var(--yh-band) left center / 28px 12px repeat-x;
  pointer-events: none;
}

/* ---------- short pages: the footer rests on the bottom edge of the viewport ----------
   <body> is a viewport-high flex column and the page's content wrapper takes the spare
   height (home, the meadow events page and the .hud-fill pages set their own height; this
   rule has zero specificity so their flex / width rules win). */
body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100svh;
}
:where(body) > :where(main, .events-explorer, .container) {
  flex: 1 0 auto;
  width: 100%;
}

/* ---------- footer: the dashed band, one mono status line at the left, a row of small icon links at the right ----------
   Five square icon-only links (28-32px: --ico), a hairline border in the muted ink, the same gap
   everywhere. The row shares the status line's centre line. Each link has an aria-label + title.

   The footer is one surface with the header and the page, read from <body> custom properties like the header's --hdr-*:
     --ftr-bg       the colour under the footer's text and icons (what every pair below is measured against; opaque where the
                    footer lies fixed under the content)
     --ftr-paint    what the footer paints (transparent on the paper pages, so the line-art runs on behind it)
     --ftr-fg       the status line's name, the icons, the focus ring (>= 4.5:1 on --ftr-bg)
     --ftr-soft     the quiet status text (>= 4.5:1 on --ftr-bg)
     --ftr-edge     the hairline of an icon square (>= 3:1)
     --ftr-plate    the colour behind an icon square (--ftr-bg unless the icons sit on plates of their own: the band, the home video)
     --ftr-fill / --ftr-fill-fg   the sweep that fills an icon on hover and its icon colour over it (>= 4.5:1)
     --ftr-mark     the // separators
   They default to the header's properties above, so the footer already matches on every page; home.css (the video), events.css (the
   Windows taskbar of /events) and submit.css (the band) set their own. tests/header-colours.test.js computes every pair per page. */

.site-footer {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 12px;
  margin-top: 40px;
  padding: 0 var(--yh-g) 12px;
  background: var(--ftr-paint);
  color: var(--ftr-fg);
}
.site-footer::before {
  flex: 1 0 100%;
  margin: 0 0 10px;
}
.site-footer .hud-status {
  margin-right: auto;
  min-width: 0;
  overflow-wrap: anywhere;
  color: var(--ftr-soft);
}
.hud-status__user {
  color: var(--ftr-fg);
  font-weight: 700;
}
.hud-status__sep {
  color: var(--ftr-mark);
  font-weight: 700;
}
.site-footer__privacy {
  color: var(--ftr-soft);
  font-size: 0.72rem;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.site-footer__privacy:hover,
.site-footer__privacy:focus-visible {
  color: var(--ftr-fg);
}
.social-links {
  --ico: 30px;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 6px;
}
.social-links a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--ico);
  height: var(--ico);
  border: 1px solid var(--ftr-edge);
  background: transparent;
  color: var(--ftr-fg);
  text-decoration: none;
  /* the hover fill is the stepped sweep of the motion kit (end of this sheet) */
  --yh-base: var(--ftr-plate);
  --yh-sw: var(--ftr-fill);
  --yh-fg-hover: var(--ftr-fill-fg);
}
.social-links svg {
  display: block;
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: square;
  stroke-linejoin: miter;
}
.social-links svg .ico-fill { fill: currentColor; stroke: none; }
.social-links a:focus-visible {
  outline: 2px solid var(--ftr-fg);
  outline-offset: 2px;
}

/* ==========================================================================
   Window (used by every inner page's content): a dark blue title strip with
   the tab name, the path and a small square close mark, a pale body with a
   hairline border.
   <section class="hud-pane">
     <div class="hud-pane__bar">
       <span class="hud-pane__tab">события</span>
       <span class="hud-pane__path">/events</span>
       <a class="hud-pane__close" href="/"><span class="ax-sr-only">закрыть</span></a>
     </div>
     <div class="hud-pane__body"> ... scrolls ... </div>
   </section>
   (no <header> / <nav> inside: the page has exactly one of each.)
   ========================================================================== */

.hud-pane {
  display: flex;
  flex-direction: column;
  min-width: 0;
  color: var(--th-ink);
}
.hud-pane__bar {
  position: relative;
  display: flex;
  align-items: center;
  gap: 16px;
  min-width: 0;
  min-height: 32px;
  padding: 0 8px 0 12px;
  background: var(--th-chrome-a);
  color: var(--th-chrome-ink);
  font-family: var(--hud-mono);
  font-size: 0.72rem;
  line-height: 1.2;
}
/* the pixel-stepped lower edge of the strip: ink pixels (4x4 Bayer) hang over the top of the body and dissolve */
.hud-pane__bar::after {
  content: "";
  position: absolute;
  z-index: 1;
  left: 0;
  right: 0;
  top: 100%;
  height: 6px;
  background: var(--yh-dz-edge) left top / 8px 6px repeat-x;
  pointer-events: none;
}
.hud-pane__tab {
  display: flex;
  flex: none;
  align-items: center;
  gap: 9px;
  max-width: 60%;
  overflow: hidden;
  color: var(--th-chrome-ink);
  font-family: var(--hud-display);
  font-size: 0.74rem;
  font-weight: 400;
  letter-spacing: 0.1em;
  text-overflow: ellipsis;
  text-transform: uppercase;
  white-space: nowrap;
}
.hud-pane__tab::before {
  content: "";
  flex: none;
  width: 6px;
  height: 6px;
  background: var(--th-tint-deep);
}
.hud-pane__path {
  flex: 1 1 0;
  min-width: 0;
  overflow: hidden;
  color: var(--th-chrome-ink);
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* close: a small square mark with a thin cross, accent on hover */
.hud-pane__close {
  position: relative;
  flex: none;
  width: 20px;
  height: 20px;
  border: 1px solid rgba(244, 247, 250, 0.55);
  cursor: pointer;
  transition: background-color var(--yh-t-fast) steps(3, end), border-color var(--yh-t-fast) steps(3, end);
}
.hud-pane__close::before,
.hud-pane__close::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 11px;
  height: 1px;
  margin: 0 0 0 -5.5px;
  background: var(--th-chrome-ink);
  transform: rotate(45deg);
}
.hud-pane__close::after {
  transform: rotate(-45deg);
}
.hud-pane__close:hover {
  border-color: var(--yh-accent);
  background: var(--yh-accent);
}
.hud-pane__close:focus-visible {
  outline-color: var(--th-chrome-ink);
  outline-offset: 2px;
}
.hud-pane__body {
  position: relative;
  max-height: var(--pane-h, none);
  padding: var(--pane-pad, 16px);
  overflow: auto;
  border: 1px solid var(--th-ink);
  border-top: 0;
  background: var(--th-panel);
  scrollbar-color: var(--th-ink) var(--th-soft);
  scrollbar-width: thin;
}
.hud-pane__body::-webkit-scrollbar {
  width: 12px;
  height: 12px;
}
.hud-pane__body::-webkit-scrollbar-track {
  background: var(--th-soft);
  border-left: 1px solid var(--th-rule);
}
.hud-pane__body::-webkit-scrollbar-thumb {
  border: 3px solid var(--th-soft);
  background: var(--th-ink);
}
.hud-pane__body::-webkit-scrollbar-thumb:hover {
  background: var(--th-accent);
}
.hud-pane__body::-webkit-scrollbar-corner {
  background: var(--th-soft);
}

/* mono status line: footers, pane captions */
.hud-status {
  margin: 0;
  color: var(--th-ink-soft);
  font-family: var(--hud-mono);
  font-size: 0.72rem;
  letter-spacing: 0.03em;
  line-height: 1.5;
}

/* A pane that fills the viewport between the frame and the status-line
   footer on desktop and scrolls inside itself, so the page never double-scrolls
   (submit, edit, vote, my submissions). Small screens just stack.
   <main class="hud-fill"><section class="hud-pane">...</section></main> */
.hud-fill {
  width: 100%;
  max-width: 1280px;
  margin: 0 auto;
  padding: var(--hdr-gap) var(--yh-g) 6px;
}
@media (min-width: 900px) and (min-height: 600px) {
  body:has(.hud-fill) {
    display: flex;
    flex-direction: column;
    height: 100vh;
    height: 100svh;
  }
  body:has(.hud-fill) > .site-header,
  body:has(.hud-fill) > .site-footer {
    flex: none;
  }
  body:has(.hud-fill) > .site-footer {
    margin-top: 12px;
  }
  .hud-fill {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    min-height: 380px;
  }
  .hud-fill > .hud-pane {
    flex: 1 1 auto;
    min-height: 0;
  }
  .hud-fill .hud-pane__body {
    flex: 1 1 auto;
    min-height: 0;
    max-height: none;
  }
}

/* ==========================================================================
   Dialog kit (xp- prefix, kept for the markup): the same flat window, the page
   heading is the title strip with the tiny controls at the right; flat inputs
   (1px ink border, paper fill, a square focus ring), flat buttons (outlined,
   the primary one filled), an error row and a status row of links. Reads only
   --th-* variables, so every theme recolours it. Used by the auth, submit, edit,
   vote and my-submissions panes.
   ========================================================================== */

.xp-win {
  position: relative;
  overflow: hidden;
  border: 1px solid var(--th-ink);
  background: var(--th-panel);
  color: var(--th-ink);
}
.xp-win__title {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0;
  padding: 0.5em 0.6em 0.5em 0.9em;
  background: var(--th-chrome-a);
  color: var(--th-chrome-ink);
  font-family: var(--hud-display);
  font-size: 0.84rem;
  font-weight: 400;
  letter-spacing: 0.1em;
  line-height: 1.3;
  overflow-wrap: anywhere;
  text-transform: uppercase;
}
.xp-win__title::before {
  content: "";
  flex: none;
  width: 6px;
  height: 6px;
  background: var(--th-tint-deep);
}
.xp-win__title::after {
  content: "";
  flex: none;
  width: 69px;
  height: 21px;
  margin-left: auto;
  background: var(--ax-controls) center / 69px 21px no-repeat;
}
.xp-win__body {
  padding: 22px 24px 24px;
}

.xp-form {
  display: flex;
  flex-direction: column;
}
.xp-label {
  margin: 16px 0 6px;
  color: var(--th-ink);
  font-family: var(--hud-mono);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  line-height: 1.4;
}
.xp-form > .xp-label:first-child {
  margin-top: 0;
}
.xp-input {
  display: block;
  width: 100%;
  min-width: 0;
  padding: 0.6em 0.8em;
  border: 1px solid var(--th-ink);
  border-radius: 0;
  background: var(--yh-paper-hi);
  color: var(--th-ink);
  font-family: var(--yh-font);
  font-size: 1rem;
  line-height: 1.4;
}
.xp-input:hover {
  background: var(--yh-paper-top);
}
.xp-input:focus-visible {
  outline: 2px solid var(--yh-accent);
  outline-offset: 1px;
}
.xp-input:user-invalid {
  border-color: var(--yh-danger);
  box-shadow: inset 3px 0 0 var(--yh-danger);
}
.xp-input[type="file"] {
  padding: 6px;
  font-size: 0.9rem;
  cursor: pointer;
}
.xp-input[type="file"]::file-selector-button {
  margin-right: 12px;
  padding: 0.4em 1.1em;
  border: 1px solid var(--th-ink);
  border-radius: 0;
  background: transparent;
  color: var(--th-ink);
  font-family: var(--hud-mono);
  font-size: 0.8rem;
  cursor: pointer;
}
.xp-input[type="file"]::file-selector-button:hover {
  background: var(--th-ink);
  color: var(--th-on-accent);
}

/* the primary button: filled ink with a square bullet; hover = the accent */
.xp-go {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.8em;
  min-height: 44px;
  margin-top: 24px;
  padding: 0.6em 1.6em;
  border: 1px solid var(--th-ink);
  border-radius: 0;
  background: var(--th-ink);
  color: var(--th-on-accent);
  font-family: var(--hud-mono);
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  line-height: 1.25;
  cursor: pointer;
  --yh-base: var(--th-ink);
  --yh-sw: var(--yh-accent);
  --yh-fg-hover: var(--yh-on-accent);
}
.xp-go::before {
  content: "";
  flex: none;
  width: 6px;
  height: 6px;
  background: var(--yh-accent-hi);
}
.xp-go:hover::before,
.xp-go:focus-visible::before {
  background: currentColor;
}
.xp-go:focus-visible {
  outline: 2px solid var(--th-ink);
  outline-offset: 3px;
}

/* error row: a red bar, a square mark, the message (red = danger, never the blue accent) */
.xp-error {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  margin: 0 0 18px;
  padding: 10px 14px;
  border: 1px solid var(--yh-danger);
  border-left-width: 6px;
  background: var(--yh-danger-wash);
  color: var(--yh-danger-deep);
  font-size: 0.95rem;
  font-weight: 600;
  line-height: 1.5;
  overflow-wrap: anywhere;
}
.xp-error::before {
  content: "";
  flex: none;
  width: 8px;
  height: 8px;
  margin-top: 0.5em;
  background: var(--yh-danger);
}

/* status row of links under a dialog */
.xp-links {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 6px 18px;
  padding: 10px 24px 12px;
  border-top: 1px solid var(--th-ink);
  background: var(--th-soft);
  font-family: var(--hud-mono);
  font-size: 0.78rem;
  line-height: 1.5;
}
.xp-links a {
  color: var(--th-accent-ink);
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.xp-links a:hover {
  color: var(--th-ink);
  text-decoration-thickness: 2px;
}

@media (max-width: 480px) {
  .xp-win__title::after {
    display: none;
  }
  .xp-win__body {
    padding: 18px 14px 20px;
  }
  .xp-links {
    padding: 10px 14px 12px;
  }
}

/* ==========================================================================
   YoRHa element kit (.yh-*): the pieces every page can use. All of them are
   flat, aligned to the 8px grid and driven by the tokens above.
     .yh-btn (+ --primary)   outlined button, square bullet, hover = invert
     .yh-tab                 a flat tab / label with a square bullet
     .yh-label               small mono caps label
     .yh-row                 list row: a darker bar, bullet or pictogram, text
     .yh-window (+ __bar, __body)   a window like .hud-pane, for any block
     .yh-frame (+ __bar, __media, __caption)   the thick-bordered picture frame
     .rf-sig.rf-sig--NAME    pictograms (CSS masks, tinted by color), 16/24/32
   ========================================================================== */

.yh-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.8em;
  min-height: 36px;
  padding: 0 16px;
  border: 1px solid var(--th-ink);
  border-radius: 0;
  background: transparent;
  color: var(--th-ink);
  font-family: var(--hud-mono);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  line-height: 1.2;
  text-decoration: none;
  cursor: pointer;
  --yh-base: var(--th-panel);
  --yh-sw: var(--th-ink);
}
.yh-btn::before {
  content: "";
  flex: none;
  width: 6px;
  height: 6px;
  background: currentColor;
}
/* (hover = the stepped fill sweep of the motion kit) */
.yh-btn--primary {
  --yh-base: var(--th-ink);
  --yh-sw: var(--yh-accent);
  --yh-fg-hover: var(--yh-on-accent);
  color: var(--th-on-accent);
}
.yh-btn--primary::before {
  background: var(--yh-accent-hi);
}
.yh-btn--primary:hover::before,
.yh-btn--primary:focus-visible::before {
  background: currentColor;
}

.yh-label {
  color: var(--th-ink-soft);
  font-family: var(--hud-mono);
  font-size: 0.7rem;
  letter-spacing: 0.08em;
  line-height: 1.3;
  text-transform: uppercase;
}

.yh-row {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 32px;
  padding: 4px 12px;
  background: var(--th-soft);
  color: var(--th-ink);
  font-family: var(--hud-mono);
  font-size: 0.74rem;
  line-height: 1.4;
}
.yh-row::before {
  content: "";
  flex: none;
  width: 6px;
  height: 6px;
  background: currentColor;
}

.yh-window {
  display: flex;
  flex-direction: column;
  min-width: 0;
  border: 1px solid var(--th-ink);
  background: var(--th-panel);
  color: var(--th-ink);
}
.yh-window__bar {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 28px;
  padding: 0 8px 0 12px;
  background: var(--th-chrome-a);
  color: var(--th-chrome-ink);
  font-family: var(--hud-mono);
  font-size: 0.7rem;
  line-height: 1.2;
}
.yh-window__bar::before {
  content: "";
  flex: none;
  width: 6px;
  height: 6px;
  background: var(--th-tint-deep);
}
.yh-window__bar::after {
  content: "";
  flex: none;
  width: 69px;
  height: 21px;
  margin-left: auto;
  background: var(--ax-controls) right center / 69px 21px no-repeat;
}
.yh-window__body {
  padding: 16px;
}

/* a picture in a thick ink frame with a small caption underneath */
.yh-frame {
  display: block;
  min-width: 0;
  margin: 0;
}
.yh-frame__media {
  position: relative;
  display: block;
  overflow: hidden;
  border: 4px solid var(--th-ink);
  background: var(--th-soft);
}
.yh-frame__caption {
  margin-top: 6px;
  color: var(--th-ink);
  font-family: var(--hud-mono);
  font-size: 0.7rem;
  font-weight: 700;
  line-height: 1.4;
}

/* pictograms from the owner's transfer sheet (docs/sig-pictograms.md): black
   glyphs on a transparent sprite, used as a CSS mask so currentColor tints them.
   One scale only: 16 / 24 / 32 px (--s). Always decoration (aria-hidden). */
.rf-sig {
  --s: 24px;
  --c: 0;
  --r: 0;
  display: inline-block;
  flex: none;
  width: var(--s);
  height: var(--s);
  background-color: currentColor;
  -webkit-mask: url("/images/sig/sig-sprite.png") calc(var(--s) * var(--c) * -1) calc(var(--s) * var(--r) * -1) / calc(var(--s) * 6) calc(var(--s) * 5) no-repeat;
  mask: url("/images/sig/sig-sprite.png") calc(var(--s) * var(--c) * -1) calc(var(--s) * var(--r) * -1) / calc(var(--s) * 6) calc(var(--s) * 5) no-repeat;
  pointer-events: none;
  user-select: none;
}
.rf-sig--16 { --s: 16px; }
.rf-sig--24 { --s: 24px; }
.rf-sig--32 { --s: 32px; }
/* the printed digits 1-0, a numbered box and the guillemets from the same sheet: size with --h */
.rf-dg {
  --h: 22px;
  --w: calc(var(--h) * 0.75);
  --i: 0;
  display: inline-block;
  flex: none;
  width: var(--w);
  height: var(--h);
  background-color: currentColor;
  -webkit-mask: url("/images/sig/sig-digits.png") calc(var(--w) * var(--i) * -1) 0 / calc(var(--w) * 13) var(--h) no-repeat;
  mask: url("/images/sig/sig-digits.png") calc(var(--w) * var(--i) * -1) 0 / calc(var(--w) * 13) var(--h) no-repeat;
  pointer-events: none;
  user-select: none;
}
.rf-dg--1 { --i: 0; } .rf-dg--2 { --i: 1; } .rf-dg--3 { --i: 2; } .rf-dg--4 { --i: 3; } .rf-dg--5 { --i: 4; }
.rf-dg--6 { --i: 5; } .rf-dg--7 { --i: 6; } .rf-dg--8 { --i: 7; } .rf-dg--9 { --i: 8; } .rf-dg--0 { --i: 9; }
.rf-dg--box { --i: 10; } .rf-dg--rq { --i: 11; } .rf-dg--lq { --i: 12; }

/* sprite cells: --c column, --r row (public/images/sig/sig-sprite.json) */
.rf-sig--plus { --c: 0; --r: 0; }
.rf-sig--cross-ring { --c: 1; --r: 0; }
.rf-sig--ring { --c: 2; --r: 0; }
.rf-sig--note { --c: 3; --r: 0; }
.rf-sig--notes { --c: 4; --r: 0; }
.rf-sig--power { --c: 5; --r: 0; }
.rf-sig--warning { --c: 0; --r: 1; }
.rf-sig--headphones { --c: 1; --r: 1; }
.rf-sig--headset-tape { --c: 2; --r: 1; }
.rf-sig--sun { --c: 3; --r: 1; }
.rf-sig--arrow-down { --c: 4; --r: 1; }
.rf-sig--ring-open { --c: 5; --r: 1; }
.rf-sig--diamond { --c: 0; --r: 2; }
.rf-sig--play-box { --c: 1; --r: 2; }
.rf-sig--arrow-box { --c: 2; --r: 2; }
.rf-sig--yin-yang { --c: 3; --r: 2; }
.rf-sig--half-moon { --c: 4; --r: 2; }
.rf-sig--arrow-ring { --c: 5; --r: 2; }
.rf-sig--antenna { --c: 0; --r: 3; }
.rf-sig--bolt { --c: 1; --r: 3; }
.rf-sig--tv-a { --c: 2; --r: 3; }
.rf-sig--tv-b { --c: 3; --r: 3; }
.rf-sig--box-bar { --c: 4; --r: 3; }
.rf-sig--wedge { --c: 5; --r: 3; }
.rf-sig--triangle { --c: 0; --r: 4; }
.rf-sig--clock { --c: 1; --r: 4; }
.rf-sig--wave { --c: 2; --r: 4; }
.rf-sig--reels { --c: 3; --r: 4; }
.rf-sig--tri-ring { --c: 4; --r: 4; }
.rf-sig--tv-arrows { --c: 5; --r: 4; }

/* ---------- utilities ---------- */

.ax-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ==========================================================================
   Motion kit (yh-anim-*): the NieR:Automata UI moves in hard steps. Nothing here
   fades smoothly or bounces: reveals are clip-path wipes in 6-8 steps (a strip
   draws itself left to right, a window scans open from the top), rows of a list
   cascade 40-60ms apart, a hovered button is filled by a stepped sweep (the
   leading edge is a 2px Bayer checker), a square bullet flips, a text line
   flickers once. Durations are the --yh-t-* tokens (140-360ms); the whole first
   paint of a page is over in ~1.2s and never blocks the pointer or the reader
   (clip-path changes neither the DOM nor the accessibility tree).
   Every animation ends in the element's normal state (fill-mode "backwards", so
   no transform survives and position:fixed children keep their viewport), and
   the reduced-motion block at the very end shows that final state at once.
     .yh-anim-wipe      title strip / bar draws open, left to right
     .yh-anim-scan      a window scans open from its top edge
     .yh-anim-flicker   a line of text blinks in
     .yh-anim-pop       a small square (an icon) opens from its centre
     .yh-anim-draw      a rule / band draws along its length
     .yh-cascade        its children enter one after the other (--yh-i, up to 9)
     --yh-d / --yh-i    delay and index of an element (inline or by rule)
   ========================================================================== */

@property --yh-p { syntax: "<length-percentage>"; inherits: false; initial-value: -16px; }
/* the ten bands of the page transition (--yh-b0 is the band at the bottom of the screen): how far each has risen, 0% .. 101% of its row */
@property --yh-b0 { syntax: "<percentage>"; inherits: false; initial-value: 0%; }
@property --yh-b1 { syntax: "<percentage>"; inherits: false; initial-value: 0%; }
@property --yh-b2 { syntax: "<percentage>"; inherits: false; initial-value: 0%; }
@property --yh-b3 { syntax: "<percentage>"; inherits: false; initial-value: 0%; }
@property --yh-b4 { syntax: "<percentage>"; inherits: false; initial-value: 0%; }
@property --yh-b5 { syntax: "<percentage>"; inherits: false; initial-value: 0%; }
@property --yh-b6 { syntax: "<percentage>"; inherits: false; initial-value: 0%; }
@property --yh-b7 { syntax: "<percentage>"; inherits: false; initial-value: 0%; }
@property --yh-b8 { syntax: "<percentage>"; inherits: false; initial-value: 0%; }
@property --yh-b9 { syntax: "<percentage>"; inherits: false; initial-value: 0%; }

@keyframes yh-wipe-x {
  from { clip-path: inset(0 100% 0 0); }
  to { clip-path: inset(0 0 0 0); }
}
@keyframes yh-scan {
  from { clip-path: inset(0 0 100% 0); }
  to { clip-path: inset(0 0 0 0); }
}
@keyframes yh-pop {
  from { clip-path: inset(50% 50% 50% 50%); }
  to { clip-path: inset(0 0 0 0); }
}
@keyframes yh-flicker {
  0% { opacity: 0; }
  14% { opacity: 1; }
  28% { opacity: 0.15; }
  42% { opacity: 1; }
  56% { opacity: 0.5; }
  70%, 100% { opacity: 1; }
}
@keyframes yh-flip {
  0% { transform: scaleX(1); }
  50% { transform: scaleX(0.1); }
  100% { transform: scaleX(1); }
}
@keyframes yh-blink {
  0%, 82% { opacity: 1; }
  83%, 100% { opacity: 0.2; }
}

/* the index of a child inside a cascade: one stagger step per row */
:is(.yh-cascade, .header-nav, .social-links) > :nth-child(1) { --yh-i: 1; }
:is(.yh-cascade, .header-nav, .social-links) > :nth-child(2) { --yh-i: 2; }
:is(.yh-cascade, .header-nav, .social-links) > :nth-child(3) { --yh-i: 3; }
:is(.yh-cascade, .header-nav, .social-links) > :nth-child(4) { --yh-i: 4; }
:is(.yh-cascade, .header-nav, .social-links) > :nth-child(5) { --yh-i: 5; }
:is(.yh-cascade, .header-nav, .social-links) > :nth-child(6) { --yh-i: 6; }
:is(.yh-cascade, .header-nav, .social-links) > :nth-child(7) { --yh-i: 7; }
:is(.yh-cascade, .header-nav, .social-links) > :nth-child(8) { --yh-i: 8; }
:is(.yh-cascade, .header-nav, .social-links) > :nth-child(n+9) { --yh-i: 9; }

.yh-anim-wipe { animation: yh-wipe-x var(--yh-t-wipe) steps(8, end) var(--yh-d, 0ms) backwards; }
.yh-anim-scan { animation: yh-scan 420ms steps(8, end) var(--yh-d, 0ms) backwards; }
.yh-anim-flicker { animation: yh-flicker 480ms steps(1, end) var(--yh-d, 0ms) backwards; }
.yh-anim-pop { animation: yh-pop var(--yh-t-mid) steps(4, end) var(--yh-d, 0ms) backwards; }
.yh-anim-draw { animation: yh-wipe-x 520ms steps(16, end) var(--yh-d, 0ms) backwards; }
.yh-cascade > * { animation: yh-wipe-x var(--yh-t-wipe) steps(6, end) calc(var(--yh-d, 0ms) + var(--yh-i, 0) * var(--yh-stagger)) backwards; }

/* ---------- first paint of the frame (every page): tabs, strip, band, footer ---------- */

.header-nav a { animation: yh-wipe-x var(--yh-t-wipe) steps(8, end) calc(var(--yh-i, 0) * 40ms) backwards; }
.hud-bar { animation: yh-wipe-x 420ms steps(10, end) 200ms backwards; }
.hud-chip { animation: yh-wipe-x var(--yh-t-wipe) steps(8, end) 280ms backwards; }
.site-footer::before { animation: yh-wipe-x 560ms steps(16, end) 160ms backwards; }
.hud-pane__bar { animation: yh-wipe-x var(--yh-t-wipe) steps(8, end) 200ms backwards; }
.hud-pane__body { animation: yh-scan 440ms steps(8, end) 320ms backwards; }
.xp-win { animation: yh-scan 440ms steps(8, end) 220ms backwards; }
.xp-win__title { animation: yh-wipe-x var(--yh-t-wipe) steps(8, end) 280ms backwards; }
.site-footer .hud-status { animation: yh-flicker 480ms steps(1, end) 600ms backwards; }
.social-links a { animation: yh-pop var(--yh-t-mid) steps(4, end) calc(640ms + var(--yh-i, 0) * 60ms) backwards; }

/* ---------- hover and focus: the stepped fill sweep ----------
   Three layers over the base colour (--yh-base): the solid fill up to --yh-p (--yh-sw),
   a 2px checker (the 4x4 Bayer grain of the video) in the same colour, and a cover in the
   base colour that hides the checker beyond 16px past the front. --yh-p is a registered
   length-percentage: 8 steps from -16px to 100% (browsers without @property just jump). The text colour flips
   half-way (steps(1) over half the time), so it changes while the front crosses it. */
.yh-btn,
.xp-go,
.social-links a,
.submit-back-btn {
  background-color: var(--yh-base, var(--th-bg));
  background-image:
    linear-gradient(90deg, transparent calc(var(--yh-p) + 16px), var(--yh-base, var(--th-bg)) calc(var(--yh-p) + 16px)),
    conic-gradient(var(--yh-sw, var(--th-ink)) 25%, transparent 0 50%, var(--yh-sw, var(--th-ink)) 0 75%, transparent 0),
    linear-gradient(90deg, var(--yh-sw, var(--th-ink)) var(--yh-p), transparent var(--yh-p));
  background-size: 100% 100%, 4px 4px, 100% 100%;
  background-repeat: no-repeat, repeat, no-repeat;
  transition: --yh-p var(--yh-t-mid) steps(8, end), color calc(var(--yh-t-mid) / 2) steps(1, end), border-color calc(var(--yh-t-mid) / 2) steps(1, end);
}
.yh-btn:hover,
.yh-btn:focus-visible,
.xp-go:hover,
.xp-go:focus-visible,
.social-links a:hover,
.social-links a:focus-visible,
.submit-back-btn:hover,
.submit-back-btn:focus-visible {
  --yh-p: calc(100% + 0px);
  border-color: var(--yh-sw);
  color: var(--yh-fg-hover, var(--th-on-accent));
}
/* the square bullet of a tab / button flips once when it is hovered */
.yh-btn:hover::before,
.xp-go:hover::before {
  animation: yh-flip var(--yh-t-mid) steps(4, end) 1;
}
/* ---------- the call-to-action tab: «отправить заявку» ----------
   The second tab while a round is open (views/partials/nav.ejs). A little bigger than its siblings (11rem instead of 9rem,
   34px high, bold 0.82rem) and the bright accent blue with white text (5.4:1) on every header colour. Hover / focus: the fill
   that rises is the deepest blue. The current page: deep blue with a 2px light-blue inset outline. Where the page is dark
   (the navy of /contact, the band of /submit) the blue alone would melt into it, so the header sets --hdr-cta-ring: a 1px pale-blue
   hairline round the tab. It lives after the tabs' own rules so it wins. */
.header-nav a.header-nav__cta {
  flex-basis: 11rem;
  min-height: 34px;
  border-top-color: var(--yh-accent);
  background: var(--yh-accent);
  box-shadow: inset 0 0 0 1px var(--hdr-cta-ring);
  color: var(--yh-on-accent);
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.03em;
}
.header-nav a.header-nav__cta::before {
  background: var(--yh-accent-deep);
}
.header-nav a.header-nav__cta:hover,
.header-nav a.header-nav__cta:focus-visible {
  color: var(--yh-on-accent);
}
.header-nav a.header-nav__cta[aria-current="page"] {
  background: var(--yh-accent-deep);
  box-shadow: inset 0 0 0 2px var(--yh-accent-lit);
}
.header-nav a.header-nav__cta[aria-current="page"]::before {
  background: var(--yh-accent);
}
/* (phones: the tabs form a grid of two columns, so the call to action simply sits right of «главная») */

/* a lit square (the open status): blinks slowly */
.hud-bar__item--on .hud-bar__led { animation: yh-blink 3.6s steps(1, end) infinite; }
/* list rows: a hard-edged bar slides in from the left edge, in steps */
.yh-row {
  box-shadow: inset 0 0 0 0 var(--yh-accent);
  transition: box-shadow var(--yh-t-fast) steps(3, end);
}
.yh-row:hover { box-shadow: inset 6px 0 0 0 var(--yh-accent); }

/* ---------- page transitions: cross-document View Transitions ----------
   Navigating between two pages of the site (Chrome 126+, Safari 18.2+; others just
   navigate) the new page rises over the old one from the bottom of the screen in ten
   horizontal bands: THE motion of the portfolio's section change (/events, events.js
   bandScale() and .pf-wipe): band r (0 = the one at the bottom) is a tween that starts r * 0.04
   after the first and takes 0.5, on a timeline of 0.5 + 9 * 0.04 = 0.86, ease power4.out
   (cubic-bezier(0.165, 0.84, 0.44, 1)), each band rising from the bottom of its own row up to 1.01 of it (no seam).
   The portfolio scrubs that timeline with the scroll; here it runs on the clock: 520ms in all, so a band takes
   302ms and the bands start 24ms apart. It is ONE clip-path animation (the keyframes below are that timeline sampled every 20ms, ten bands
   = a 40-point polygon): clip-path runs on the compositor, so a busy main thread (the new page's own start-up work) cannot make the rise
   stutter, which the ten animated mask gradients (custom properties: main thread) did. The old page stays where it is, and so do the tab bar, the status
   strip, the account tab and the footer: they are named, so they hold their place / morph between the two
   layouts instead of rising with the page (the morph uses the same ease). Back / forward use the same motion.
   Under reduced motion it is a short cross-fade. */

@view-transition { navigation: auto; }

.header-nav { view-transition-name: yh-nav; }
.hud-bar { view-transition-name: yh-bar; }
.hud-chip { view-transition-name: yh-chip; }
.site-footer { view-transition-name: yh-foot; }

@keyframes yh-vt-b0 { from { --yh-b0: 0%; } to { --yh-b0: 101%; } }
@keyframes yh-vt-b1 { from { --yh-b1: 0%; } to { --yh-b1: 101%; } }
@keyframes yh-vt-b2 { from { --yh-b2: 0%; } to { --yh-b2: 101%; } }
@keyframes yh-vt-b3 { from { --yh-b3: 0%; } to { --yh-b3: 101%; } }
@keyframes yh-vt-b4 { from { --yh-b4: 0%; } to { --yh-b4: 101%; } }
@keyframes yh-vt-b5 { from { --yh-b5: 0%; } to { --yh-b5: 101%; } }
@keyframes yh-vt-b6 { from { --yh-b6: 0%; } to { --yh-b6: 101%; } }
@keyframes yh-vt-b7 { from { --yh-b7: 0%; } to { --yh-b7: 101%; } }
@keyframes yh-vt-b8 { from { --yh-b8: 0%; } to { --yh-b8: 101%; } }
@keyframes yh-vt-b9 { from { --yh-b9: 0%; } to { --yh-b9: 101%; } }
@keyframes yh-vt-in {
  from { opacity: 0; }
  to { opacity: 1; }
}
::view-transition-old(root) { animation: none; mix-blend-mode: normal; }
@keyframes yh-vt-rise {
  0% { clip-path: polygon(-1% 100%, 101% 100%, 101% 100%, -1% 100%, -1% 90%, 101% 90%, 101% 90%, -1% 90%, -1% 80%, 101% 80%, 101% 80%, -1% 80%, -1% 70%, 101% 70%, 101% 70%, -1% 70%, -1% 60%, 101% 60%, 101% 60%, -1% 60%, -1% 50%, 101% 50%, 101% 50%, -1% 50%, -1% 40%, 101% 40%, 101% 40%, -1% 40%, -1% 30%, 101% 30%, 101% 30%, -1% 30%, -1% 20%, 101% 20%, 101% 20%, -1% 20%, -1% 10%, 101% 10%, 101% 10%, -1% 10%); }
  3.8% { clip-path: polygon(-1% 100%, 101% 100%, 101% 97.2%, -1% 97.2%, -1% 90%, 101% 90%, 101% 90%, -1% 90%, -1% 80%, 101% 80%, 101% 80%, -1% 80%, -1% 70%, 101% 70%, 101% 70%, -1% 70%, -1% 60%, 101% 60%, 101% 60%, -1% 60%, -1% 50%, 101% 50%, 101% 50%, -1% 50%, -1% 40%, 101% 40%, 101% 40%, -1% 40%, -1% 30%, 101% 30%, 101% 30%, -1% 30%, -1% 20%, 101% 20%, 101% 20%, -1% 20%, -1% 10%, 101% 10%, 101% 10%, -1% 10%); }
  7.7% { clip-path: polygon(-1% 100%, 101% 100%, 101% 95.2%, -1% 95.2%, -1% 90%, 101% 90%, 101% 87.7%, -1% 87.7%, -1% 80%, 101% 80%, 101% 80%, -1% 80%, -1% 70%, 101% 70%, 101% 70%, -1% 70%, -1% 60%, 101% 60%, 101% 60%, -1% 60%, -1% 50%, 101% 50%, 101% 50%, -1% 50%, -1% 40%, 101% 40%, 101% 40%, -1% 40%, -1% 30%, 101% 30%, 101% 30%, -1% 30%, -1% 20%, 101% 20%, 101% 20%, -1% 20%, -1% 10%, 101% 10%, 101% 10%, -1% 10%); }
  11.5% { clip-path: polygon(-1% 100%, 101% 100%, 101% 93.8%, -1% 93.8%, -1% 90%, 101% 90%, 101% 85.6%, -1% 85.6%, -1% 80%, 101% 80%, 101% 78.2%, -1% 78.2%, -1% 70%, 101% 70%, 101% 70%, -1% 70%, -1% 60%, 101% 60%, 101% 60%, -1% 60%, -1% 50%, 101% 50%, 101% 50%, -1% 50%, -1% 40%, 101% 40%, 101% 40%, -1% 40%, -1% 30%, 101% 30%, 101% 30%, -1% 30%, -1% 20%, 101% 20%, 101% 20%, -1% 20%, -1% 10%, 101% 10%, 101% 10%, -1% 10%); }
  15.4% { clip-path: polygon(-1% 100%, 101% 100%, 101% 92.8%, -1% 92.8%, -1% 90%, 101% 90%, 101% 84%, -1% 84%, -1% 80%, 101% 80%, 101% 75.9%, -1% 75.9%, -1% 70%, 101% 70%, 101% 68.8%, -1% 68.8%, -1% 60%, 101% 60%, 101% 60%, -1% 60%, -1% 50%, 101% 50%, 101% 50%, -1% 50%, -1% 40%, 101% 40%, 101% 40%, -1% 40%, -1% 30%, 101% 30%, 101% 30%, -1% 30%, -1% 20%, 101% 20%, 101% 20%, -1% 20%, -1% 10%, 101% 10%, 101% 10%, -1% 10%); }
  19.2% { clip-path: polygon(-1% 100%, 101% 100%, 101% 92%, -1% 92%, -1% 90%, 101% 90%, 101% 82.9%, -1% 82.9%, -1% 80%, 101% 80%, 101% 74.3%, -1% 74.3%, -1% 70%, 101% 70%, 101% 66.3%, -1% 66.3%, -1% 60%, 101% 60%, 101% 59.4%, -1% 59.4%, -1% 50%, 101% 50%, 101% 50%, -1% 50%, -1% 40%, 101% 40%, 101% 40%, -1% 40%, -1% 30%, 101% 30%, 101% 30%, -1% 30%, -1% 20%, 101% 20%, 101% 20%, -1% 20%, -1% 10%, 101% 10%, 101% 10%, -1% 10%); }
  23.1% { clip-path: polygon(-1% 100%, 101% 100%, 101% 91.4%, -1% 91.4%, -1% 90%, 101% 90%, 101% 82.1%, -1% 82.1%, -1% 80%, 101% 80%, 101% 73.1%, -1% 73.1%, -1% 70%, 101% 70%, 101% 64.6%, -1% 64.6%, -1% 60%, 101% 60%, 101% 56.8%, -1% 56.8%, -1% 50%, 101% 50%, 101% 50%, -1% 50%, -1% 40%, 101% 40%, 101% 40%, -1% 40%, -1% 30%, 101% 30%, 101% 30%, -1% 30%, -1% 20%, 101% 20%, 101% 20%, -1% 20%, -1% 10%, 101% 10%, 101% 10%, -1% 10%); }
  26.9% { clip-path: polygon(-1% 100%, 101% 100%, 101% 91%, -1% 91%, -1% 90%, 101% 90%, 101% 81.5%, -1% 81.5%, -1% 80%, 101% 80%, 101% 72.3%, -1% 72.3%, -1% 70%, 101% 70%, 101% 63.4%, -1% 63.4%, -1% 60%, 101% 60%, 101% 54.9%, -1% 54.9%, -1% 50%, 101% 50%, 101% 47.2%, -1% 47.2%, -1% 40%, 101% 40%, 101% 40%, -1% 40%, -1% 30%, 101% 30%, 101% 30%, -1% 30%, -1% 20%, 101% 20%, 101% 20%, -1% 20%, -1% 10%, 101% 10%, 101% 10%, -1% 10%); }
  30.8% { clip-path: polygon(-1% 100%, 101% 100%, 101% 90.6%, -1% 90.6%, -1% 90%, 101% 90%, 101% 81%, -1% 81%, -1% 80%, 101% 80%, 101% 71.6%, -1% 71.6%, -1% 70%, 101% 70%, 101% 62.4%, -1% 62.4%, -1% 60%, 101% 60%, 101% 53.6%, -1% 53.6%, -1% 50%, 101% 50%, 101% 45.2%, -1% 45.2%, -1% 40%, 101% 40%, 101% 37.7%, -1% 37.7%, -1% 30%, 101% 30%, 101% 30%, -1% 30%, -1% 20%, 101% 20%, 101% 20%, -1% 20%, -1% 10%, 101% 10%, 101% 10%, -1% 10%); }
  34.6% { clip-path: polygon(-1% 100%, 101% 100%, 101% 90.4%, -1% 90.4%, -1% 90%, 101% 90%, 101% 80.7%, -1% 80.7%, -1% 80%, 101% 80%, 101% 71.1%, -1% 71.1%, -1% 70%, 101% 70%, 101% 61.7%, -1% 61.7%, -1% 60%, 101% 60%, 101% 52.6%, -1% 52.6%, -1% 50%, 101% 50%, 101% 43.8%, -1% 43.8%, -1% 40%, 101% 40%, 101% 35.6%, -1% 35.6%, -1% 30%, 101% 30%, 101% 28.3%, -1% 28.3%, -1% 20%, 101% 20%, 101% 20%, -1% 20%, -1% 10%, 101% 10%, 101% 10%, -1% 10%); }
  38.5% { clip-path: polygon(-1% 100%, 101% 100%, 101% 90.2%, -1% 90.2%, -1% 90%, 101% 90%, 101% 80.4%, -1% 80.4%, -1% 80%, 101% 80%, 101% 70.8%, -1% 70.8%, -1% 70%, 101% 70%, 101% 61.2%, -1% 61.2%, -1% 60%, 101% 60%, 101% 51.9%, -1% 51.9%, -1% 50%, 101% 50%, 101% 42.8%, -1% 42.8%, -1% 40%, 101% 40%, 101% 34.1%, -1% 34.1%, -1% 30%, 101% 30%, 101% 26%, -1% 26%, -1% 20%, 101% 20%, 101% 18.9%, -1% 18.9%, -1% 10%, 101% 10%, 101% 10%, -1% 10%); }
  42.3% { clip-path: polygon(-1% 100%, 101% 100%, 101% 90.1%, -1% 90.1%, -1% 90%, 101% 90%, 101% 80.2%, -1% 80.2%, -1% 80%, 101% 80%, 101% 70.5%, -1% 70.5%, -1% 70%, 101% 70%, 101% 60.8%, -1% 60.8%, -1% 60%, 101% 60%, 101% 51.3%, -1% 51.3%, -1% 50%, 101% 50%, 101% 42%, -1% 42%, -1% 40%, 101% 40%, 101% 33%, -1% 33%, -1% 30%, 101% 30%, 101% 24.4%, -1% 24.4%, -1% 20%, 101% 20%, 101% 16.4%, -1% 16.4%, -1% 10%, 101% 10%, 101% 9.5%, -1% 9.5%); }
  46.2% { clip-path: polygon(-1% 100%, 101% 100%, 101% 90%, -1% 90%, -1% 90%, 101% 90%, 101% 80.1%, -1% 80.1%, -1% 80%, 101% 80%, 101% 70.3%, -1% 70.3%, -1% 70%, 101% 70%, 101% 60.5%, -1% 60.5%, -1% 60%, 101% 60%, 101% 50.9%, -1% 50.9%, -1% 50%, 101% 50%, 101% 41.4%, -1% 41.4%, -1% 40%, 101% 40%, 101% 32.1%, -1% 32.1%, -1% 30%, 101% 30%, 101% 23.2%, -1% 23.2%, -1% 20%, 101% 20%, 101% 14.6%, -1% 14.6%, -1% 10%, 101% 10%, 101% 6.8%, -1% 6.8%); }
  50% { clip-path: polygon(-1% 100%, 101% 100%, 101% 89.9%, -1% 89.9%, -1% 90%, 101% 90%, 101% 80%, -1% 80%, -1% 80%, 101% 80%, 101% 70.1%, -1% 70.1%, -1% 70%, 101% 70%, 101% 60.3%, -1% 60.3%, -1% 60%, 101% 60%, 101% 50.6%, -1% 50.6%, -1% 50%, 101% 50%, 101% 41%, -1% 41%, -1% 40%, 101% 40%, 101% 31.5%, -1% 31.5%, -1% 30%, 101% 30%, 101% 22.3%, -1% 22.3%, -1% 20%, 101% 20%, 101% 13.4%, -1% 13.4%, -1% 10%, 101% 10%, 101% 5%, -1% 5%); }
  53.8% { clip-path: polygon(-1% 100%, 101% 100%, 101% 89.9%, -1% 89.9%, -1% 90%, 101% 90%, 101% 80%, -1% 80%, -1% 80%, 101% 80%, 101% 70%, -1% 70%, -1% 70%, 101% 70%, 101% 60.2%, -1% 60.2%, -1% 60%, 101% 60%, 101% 50.4%, -1% 50.4%, -1% 50%, 101% 50%, 101% 40.6%, -1% 40.6%, -1% 40%, 101% 40%, 101% 31.1%, -1% 31.1%, -1% 30%, 101% 30%, 101% 21.6%, -1% 21.6%, -1% 20%, 101% 20%, 101% 12.4%, -1% 12.4%, -1% 10%, 101% 10%, 101% 3.6%, -1% 3.6%); }
  57.7% { clip-path: polygon(-1% 100%, 101% 100%, 101% 89.9%, -1% 89.9%, -1% 90%, 101% 90%, 101% 79.9%, -1% 79.9%, -1% 80%, 101% 80%, 101% 70%, -1% 70%, -1% 70%, 101% 70%, 101% 60%, -1% 60%, -1% 60%, 101% 60%, 101% 50.2%, -1% 50.2%, -1% 50%, 101% 50%, 101% 40.4%, -1% 40.4%, -1% 40%, 101% 40%, 101% 30.7%, -1% 30.7%, -1% 30%, 101% 30%, 101% 21.1%, -1% 21.1%, -1% 20%, 101% 20%, 101% 11.8%, -1% 11.8%, -1% 10%, 101% 10%, 101% 2.6%, -1% 2.6%); }
  61.5% { clip-path: polygon(-1% 100%, 101% 100%, 101% 89.9%, -1% 89.9%, -1% 90%, 101% 90%, 101% 79.9%, -1% 79.9%, -1% 80%, 101% 80%, 101% 69.9%, -1% 69.9%, -1% 70%, 101% 70%, 101% 60%, -1% 60%, -1% 60%, 101% 60%, 101% 50.1%, -1% 50.1%, -1% 50%, 101% 50%, 101% 40.2%, -1% 40.2%, -1% 40%, 101% 40%, 101% 30.4%, -1% 30.4%, -1% 30%, 101% 30%, 101% 20.8%, -1% 20.8%, -1% 20%, 101% 20%, 101% 11.2%, -1% 11.2%, -1% 10%, 101% 10%, 101% 1.9%, -1% 1.9%); }
  65.4% { clip-path: polygon(-1% 100%, 101% 100%, 101% 89.9%, -1% 89.9%, -1% 90%, 101% 90%, 101% 79.9%, -1% 79.9%, -1% 80%, 101% 80%, 101% 69.9%, -1% 69.9%, -1% 70%, 101% 70%, 101% 59.9%, -1% 59.9%, -1% 60%, 101% 60%, 101% 50%, -1% 50%, -1% 50%, 101% 50%, 101% 40.1%, -1% 40.1%, -1% 40%, 101% 40%, 101% 30.2%, -1% 30.2%, -1% 30%, 101% 30%, 101% 20.5%, -1% 20.5%, -1% 20%, 101% 20%, 101% 10.8%, -1% 10.8%, -1% 10%, 101% 10%, 101% 1.3%, -1% 1.3%); }
  69.2% { clip-path: polygon(-1% 100%, 101% 100%, 101% 89.9%, -1% 89.9%, -1% 90%, 101% 90%, 101% 79.9%, -1% 79.9%, -1% 80%, 101% 80%, 101% 69.9%, -1% 69.9%, -1% 70%, 101% 70%, 101% 59.9%, -1% 59.9%, -1% 60%, 101% 60%, 101% 49.9%, -1% 49.9%, -1% 50%, 101% 50%, 101% 40%, -1% 40%, -1% 40%, 101% 40%, 101% 30.1%, -1% 30.1%, -1% 30%, 101% 30%, 101% 20.3%, -1% 20.3%, -1% 20%, 101% 20%, 101% 10.5%, -1% 10.5%, -1% 10%, 101% 10%, 101% 0.9%, -1% 0.9%); }
  73.1% { clip-path: polygon(-1% 100%, 101% 100%, 101% 89.9%, -1% 89.9%, -1% 90%, 101% 90%, 101% 79.9%, -1% 79.9%, -1% 80%, 101% 80%, 101% 69.9%, -1% 69.9%, -1% 70%, 101% 70%, 101% 59.9%, -1% 59.9%, -1% 60%, 101% 60%, 101% 49.9%, -1% 49.9%, -1% 50%, 101% 50%, 101% 39.9%, -1% 39.9%, -1% 40%, 101% 40%, 101% 30%, -1% 30%, -1% 30%, 101% 30%, 101% 20.1%, -1% 20.1%, -1% 20%, 101% 20%, 101% 10.3%, -1% 10.3%, -1% 10%, 101% 10%, 101% 0.6%, -1% 0.6%); }
  76.9% { clip-path: polygon(-1% 100%, 101% 100%, 101% 89.9%, -1% 89.9%, -1% 90%, 101% 90%, 101% 79.9%, -1% 79.9%, -1% 80%, 101% 80%, 101% 69.9%, -1% 69.9%, -1% 70%, 101% 70%, 101% 59.9%, -1% 59.9%, -1% 60%, 101% 60%, 101% 49.9%, -1% 49.9%, -1% 50%, 101% 50%, 101% 39.9%, -1% 39.9%, -1% 40%, 101% 40%, 101% 30%, -1% 30%, -1% 30%, 101% 30%, 101% 20%, -1% 20%, -1% 20%, 101% 20%, 101% 10.2%, -1% 10.2%, -1% 10%, 101% 10%, 101% 0.4%, -1% 0.4%); }
  80.8% { clip-path: polygon(-1% 100%, 101% 100%, 101% 89.9%, -1% 89.9%, -1% 90%, 101% 90%, 101% 79.9%, -1% 79.9%, -1% 80%, 101% 80%, 101% 69.9%, -1% 69.9%, -1% 70%, 101% 70%, 101% 59.9%, -1% 59.9%, -1% 60%, 101% 60%, 101% 49.9%, -1% 49.9%, -1% 50%, 101% 50%, 101% 39.9%, -1% 39.9%, -1% 40%, 101% 40%, 101% 29.9%, -1% 29.9%, -1% 30%, 101% 30%, 101% 20%, -1% 20%, -1% 20%, 101% 20%, 101% 10%, -1% 10%, -1% 10%, 101% 10%, 101% 0.2%, -1% 0.2%); }
  84.6% { clip-path: polygon(-1% 100%, 101% 100%, 101% 89.9%, -1% 89.9%, -1% 90%, 101% 90%, 101% 79.9%, -1% 79.9%, -1% 80%, 101% 80%, 101% 69.9%, -1% 69.9%, -1% 70%, 101% 70%, 101% 59.9%, -1% 59.9%, -1% 60%, 101% 60%, 101% 49.9%, -1% 49.9%, -1% 50%, 101% 50%, 101% 39.9%, -1% 39.9%, -1% 40%, 101% 40%, 101% 29.9%, -1% 29.9%, -1% 30%, 101% 30%, 101% 19.9%, -1% 19.9%, -1% 20%, 101% 20%, 101% 10%, -1% 10%, -1% 10%, 101% 10%, 101% 0.1%, -1% 0.1%); }
  88.5% { clip-path: polygon(-1% 100%, 101% 100%, 101% 89.9%, -1% 89.9%, -1% 90%, 101% 90%, 101% 79.9%, -1% 79.9%, -1% 80%, 101% 80%, 101% 69.9%, -1% 69.9%, -1% 70%, 101% 70%, 101% 59.9%, -1% 59.9%, -1% 60%, 101% 60%, 101% 49.9%, -1% 49.9%, -1% 50%, 101% 50%, 101% 39.9%, -1% 39.9%, -1% 40%, 101% 40%, 101% 29.9%, -1% 29.9%, -1% 30%, 101% 30%, 101% 19.9%, -1% 19.9%, -1% 20%, 101% 20%, 101% 9.9%, -1% 9.9%, -1% 10%, 101% 10%, 101% -0%, -1% -0%); }
  92.3% { clip-path: polygon(-1% 100%, 101% 100%, 101% 89.9%, -1% 89.9%, -1% 90%, 101% 90%, 101% 79.9%, -1% 79.9%, -1% 80%, 101% 80%, 101% 69.9%, -1% 69.9%, -1% 70%, 101% 70%, 101% 59.9%, -1% 59.9%, -1% 60%, 101% 60%, 101% 49.9%, -1% 49.9%, -1% 50%, 101% 50%, 101% 39.9%, -1% 39.9%, -1% 40%, 101% 40%, 101% 29.9%, -1% 29.9%, -1% 30%, 101% 30%, 101% 19.9%, -1% 19.9%, -1% 20%, 101% 20%, 101% 9.9%, -1% 9.9%, -1% 10%, 101% 10%, 101% -0.1%, -1% -0.1%); }
  96.2% { clip-path: polygon(-1% 100%, 101% 100%, 101% 89.9%, -1% 89.9%, -1% 90%, 101% 90%, 101% 79.9%, -1% 79.9%, -1% 80%, 101% 80%, 101% 69.9%, -1% 69.9%, -1% 70%, 101% 70%, 101% 59.9%, -1% 59.9%, -1% 60%, 101% 60%, 101% 49.9%, -1% 49.9%, -1% 50%, 101% 50%, 101% 39.9%, -1% 39.9%, -1% 40%, 101% 40%, 101% 29.9%, -1% 29.9%, -1% 30%, 101% 30%, 101% 19.9%, -1% 19.9%, -1% 20%, 101% 20%, 101% 9.9%, -1% 9.9%, -1% 10%, 101% 10%, 101% -0.1%, -1% -0.1%); }
  100% { clip-path: polygon(-1% 100%, 101% 100%, 101% 89.9%, -1% 89.9%, -1% 90%, 101% 90%, 101% 79.9%, -1% 79.9%, -1% 80%, 101% 80%, 101% 69.9%, -1% 69.9%, -1% 70%, 101% 70%, 101% 59.9%, -1% 59.9%, -1% 60%, 101% 60%, 101% 49.9%, -1% 49.9%, -1% 50%, 101% 50%, 101% 39.9%, -1% 39.9%, -1% 40%, 101% 40%, 101% 29.9%, -1% 29.9%, -1% 30%, 101% 30%, 101% 19.9%, -1% 19.9%, -1% 20%, 101% 20%, 101% 9.9%, -1% 9.9%, -1% 10%, 101% 10%, 101% -0.1%, -1% -0.1%); }
}
::view-transition-new(root) {
  animation: yh-vt-rise 518ms linear both;
  mix-blend-mode: normal;
}
::view-transition-group(yh-nav),
::view-transition-group(yh-bar),
::view-transition-group(yh-chip),
::view-transition-group(yh-foot) {
  animation-duration: 520ms;
  animation-timing-function: cubic-bezier(0.165, 0.84, 0.44, 1);
}
::view-transition-old(yh-nav),
::view-transition-old(yh-bar),
::view-transition-old(yh-chip),
::view-transition-old(yh-foot) { animation: none; mix-blend-mode: normal; }
::view-transition-new(yh-nav),
::view-transition-new(yh-bar),
::view-transition-new(yh-chip),
::view-transition-new(yh-foot) { animation: yh-vt-in 320ms cubic-bezier(0.165, 0.84, 0.44, 1) both; mix-blend-mode: normal; }

/* the home model pops away (public/js/viewer3d.js names it yh-model on the way out): its snapshot swells to 107% in the first 30%, then
   shrinks to 0 (ease-in), 320ms in all: faster than the 1000ms spring it came in with, and over before the new page has covered the
   scene (the ten bands take 518ms). The orbits and the text ring stay in the old page's snapshot under the rising new page. Scales from
   the centre of the snapshot, which is the model's centre. Pages without the model never have the name. */
@keyframes yh-model-pop {
  from { scale: 0; }
  to { scale: 1; }
}
@keyframes yh-model-out {
  0% { scale: 1; animation-timing-function: cubic-bezier(0.2, 0.7, 0.3, 1); }
  30% { scale: 1.07; animation-timing-function: cubic-bezier(0.4, 0, 0.9, 0.6); }
  100% { scale: 0; }
}
::view-transition-old(yh-model) { animation: yh-model-out 320ms linear both; mix-blend-mode: normal; }
::view-transition-new(yh-model) { animation: none; mix-blend-mode: normal; }

/* the fallback of the page transition: browsers without cross-document view transitions (Firefox, Safari before 18.2), and any load where
   Chrome's own transition did not run, get the same ten-band rise as a cover that lifts off the new page: the head script of head-open.ejs
   puts .yh-enter on <html> when the page was reached from another page of the site, the cover (paper colour, fixed to the window) is
   opened band by band from the bottom with the very same timing and variables as ::view-transition-new(root) above, then it is gone.
   The cover is only ever asked for by the head script (it never puts the class on a page whose browser runs its own transition), and it
   takes the class off again when the last band has opened. Under reduced motion every animation is zeroed below. */
html.yh-enter::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 2147483000;
  pointer-events: none;
  background: var(--yh-paper-hi);
  animation:
    yh-vt-b0 302ms cubic-bezier(0.165, 0.84, 0.44, 1) 0ms both,
    yh-vt-b1 302ms cubic-bezier(0.165, 0.84, 0.44, 1) 24ms both,
    yh-vt-b2 302ms cubic-bezier(0.165, 0.84, 0.44, 1) 48ms both,
    yh-vt-b3 302ms cubic-bezier(0.165, 0.84, 0.44, 1) 72ms both,
    yh-vt-b4 302ms cubic-bezier(0.165, 0.84, 0.44, 1) 96ms both,
    yh-vt-b5 302ms cubic-bezier(0.165, 0.84, 0.44, 1) 120ms both,
    yh-vt-b6 302ms cubic-bezier(0.165, 0.84, 0.44, 1) 144ms both,
    yh-vt-b7 302ms cubic-bezier(0.165, 0.84, 0.44, 1) 168ms both,
    yh-vt-b8 302ms cubic-bezier(0.165, 0.84, 0.44, 1) 192ms both,
    yh-vt-b9 302ms cubic-bezier(0.165, 0.84, 0.44, 1) 216ms both;
  animation-play-state: paused;   /* closed until the page's first frame is up (.yh-go, head-open.ejs) */
  -webkit-mask-image:
    linear-gradient(0deg, transparent var(--yh-b0), #000 var(--yh-b0)),
    linear-gradient(0deg, transparent var(--yh-b1), #000 var(--yh-b1)),
    linear-gradient(0deg, transparent var(--yh-b2), #000 var(--yh-b2)),
    linear-gradient(0deg, transparent var(--yh-b3), #000 var(--yh-b3)),
    linear-gradient(0deg, transparent var(--yh-b4), #000 var(--yh-b4)),
    linear-gradient(0deg, transparent var(--yh-b5), #000 var(--yh-b5)),
    linear-gradient(0deg, transparent var(--yh-b6), #000 var(--yh-b6)),
    linear-gradient(0deg, transparent var(--yh-b7), #000 var(--yh-b7)),
    linear-gradient(0deg, transparent var(--yh-b8), #000 var(--yh-b8)),
    linear-gradient(0deg, transparent var(--yh-b9), #000 var(--yh-b9));
  mask-image:
    linear-gradient(0deg, transparent var(--yh-b0), #000 var(--yh-b0)),
    linear-gradient(0deg, transparent var(--yh-b1), #000 var(--yh-b1)),
    linear-gradient(0deg, transparent var(--yh-b2), #000 var(--yh-b2)),
    linear-gradient(0deg, transparent var(--yh-b3), #000 var(--yh-b3)),
    linear-gradient(0deg, transparent var(--yh-b4), #000 var(--yh-b4)),
    linear-gradient(0deg, transparent var(--yh-b5), #000 var(--yh-b5)),
    linear-gradient(0deg, transparent var(--yh-b6), #000 var(--yh-b6)),
    linear-gradient(0deg, transparent var(--yh-b7), #000 var(--yh-b7)),
    linear-gradient(0deg, transparent var(--yh-b8), #000 var(--yh-b8)),
    linear-gradient(0deg, transparent var(--yh-b9), #000 var(--yh-b9));
  -webkit-mask-size: 100% 10%;
  mask-size: 100% 10%;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position:
    0 100%,
    0 88.8889%,
    0 77.7778%,
    0 66.6667%,
    0 55.5556%,
    0 44.4444%,
    0 33.3333%,
    0 22.2222%,
    0 11.1111%,
    0 0;
  mask-position:
    0 100%,
    0 88.8889%,
    0 77.7778%,
    0 66.6667%,
    0 55.5556%,
    0 44.4444%,
    0 33.3333%,
    0 22.2222%,
    0 11.1111%,
    0 0;
}
html.yh-enter.yh-go::before { animation-play-state: running; }

/* ---------- reduced motion: the final state at once, no page transition ---------- */

@media (prefers-reduced-motion: reduce) {
  /* the page transition stays, but as a short cross-fade (no rise, no morph, no model pop): the OS flag (Windows: Settings > Accessibility >
     Visual effects > Animation effects off) must not make the site look as if it had no transitions at all */
  ::view-transition-new(root) {
    animation: yh-vt-in 200ms ease both;
  }
  ::view-transition-group(yh-nav),
  ::view-transition-group(yh-bar),
  ::view-transition-group(yh-chip),
  ::view-transition-group(yh-foot) { animation-duration: 0.01ms; }
  ::view-transition-old(yh-model) { display: none; }
  html.yh-enter::before { display: none; }
  *,
  *::before,
  *::after {
    animation-delay: 0s !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-delay: 0s !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
