/* =============================================================================================
   Softdot.Studio theme: fonts, tokens, base, typography, buttons, footer.
   Loaded on every page through SiteHeader::head(), before the header and the page stylesheet.

   Two worlds: ink (dark, default) and paper (light). A section opts into paper with
   .is-paper; components read the semantic tokens (--fg, --bg, --line …), never raw colours.
   Accents carry meaning: cyan = technology, amber = operations, signal red = rework only.
   ============================================================================================= */

/* Local review stars, shared by the home chapter and the product catalogue. */
.review-stars {
    display: inline-flex;
    flex: none;
    gap: 3px;
    align-items: center;
    color: var(--w-care);
    vertical-align: middle;
}

.review-star {
    display: block;
    flex: none;
}

/* --- Self-hosted fonts (OFL, see shared/fonts/LICENSES.md) ------------------------------------ */

@font-face {
    font-family: Newsreader;
    font-style: normal;
    font-weight: 300 600;
    font-display: swap;
    src: url("fonts/newsreader-display.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: Newsreader;
    font-style: italic;
    font-weight: 300 600;
    font-display: swap;
    src: url("fonts/newsreader-display-italic.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 reading cut of the italic (optical size 12): the italic lines at text size, which the
   display cut (optical size 48, for titles) sets too tight and thin (Maurice, 2026-10-21). */
@font-face {
    font-family: "Newsreader Text";
    font-style: italic;
    font-weight: 300 600;
    font-display: swap;
    src: url("fonts/newsreader-text-italic.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: "Instrument Sans";
    font-style: normal;
    font-weight: 400 700;
    font-display: swap;
    src: url("fonts/instrument-sans.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: "IBM Plex Mono";
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url("fonts/ibm-plex-mono-400.woff2") format("woff2");
}

@font-face {
    font-family: "IBM Plex Mono";
    font-style: normal;
    font-weight: 500 700;
    font-display: swap;
    src: url("fonts/ibm-plex-mono-500.woff2") format("woff2");
}

@font-face {
    font-family: Caveat;
    font-style: normal;
    font-weight: 400 700;
    font-display: swap;
    src: url("fonts/caveat-500.woff2") format("woff2");
}

/* Metric-matched local fallbacks: the swap to the web font barely moves a line. */
@font-face {
    font-family: "Newsreader Fallback";
    src: local("Georgia"), local("Times New Roman");
    size-adjust: 97.42%;
    ascent-override: 75.44%;
    descent-override: 27.2%;
    line-gap-override: 0%;
}

@font-face {
    font-family: "Instrument Sans Fallback";
    src: local("Arial"), local("Helvetica Neue"), local("Roboto");
    size-adjust: 102.15%;
    ascent-override: 94.96%;
    descent-override: 24.47%;
    line-gap-override: 0%;
}

@font-face {
    font-family: "IBM Plex Mono Fallback";
    src: local("Consolas"), local("Menlo"), local("Courier New");
    size-adjust: 109.13%;
    ascent-override: 93.92%;
    descent-override: 25.2%;
    line-gap-override: 0%;
}

/* --- Tokens ------------------------------------------------------------------------------------ */

:root {
    /* Raw palette */
    --ink-0: #050709;
    --ink-1: #07090d;
    --ink-2: #0e1218;
    --ink-3: #151b23;
    --ink-line: #1c2430;
    --ink-line-strong: #2a3442;
    --ink-fg: #e8ecf1;
    --ink-fg-2: #a9b3c1;
    --ink-fg-3: #7d8796;
    --paper-0: #f7f4ee;
    --paper-1: #f2eee6;
    --paper-2: #e8e2d6;
    --paper-line: #d6cfc1;
    --paper-line-strong: #b9b0a0;
    --paper-fg: #0b0e12;
    --paper-fg-2: #3c4450;
    --paper-fg-3: #5f6672;
    --cyan: #3ee6ff;
    --cyan-ink: #00687a;
    --amber: #ffb54a;
    --amber-ink: #8a4b00;
    --signal: #ff5b4f;
    --signal-ink: #b3261e;

    /* World colours (draft "Tropfen", 2026-10-20): one light per world of the home page; the
       products page takes the colours of its groups from here (apps rosé, trading emerald). */
    --w-web: #6faeff;
    --w-software: #3ee6ff;
    --w-ai: #a98cff;
    --w-trading: #45e3a0;
    --w-apps: #ff8fb6;
    --w-games: #c6ee5e;
    --w-pearl: #ece6dc;
    --w-care: #ffb54a;

    /* Semantic (ink world by default) */
    --bg: var(--ink-1);
    --bg-raised: var(--ink-2);
    --fg: var(--ink-fg);
    --fg-2: var(--ink-fg-2);
    --fg-3: var(--ink-fg-3);
    --line: var(--ink-line);
    --line-strong: var(--ink-line-strong);
    --tech: var(--cyan);
    --ops: var(--amber);
    --rework: var(--signal);
    --focus: var(--cyan);

    /* Type */
    --font-display: newsreader, "Newsreader Fallback", georgia, serif;
    --font-voice: "Newsreader Text", newsreader, "Newsreader Fallback", georgia, serif;
    --font-text: "Instrument Sans", "Instrument Sans Fallback", system-ui, sans-serif;
    --font-data: "IBM Plex Mono", "IBM Plex Mono Fallback", consolas, monospace;
    --font-hand: caveat, "Segoe Print", "Bradley Hand", cursive;
    --step-n1: clamp(0.82rem, 0.79rem + 0.12vw, 0.9rem);
    --step-0: clamp(1rem, 0.96rem + 0.18vw, 1.125rem);
    --step-1: clamp(1.15rem, 1.06rem + 0.42vw, 1.42rem);
    --step-2: clamp(1.45rem, 1.25rem + 0.9vw, 2.05rem);
    --step-3: clamp(1.9rem, 1.5rem + 1.9vw, 3.2rem);
    --step-4: clamp(2.35rem, 1.65rem + 3.3vw, 4.9rem);
    --step-5: clamp(2.7rem, 1.6rem + 5.2vw, 7.1rem);

    /* Space and shape */
    --gutter: clamp(20px, 5vw, 72px);
    --measure: 38rem;
    --page-max: 1440px;
    --radius-s: 6px;
    --radius-m: 12px;
    --radius-l: 22px;

    /* One fluid spacing scale for every page. Pages name the roles they use (kicker to title,
       title to lead …) on top of these steps instead of writing their own numbers. */
    --space-1: clamp(4px, 0.15vw + 3px, 6px);
    --space-2: clamp(8px, 0.3vw + 6px, 12px);
    --space-3: clamp(12px, 0.45vw + 9px, 18px);
    --space-4: clamp(18px, 0.6vw + 14px, 26px);
    --space-5: clamp(24px, 1.1vw + 18px, 40px);
    --space-6: clamp(36px, 2vw + 24px, 64px);
    --space-7: clamp(52px, 3vw + 32px, 92px);
    --space-8: clamp(72px, 4.6vw + 40px, 128px);

    /* Motion: durations and curves shared by every transition and animation */
    --dur-1: 0.18s;
    --dur-2: 0.32s;
    --dur-3: 0.6s;
    --dur-4: 0.9s;
    --dur-5: 1.4s;
    --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
    --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
    --ease-spring: cubic-bezier(0.34, 1.4, 0.64, 1);
    --ease-glide: cubic-bezier(0.45, 0, 0.15, 1);

    color-scheme: dark;
}

/* The light world: a section (or the contact sheet) switches its whole subtree. */
.is-paper {
    --bg: var(--paper-1);
    --bg-raised: var(--paper-0);
    --fg: var(--paper-fg);
    --fg-2: var(--paper-fg-2);
    --fg-3: var(--paper-fg-3);
    --line: var(--paper-line);
    --line-strong: var(--paper-line-strong);
    --tech: var(--cyan-ink);
    --ops: var(--amber-ink);
    --rework: var(--signal-ink);
    --focus: var(--cyan-ink);

    color-scheme: light;
    color: var(--fg);
}

/* --- Base -------------------------------------------------------------------------------------- */

*,
*::before,
*::after {
    box-sizing: border-box;
}

html {
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
    background: var(--ink-1);
}

body {
    margin: 0;
    min-height: 100vh;
    background: var(--bg);
    color: var(--fg);
    font-family: var(--font-text);
    font-size: var(--step-0);
    line-height: 1.6;
    font-kerning: normal;
    font-variant-ligatures: common-ligatures;
    text-rendering: optimizelegibility;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    overflow-wrap: break-word;
}

img,
svg,
video,
canvas {
    display: block;
    max-width: 100%;
}

img {
    height: auto;
}

h1,
h2,
h3,
h4,
p,
figure,
blockquote,
dl,
dd,
ol,
ul {
    margin: 0;
}

button,
input,
select,
textarea {
    font: inherit;
    color: inherit;
}

a {
    color: inherit;
    text-decoration-thickness: 1px;
    text-underline-offset: 0.2em;
}

::selection {
    background: rgba(62, 230, 255, 0.28);
    color: inherit;
}

.is-paper ::selection {
    background: rgba(0, 104, 122, 0.18);
}

:focus-visible {
    outline: 2px solid var(--focus);
    outline-offset: 3px;
    border-radius: 2px;
}

.skip-link {
    position: absolute;
    top: 8px;
    left: 8px;
    z-index: 3000;
    display: inline-flex;
    align-items: center;
    min-height: 44px; /* A full 44 px touch target on phones too (independent live check, 2026-10-29). */
    padding: 12px 18px;
    border-radius: var(--radius-s);
    background: var(--cyan);
    color: var(--ink-1);
    font-weight: 600;
    text-decoration: none;
    transform: translateY(-160%);
    transition: transform 0.2s var(--ease-out);
}

.skip-link:focus-visible {
    transform: none;
}

.visually-hidden {
    position: absolute !important;
    width: 1px !important;
    height: 1px !important;
    overflow: hidden !important;
    clip-path: inset(50%) !important;
    white-space: nowrap !important;
}

/* --- Typography -------------------------------------------------------------------------------- */

.t-display,
.t-h2,
.t-h3 {
    font-family: var(--font-display);
    font-weight: 400;
    letter-spacing: -0.012em;
    text-wrap: balance;
}

.t-display {
    font-size: var(--step-5);
    line-height: 0.98;
    letter-spacing: -0.022em;
}

.t-h2 {
    font-size: var(--step-4);
    line-height: 1.02;
}

.t-h3 {
    font-size: var(--step-2);
    line-height: 1.15;
}

.t-display em,
.t-h2 em,
.t-h3 em {
    font-style: italic;
}

.t-lead {
    max-width: var(--measure);
    color: var(--fg-2);
    font-size: var(--step-1);
    line-height: 1.55;
    text-wrap: pretty;
}

.t-body {
    max-width: var(--measure);
    color: var(--fg-2);
    text-wrap: pretty;
}

.t-kicker {
    display: inline-flex;
    align-items: center;
    gap: 0.75em;
    color: var(--fg-3);
    font-family: var(--font-data);
    font-size: 0.78rem;
    font-weight: 500;
    letter-spacing: 0.14em;
    text-transform: uppercase;
}

.t-kicker::before {
    content: "";
    width: 22px;
    height: 1px;
    background: currentcolor;
    opacity: 0.6;
}

.t-data {
    font-family: var(--font-data);
    font-size: 0.85em;
    letter-spacing: 0.01em;
    font-variant-numeric: tabular-nums;
}

.t-tech {
    color: var(--tech);
}

.t-ops {
    color: var(--ops);
}

/* --- Buttons and links ------------------------------------------------------------------------- */

.btn {
    --btn-bg: var(--fg);
    --btn-fg: var(--bg);

    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.7em;
    min-height: 52px;
    padding: 0 1.5em;
    border: 1px solid transparent;
    border-radius: 999px;
    background: var(--btn-bg);
    color: var(--btn-fg);
    font-family: var(--font-text);
    font-size: 0.98rem;
    font-weight: 600;
    letter-spacing: 0.005em;
    line-height: 1.2;
    text-decoration: none;
    cursor: pointer;
    isolation: isolate;
    transition: transform 0.35s var(--ease-out), background-color 0.25s ease, color 0.25s ease, border-color 0.25s ease;
    -webkit-tap-highlight-color: transparent;
}

.btn svg {
    flex: none;
    width: 18px;
    height: 18px;
    transition: transform 0.35s var(--ease-out);
}

.btn--primary {
    --btn-bg: var(--cyan);
    --btn-fg: var(--ink-1);
}

.is-paper .btn--primary {
    --btn-bg: var(--paper-fg);
    --btn-fg: var(--paper-0);
}

.btn--ghost {
    --btn-bg: transparent;
    --btn-fg: var(--fg);

    border-color: var(--line-strong);
}

.btn--quiet {
    --btn-bg: transparent;
    --btn-fg: var(--fg);

    min-height: 44px;
    padding: 0 0.25em;
    border-radius: var(--radius-s);
}

@media (hover: hover) {
    .btn:hover svg {
        transform: translateX(3px);
    }

    .btn--primary:hover {
        transform: translateY(-2px);
    }

    .btn--ghost:hover {
        border-color: var(--fg);
    }
}

.btn:active {
    transform: scale(0.97);
}

.link-arrow {
    display: inline-flex;
    align-items: center;
    gap: 0.45em;
    min-height: 44px;
    color: var(--fg);
    font-weight: 600;
    text-decoration: none;
}

.link-arrow::after {
    content: "";
    width: 0.62em;
    height: 0.62em;
    border-top: 1.5px solid currentcolor;
    border-right: 1.5px solid currentcolor;
    transform: rotate(45deg);
    transition: transform 0.3s var(--ease-out);
}

.link-arrow[target="_blank"]::after {
    transform: rotate(0deg);
}

.link-arrow--quiet {
    color: var(--fg-2);
    font-weight: 500;
}

@media (hover: hover) {
    .link-arrow:hover::after {
        transform: translateX(3px) rotate(45deg);
    }

    .link-arrow[target="_blank"]:hover::after {
        transform: translate(2px, -2px);
    }
}

/* --- The protected e-mail address (site_mail.php, shared/mail.js, 2026-10-26) -------------------
   The address as the outlines of its letters (IBM Plex Mono, like the text that replaces them: 0.6em
   a letter, 1.3em high, the baseline 1.025em from the top), a press makes it a link. Picture and
   link keep one box: a line height of 1.3 puts the text where the letters of the picture were. Inline
   the key and the link reach 44 px through padding the negative margin takes back from the line;
   as a button the picture sits in a ghost pill. Motion only in shared/mail.js (transform, opacity). */

.sd-mail {
    position: relative;
    color: var(--fg);
    font-family: var(--font-data);
    font-weight: 400;
    letter-spacing: 0;
    white-space: nowrap;
}

.sd-mail--inline {
    font-size: 0.92em;
}

.sd-mail--button {
    display: inline-flex;
    flex-wrap: wrap;
    gap: 6px;
    align-items: center;
    font-size: 0.86rem;
}

.sd-mail-key,
.sd-mail-link {
    color: inherit;
    font: inherit;
    -webkit-tap-highlight-color: transparent;
}

.sd-mail--inline .sd-mail-key,
.sd-mail--inline .sd-mail-link {
    display: inline-block;
    margin-block: -13px;
    padding: 13px 0;
    border: 0;
    border-radius: 6px;
    background: none;
    line-height: 1.3;
    text-decoration: none;
    cursor: pointer;
}

.sd-mail-face {
    display: inline-block;
    width: 13.2em;
    height: 1.3em;
    overflow: visible;
    vertical-align: top;
}

.sd-mail-rule {
    stroke-width: 1px;
    stroke-dasharray: 1.5 3;
    opacity: 0.55;
    transition: opacity var(--dur-1) ease;
}

/* As a button: the theme's 18 px for icons in buttons is meant for the mail icon, not the letters. */
.sd-mail--button .sd-mail-key,
.sd-mail--button .sd-mail-link {
    font-family: var(--font-data);
    font-size: inherit;
    font-weight: 400;
}

.btn .sd-mail-face,
.btn:hover .sd-mail-face {
    width: 13.2em;
    height: 1.3em;
    transform: none;
}

.sd-mail-text {
    position: relative;
    display: inline-block;
    line-height: 1.3;
    clip-path: inset(0);
}

.sd-mail--inline .sd-mail-text {
    text-decoration: underline;
    text-decoration-color: color-mix(in oklab, currentcolor 45%, transparent);
    text-decoration-thickness: 1px;
    text-underline-offset: 0.2em;
}

.sd-mail-glint {
    position: absolute;
    inset: 0 -40%;
    background: linear-gradient(100deg, transparent 32%, rgba(255, 255, 255, 0.5) 50%, transparent 68%);
    pointer-events: none;
}

.sd-mail-note {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

.sd-mail.is-asking .sd-mail-key {
    cursor: progress;
}

.sd-mail.is-asking .sd-mail-face {
    opacity: 0.6;
}

.sd-mail-label {
    text-decoration: underline dotted;
    text-underline-offset: 0.25em;
    white-space: normal;
}

.sd-mail.is-asking .sd-mail-label {
    opacity: 0.6;
}

.sd-mail-consent {
    max-width: min(32rem, calc(100vw - 32px));
    padding: clamp(24px, 5vw, 40px);
    border: 1px solid rgb(255 255 255 / 18%);
    border-radius: 28px;
    color: var(--fg);
    background: radial-gradient(ellipse at 30% 0%, #243748, #11151e 75%);
    box-shadow: 0 24px 80px rgb(0 0 0 / 55%);
    font-family: var(--font-text);
}

.sd-mail-consent::backdrop {
    background: rgb(4 7 14 / 78%);
}

.sd-mail-consent h2 {
    margin: 0 0 16px;
    font-size: 1.5rem;
}

.sd-mail-consent p {
    margin: 0 0 16px;
    line-height: 1.65;
}

.sd-mail-consent > a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    color: inherit;
}

.sd-mail-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    margin-top: 20px;
}

.sd-mail-actions .btn {
    white-space: normal;
}

.sd-mail--inline :is(.sd-mail-key, .sd-mail-link):focus-visible {
    outline: 2px solid var(--focus);
    outline-offset: -8px;
}

/* The copy button: a small round light after the address, 44 px to the touch. */
.sd-mail-copy {
    position: relative;
    display: inline-grid;
    place-items: center;
    width: 44px;
    height: 44px;
    margin-block: -13px;
    margin-inline-start: 2px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: none;
    color: var(--fg-2);
    vertical-align: middle;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

.sd-mail-copy::before {
    content: "";
    position: absolute;
    inset: 9px;
    border: 1px solid color-mix(in oklab, currentcolor 35%, transparent);
    border-radius: 50%;
    background: rgba(9, 12, 17, 0.55);
    transition: border-color var(--dur-1) ease;
}

.sd-mail-copy svg {
    position: relative;
    grid-area: 1 / 1;
    width: 15px;
    height: 15px;
    transition: opacity var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-spring);
}

.sd-mail-done-icon {
    opacity: 0;
    transform: scale(0.5);
}

.sd-mail-copy.is-done {
    color: var(--w-trading);
}

.sd-mail-copy.is-done .sd-mail-copy-icon {
    opacity: 0;
    transform: scale(0.5);
}

.sd-mail-copy.is-done .sd-mail-done-icon {
    opacity: 1;
    transform: none;
}

.sd-mail-copy:focus-visible {
    outline: 2px solid var(--focus);
    outline-offset: -4px;
}

/* A short message above the address (copied, or no answer); shared/mail.js nudges it into the window. */
.sd-mail-bubble {
    position: absolute;
    bottom: calc(100% + 10px);
    left: 0;
    z-index: 5;
    width: max-content;
    max-width: min(22rem, calc(100vw - 16px));
    padding: 7px 12px;
    border: 1px solid rgba(214, 224, 240, 0.18);
    border-radius: 12px;
    background: rgba(9, 12, 17, 0.94);
    color: var(--fg);
    font-family: var(--font-text);
    font-size: 0.8rem;
    line-height: 1.4;
    white-space: normal;
    opacity: 0;
    transform: translate(var(--nudge, 0), 4px);
    transition: opacity var(--dur-2) ease, transform var(--dur-2) var(--ease-out);
    pointer-events: none;
}

.sd-mail-bubble.is-shown {
    opacity: 1;
    transform: translate(var(--nudge, 0), 0);
}

.sd-mail-bubble.is-failed {
    border-color: color-mix(in oklab, var(--w-care) 45%, transparent);
}

@media (hover: hover) {
    .sd-mail--inline .sd-mail-key:hover .sd-mail-rule {
        opacity: 1;
    }

    .sd-mail-copy:hover {
        color: var(--fg);
    }

    .sd-mail-copy:hover::before {
        border-color: color-mix(in oklab, currentcolor 70%, transparent);
    }
}

/* --- Guided build-up ---------------------------------------------------------------------------
   A [data-reveal-group] shows its [data-reveal] parts in reading order once it is reached
   (.is-in, stagger --ri × --part-step; welcome/js/reveal.js, on the home page the beats of
   welcome/js/sequence.js, which also sets --word-step per chapter). The hiding exists only while
   html.reveal is set: the page's inline script sets it and removes it again unless the module
   confirms in time. */

html.reveal [data-reveal-group] [data-reveal],
html.reveal [data-reveal-group][data-reveal] {
    opacity: 0;
    translate: 0 24px;
    transition: opacity var(--dur-4) var(--ease-out), translate 1.1s var(--ease-out);
    transition-delay: calc(var(--ri, 0) * var(--part-step, 105ms));
}

html.reveal [data-reveal-group].is-in [data-reveal],
html.reveal [data-reveal-group].is-in[data-reveal] {
    opacity: 1;
    translate: none;
}

/* Words (site_text.php): the heading stays in place, its words rise one after another in reading
   order and a soft light passes behind them once. The spans are inline blocks in every state, so
   the line breaks never change between hidden and shown. */
.w {
    display: inline-block;
}

[data-reveal="words"] {
    position: relative;
    isolation: isolate;
}

[data-reveal="words"]::before {
    content: "";
    position: absolute;
    inset: -0.3em -0.8em;
    z-index: -1;
    border-radius: 50%;
    background: radial-gradient(closest-side, var(--words-light, rgba(62, 230, 255, 0.16)), transparent);
    opacity: 0;
    pointer-events: none;
}

html.reveal [data-reveal-group] [data-reveal="words"] {
    opacity: 1;
    translate: none;
}

html.reveal [data-reveal="words"] .w {
    opacity: 0;
    translate: 0 0.4em;
    transition: opacity var(--dur-3) var(--ease-out), translate var(--dur-4) var(--ease-out);
    transition-delay: calc(var(--ri, 0) * var(--part-step, 105ms) + var(--wi, 0) * var(--word-step, 55ms));
}

html.reveal [data-reveal-group].is-in [data-reveal="words"] .w {
    opacity: 1;
    translate: none;
}

html.reveal [data-reveal-group].is-in [data-reveal="words"]::before {
    animation: words-light 2s var(--ease-out) calc(var(--ri, 0) * var(--part-step, 105ms)) both;
}

@keyframes words-light {
    0% {
        opacity: 0;
        transform: translateX(-30%) scaleX(0.6);
    }

    40% {
        opacity: 1;
    }

    100% {
        opacity: 0;
        transform: translateX(30%) scaleX(1);
    }
}

/* Deal: a card comes out of a stack in the depth (the parent gives the perspective). */
html.reveal [data-reveal-group] [data-reveal="deal"] {
    translate: 0 40px;
    rotate: x 9deg;
    scale: 0.96;
    transform-origin: 50% 100%;
    transition: opacity var(--dur-4) var(--ease-out), translate 1.1s var(--ease-out), rotate 1.1s var(--ease-out), scale 1.1s var(--ease-out);
    transition-delay: calc(var(--ri, 0) * var(--part-step, 105ms));
}

html.reveal [data-reveal-group].is-in [data-reveal="deal"] {
    translate: none;
    rotate: none;
    scale: none;
}

/* --- Footer (site_footer.php) ------------------------------------------------------------------ */

/* In the room (draft "Tropfen 3", 2026-10-23; before: an opaque block with a hard line): the room
   runs on to the end of the page behind it, a horizon of light takes the line's place, and the room
   grows a little deeper towards the bottom, for the reading. The headings carry the dot of the
   kicker lines; the links a round light on pointer and focus (as the light of the legal bar).
   Static layers, motion on opacity and transform only. */
.site-footer {
    position: relative;
    padding: clamp(64px, 9vw, 112px) var(--gutter) calc(32px + env(safe-area-inset-bottom, 0px));
    background:
        radial-gradient(60% 150px at 50% 0, rgba(214, 224, 240, 0.05), transparent),
        linear-gradient(to bottom, rgba(5, 7, 9, 0), rgba(5, 7, 9, 0.55) 55%, rgba(5, 7, 9, 0.82));
    color: var(--ink-fg-2);
    font-size: 0.94rem;
}

/* The horizon: a line of light that fades out to both sides. */
.site-footer::before {
    content: "";
    position: absolute;
    top: 0;
    left: 50%;
    width: min(var(--page-max, 1440px), 100% - 2 * var(--gutter));
    height: 1px;
    background: linear-gradient(90deg, transparent, rgba(214, 224, 240, 0.18) 24%, rgba(214, 224, 240, 0.26) 50%, rgba(214, 224, 240, 0.18) 76%, transparent);
    translate: -50% 0;
    pointer-events: none;
}

.site-footer-inner {
    display: grid;
    grid-template-columns: minmax(0, 1.4fr) repeat(3, minmax(0, 1fr));
    gap: 40px 32px;
    max-width: var(--page-max);
    margin: 0 auto;
}

.site-footer-brand {
    display: inline-flex;
    align-items: center;
    gap: 12px;
    min-height: 44px;
    color: var(--ink-fg);
    font-family: var(--font-data);
    font-size: 1.15rem;
    font-weight: 500;
    letter-spacing: -0.02em;
    text-decoration: none;
}

.site-footer-brand img {
    width: 40px;
    height: 40px;
}

.site-footer-accent {
    color: var(--cyan);
}

.site-footer-claim {
    max-width: 22rem;
    margin-top: 18px;
    color: var(--ink-fg-3);
    line-height: 1.55;
}

.site-footer h2 {
    display: flex;
    gap: 10px;
    align-items: center;
    margin-bottom: 12px;
    color: var(--ink-fg-3);
    font-family: var(--font-data);
    font-size: 0.74rem;
    font-weight: 500;
    letter-spacing: 0.14em;
    text-transform: uppercase;
}

/* The dot of the kicker lines (shared/site-drop.css, .sdot), a little smaller. */
.site-footer h2::before {
    content: "";
    flex: none;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: radial-gradient(circle at 38% 34%, #fff 0 10%, var(--w-pearl) 46%, rgba(236, 230, 220, 0.3));
    box-shadow: 0 0 10px rgba(236, 230, 220, 0.45);
}

.site-footer ul {
    padding: 0;
    list-style: none;
}

/* A link: its words stay on the column's edge, its round light reaches out on both sides. */
.site-footer-links :is(a, button) {
    position: relative;
    display: inline-flex;
    align-items: center;
    min-width: 44px;
    min-height: 44px;
    margin: 0 -14px;
    padding: 0 14px;
    border-radius: 999px;
    color: var(--ink-fg-2);
    text-decoration: none;
    transition: color 0.25s ease;
    isolation: isolate;
}

.site-footer-links :is(a, button)::before {
    content: "";
    position: absolute;
    inset: 5px 0;
    z-index: -1;
    border-radius: 999px;
    background: radial-gradient(closest-side, rgba(214, 224, 240, 0.18), rgba(214, 224, 240, 0.06) 72%, transparent);
    opacity: 0;
    transition: opacity 0.35s ease;
}

.site-footer-links :is(a, button):where(:hover, :focus-visible) {
    color: var(--ink-fg);
}

.site-footer-links :is(a, button):where(:hover, :focus-visible)::before {
    opacity: 1;
}

.site-footer-social {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

/* A profile: a small round drop with a rim of light. */
.site-footer-social a {
    position: relative;
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    border: 1px solid rgba(214, 224, 240, 0.14);
    border-radius: 50%;
    background: radial-gradient(circle at 50% 120%, rgba(214, 224, 240, 0.08), rgba(9, 12, 17, 0.6) 70%);
    color: var(--ink-fg-2);
    transition: color 0.25s ease, border-color 0.25s ease, transform 0.3s var(--ease-out);
}

.site-footer-social a::after {
    content: "";
    position: absolute;
    inset: -1px;
    border-radius: 50%;
    box-shadow: 0 0 18px rgba(214, 224, 240, 0.16);
    opacity: 0;
    transition: opacity 0.35s ease;
    pointer-events: none;
}

.site-footer-social a:focus-visible::after {
    opacity: 1;
}

.site-footer-social svg {
    width: 18px;
    height: 18px;
}

@media (hover: hover) {
    .site-footer-social a:hover {
        border-color: rgba(214, 224, 240, 0.32);
        color: var(--ink-fg);
        transform: translateY(-2px);
    }

    .site-footer-social a:hover::after {
        opacity: 1;
    }
}

.site-footer-bottom {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: 12px 24px;
    max-width: var(--page-max);
    margin: clamp(40px, 6vw, 72px) auto 0;
    padding-top: 22px;
    border-top: 1px solid transparent;
    border-image: linear-gradient(90deg, transparent, rgba(214, 224, 240, 0.12) 12%, rgba(214, 224, 240, 0.12) 88%, transparent) 1;
    color: var(--ink-fg-3);
    font-family: var(--font-data);
    font-size: 0.76rem;
    letter-spacing: 0.04em;
}

@media (max-width: 60em) {
    .site-footer-inner {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    /* The profiles take the full row, so the four icons stay on one line. */
    .site-footer-about,
    .site-footer-profiles {
        grid-column: 1 / -1;
    }
}

@media (max-width: 26em) {
    .site-footer-inner {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* --- Preferences ------------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        scroll-behavior: auto !important;
    }

    .btn,
    .btn svg,
    .link-arrow::after,
    .site-footer-links :is(a, button),
    .site-footer-links :is(a, button)::before,
    .site-footer-social a,
    .site-footer-social a::after {
        transition: none;
    }
}

@media (forced-colors: active) {
    .btn {
        border: 1px solid ButtonText;
    }
}

@media print {
    body {
        background: #fff;
        color: #000;
    }

    .site-footer {
        display: none;
    }

    html.reveal [data-reveal-group] [data-reveal],
    html.reveal [data-reveal-group][data-reveal],
    html.reveal [data-reveal="words"] .w {
        opacity: 1;
        translate: none;
        rotate: none;
        scale: none;
    }

    [data-reveal="words"]::before {
        display: none;
    }
}
