/* #region Address search band */
/* The search sits on a strip of its own between the hero marquee and the manifesto, never as a bare
   .container under the hero: .container carries no gutter, so under 1400 px the field then hugs the
   left edge of the window with nothing around it. As a band it reads as part of the
   page's architecture: the wash names it, and the strip carries the field to the right of the
   line that explains it. The marquee above already draws a bottom border, so this one has none of
   its own on top. */
.space-search-band {
    position: relative;
    z-index: 5;
    /* The question this page answers fastest, so it gets air of its own instead of looking like a
       technical strip glued under the marquee. The hero leads here by button, and an anchor's target
       needs room above it or it lands under the fixed navigation bar. */
    padding: clamp(3.4rem, 6vw, 5.75rem) 0;
    scroll-margin-top: clamp(4.5rem, 7vw, 6.5rem);
    background: linear-gradient(90deg, var(--tint), rgba(245, 245, 245, .01) 55%, transparent);
    border-bottom: 1px solid var(--hairline);
}

.space-search-band-inner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: clamp(1.4rem, 3vw, 3rem);
    width: min(90vw, var(--section-content-max));
    max-width: none;
    margin-inline: auto;
}

.space-search-band-copy {
    flex: 1 1 22rem;
    min-width: 0;
}

    /* The eyebrow's own bottom margin is written for a section heading, not for a two-line strip. */
    .space-search-band-copy .h-tag {
        margin-bottom: .9rem;
    }

/* Raised together with the band's own spacing: in a taller strip a sentence at the smaller size is lost
   and the whole space reads as empty rather than as an invitation. */
.space-search-band-title {
    max-width: 34ch;
    margin: 0;
    color: var(--white-soft);
    font-family: var(--font-display);
    font-size: clamp(1.2rem, 2vw, 1.7rem);
    font-weight: 300;
    line-height: 1.4;
}

.space-search-band .domain-search {
    position: relative;
    flex: 1 1 20rem;
    max-width: 32rem;
}

/* The answers hang over the page instead of growing the strip: a band that changes height as you
   type pushes the whole page down under your cursor. */
.space-search-band .domain-search-results {
    position: absolute;
    inset: 100% 0 auto;
    margin-top: .5rem;
    box-shadow: 0 26px 60px rgba(5,5,5,.55);
}
/* #endregion */

/* #region Flip Card */
.flip-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8vw;
    align-items: center;
    max-width: none;
    margin: 0 auto;
}

/* No ring behind the card. A 32rem gold hairline circle hung off the right edge here, and next to a
   card that turns over by itself it read as a second object rather than as ground — the section has
   one subject and it is the card. The gradients stay: they are light on a surface, which is what
   this section's right half is for. Nothing is positioned or clipped here any more, so the
   containing block and the overflow guard the ring needed went with it. */
.flip-section {
    background: radial-gradient(circle at 77% 50%, var(--tint), transparent 25%), linear-gradient(145deg, var(--tint), transparent 42%), var(--surface-editorial);
}

.flip-content h2 {
    font-family: var(--font-display);
    font-size: var(--section-title-size);
    color: var(--white);
    font-weight: 300;
    letter-spacing: -.035em;
    margin-bottom: 3vh;
    line-height: var(--section-title-line-height);
}

    .flip-content h2 i {
        color: var(--gold);
        font-weight: 300;
    }

.flip-content p {
    font-size: 1.05rem;
    font-weight: 200;
    color: var(--text-muted);
    line-height: 1.8;
    margin-bottom: 4vh;
}

.card-stage {
    perspective: 1000px;
    width: 100%;
    max-width: 500px;
    margin: 0 auto;
}

/* Left-aligned wherever its section centres text, so the address stays under the name above it. */
.identity-card {
    position: relative;
    width: 100%;
    text-align: left;
    aspect-ratio: 1.6;
    transition: transform 1.5s var(--ease-house);
    transform-style: preserve-3d;
}

    .identity-card.flipped {
        transform: rotateY(180deg);
    }

.card-face {
    position: absolute;
    width: 100%;
    height: 100%;
    backface-visibility: hidden;
    padding: clamp(2rem, 4vw, 3rem);
    display: flex;
    flex-direction: column;
    justify-content: center;
    box-shadow: 0 30px 60px rgba(5,5,5,0.8);
}

.face-amateur {
    background: var(--surface-card);
    border: 1px solid var(--hairline);
}

/* The professional face is the same black stock as the house, set apart by its finish rather than by a
   brighter surface: a crisp frame, a gilt line set in from the edge like a printed card's border, and type
   at full strength where the amateur face is greyed. */
.face-pro {
    background: var(--surface-raised);
    border: 1px solid var(--hairline-strong);
    transform: rotateY(180deg);
}

    .face-pro::after {
        position: absolute;
        inset: clamp(.6rem, 1.2vw, .9rem);
        border: 1px solid rgba(var(--gold-rgb), .45);
        content: '';
        pointer-events: none;
    }

.c-header {
    display: flex;
    align-items: center;
    gap: 20px;
    margin-bottom: 30px;
}

.c-avatar {
    width: 60px;
    height: 60px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: var(--font-display);
    font-size: 1.5rem;
}

.face-amateur .c-avatar {
    background: var(--surface-raised);
    color: var(--text-muted);
}

.face-pro .c-avatar {
    background: var(--black);
    border: 1px solid var(--hairline-strong);
    color: var(--gold);
}

.c-name {
    font-family: var(--font-display);
    font-size: 1.8rem;
    line-height: 1.1;
}

.c-role {
    font-family: var(--font-mono);
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 3px;
    margin-top: 5px;
}

.face-amateur .c-name {
    color: var(--white-soft);
}

.face-amateur .c-role {
    color: var(--text-muted);
}

.face-pro .c-name {
    color: var(--white);
}

.face-pro .c-role {
    color: rgba(245, 245, 245, .5);
}

.c-email {
    font-family: var(--font);
    font-size: 1.1rem;
    line-height: 1.6;
}

.face-amateur .c-email {
    color: var(--white-soft);
}

.face-pro .c-email {
    color: var(--white);
    font-weight: 400;
}

.status-timeline {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-top: 4vh;
    gap: 20px;
}

.st-label {
    font-family: var(--font-mono);
    font-size: 0.65rem;
    text-transform: uppercase;
    letter-spacing: 3px;
    color: var(--white);
    opacity: 0.5;
    transition: opacity 0.5s ease, color 0.5s ease;
}

/* The two labels fill a 320px row between them, and a basis-0 bar with nothing left was simply gone. */
.st-bar-bg {
    flex: 1;
    min-width: 3rem;
    height: 1px;
    background: var(--white-subtle);
    position: relative;
}

.st-bar-fill {
    position: absolute;
    top: 0;
    left: 0;
    height: 100%;
    width: 0%;
    background: var(--gold);
    transition: width 1.5s var(--ease-house);
}

.st-label.active-white {
    color: var(--white);
    opacity: 1;
}

.st-label.active-gold {
    color: var(--gold);
    opacity: 1;
}

.st-bar-fill.full {
    width: 100%;
}
/* #endregion */

/* #region Strategy */
.strat-header {
    text-align: left;
    margin-bottom: 10vh;
}

    .strat-header h2 i {
        color: var(--gold);
        font-weight: 300;
    }

/* The numbered cards. They are not the Space page's any more — that page's six arguments became the
   stage below — but they are still what the profession family pages draw their „jak to działa" in,
   three steps to a row, so the rules stay where those pages already load them from. The reveal is
   site.js's own .reveal-elem/.visible pair, which those cards carry; nothing here observes them. */
.strat-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: clamp(1rem, 1.8vw, 1.8rem);
    max-width: none;
    margin: 0 auto;
}

.strat-card {
    position: relative;
    /* The card crops its own watermark — the figure is pushed past the bottom-right corner and the
       edge is what cuts it. Without this it would hang outside the border. */
    overflow: hidden;
    min-height: 21rem;
    padding: clamp(2rem, 3vw, 3rem);
    border: 1px solid var(--hairline);
    background: linear-gradient(145deg, var(--tint), transparent 52%), var(--surface-card);
    opacity: 0;
    transform: translateY(30px);
    transition: all 1s var(--ease-house);
}

    /* A white rule at rest; gold arrives on it under the hand. */
    .strat-card::after {
        position: absolute;
        right: 0;
        bottom: 0;
        width: 42%;
        height: 1px;
        background: var(--hairline-strong);
        content: "";
        transition: background-color var(--motion) var(--ease-house);
    }

    .strat-card:hover::after {
        background: var(--gold-hover);
    }

    .strat-card.visible {
        opacity: 1;
        transform: translateY(0);
    }

    .strat-card:hover {
        border-color: var(--gold-accent);
    }

    .strat-card.delay-1 {
        transition-delay: 0.2s;
    }

    .strat-card.delay-2 {
        transition-delay: 0.4s;
    }

/* THE STEP IS THE THING HERE, NOT ITS NUMBER. Set the other way round — the figure above each step in gold
   display italic at a heading's size, the step itself („Wybierasz adres") as a mono label at .8rem — the
   number is the loudest thing in the card and the sentence it numbers the quietest. So the two trade places.
   The figure becomes the house's watermark: far larger than the card, pushed past its bottom-right
   corner so the edge crops it, at a fraction of the white that warms to gold under the hand. The
   declarations are the segment scenario tile's, value for value, because there is one such treatment
   on this site. */
.strat-num {
    position: absolute;
    right: -.04em;
    bottom: -.1em;
    z-index: 0;
    color: rgba(245, 245, 245, .045);
    font-family: var(--font-display);
    font-size: clamp(6rem, 9vw, 9.5rem);
    font-weight: 400;
    letter-spacing: -.04em;
    line-height: .8;
    pointer-events: none;
    user-select: none;
    transition: color var(--motion) var(--ease-house);
}

.strat-card:hover .strat-num,
.strat-card:focus-within .strat-num {
    color: rgba(var(--gold-rgb), .085);
}

/* Everything the reader reads stands above the watermark. */
.strat-card > :not(.strat-num) {
    position: relative;
    z-index: 1;
}

/* The step, promoted to what it is: a heading. The display face at the size the house gives a card
   title, in place of a mono label in capitals that read as a caption for the paragraph under it. */
.strat-title {
    margin-bottom: 1.1rem;
    color: var(--white);
    font-family: var(--font-display);
    font-size: clamp(1.3rem, 1.9vw, 1.65rem);
    font-weight: 300;
    letter-spacing: -.01em;
    line-height: 1.2;
    text-transform: none;
}

.strat-desc {
    font-size: 1rem;
    font-weight: 200;
    color: var(--text-muted);
    line-height: 1.8;
}

/* ONE OBJECT, SIX WORLDS.

   There is exactly one address on this stage and it belongs to no act. The plate is a single node
   standing in the middle of the arena, a sibling of the six sets of scenery and stacked over all of
   them, and nothing an act does touches it — no fade, no transform, no second copy. An act only
   builds its apparatus in the two halves around the plate and strikes it again. So the reader
   watches one object hold perfectly still while the world around it reorganises itself six times,
   which is the argument the section came to make, drawn instead of described.

   What moves instead is the name. A timer re-engraves the plate every few seconds — the characters
   are cut out one by one, the next diamond of the portfolio is cut in, the light passes across the
   plate as it happens — and every act's own props turn with it, so each
   frame of the section is one coherent example. Six hundred addresses cannot be argued for with one
   of them.

   TWO READINGS, and the plain one ships in the markup.
   PLAIN — no scripting, under 1001px, or a reader who asked for less movement: the plate stands
   with the first name and the ten acts read as a list under it. The apparatus is scenery and is
   hidden there; every sentence and the address are on the screen, so
   nothing this section has to say is behind the mechanism.
   STAGED — space.js adds .is-theatre: the frame is pinned while it is scrolled past, the acts change
   with the scroll, and the plate keeps its own clock.

   Superseded stagings, so none is tried a third time: all six arguments tiled across a grid (twice —
   it turns every scene into a thumbnail), and six panels that each carried their own copy of the
   address and cross-faded, which is six slides whatever the easing. */
.addr-theatre {
    /* Nothing is measured in script any more: every length inside the device is read off the
       device's own width through one container, which is what the phone made possible — the earlier
       geometry had scenery standing beside the address and its width had to be handed down from
       JavaScript to line the two up. */
    display: flex;
    flex-direction: column;
    gap: clamp(1.8rem, 3.4vh, 3rem);
}

.addr-frame {
    display: grid;
    gap: clamp(1.6rem, 3vh, 2.6rem);
    grid-template-areas: "arena" "argument" "meter";
    justify-items: center;
}

/* #region The arena, the phone and the one row in it */
.addr-arena {
    position: relative;
    display: grid;
    width: 100%;
    grid-area: arena;
    place-items: center;
}

/* The whole object is the link — the phone and its label together — for the same reason the oak
   frame beside the Art price is: what the reader is deciding is whether this address is theirs, so
   the object is the control. It is also the container every length inside the device is measured
   against, so the phone, its bezel, its status bar and each act's app all scale together and each
   number is written once. An element cannot read its own container, which is why the container is
   this wrapper and not the phone. */
.addr-device {
    display: flex;
    /* The height cap is for a phone held sideways, where a phone this wide was 1.6 screens tall. */
    width: min(19rem, 78vw, 42svh);
    flex-direction: column;
    align-items: center;
    gap: clamp(.8rem, 1.6vh, 1.3rem);
    container-type: inline-size;
    text-decoration: none;
}

    .addr-device[href]:focus-visible {
        outline: 1px solid var(--gold);
        outline-offset: 12px;
    }

/* THE PHONE, and it is the whole reason this section works at all. Drawn as geometry — chips, rules, a fan
   of lines, a „measure", a brace — the six arguments ask a reader who is not technical to decode a diagram
   before they can agree with it. Nothing on a phone has to be decoded: a tab strip, a sponsored post, a
   chat, a contact list, a saved card and a search field are surfaces everybody uses daily, so the situation
   lands before the copy does — and the situation is the reader's own client, holding their own phone.

   Narrow on purpose. A phone is the one object whose proportions identify it from across a room, so
   the width comes from the height the arena can give it rather than the other way round. */
.addr-phone {
    position: relative;
    display: flex;
    width: 100%;
    flex-direction: column;
    aspect-ratio: 9 / 18.5;
    padding: 2.4cqw;
    /* Almost black, and deliberately not gold. The device is the FRAME, not the subject: the only
       thing on this stage that may carry the house's gold is the address inside it, and a gilded
       bezel around it competed with the one line the reader is supposed to read. So the body keeps
       a neutral hairline and a neutral top-light — enough for the object to have form and an edge,
       nothing that pulls the eye to the casing. */
    border: 1px solid rgba(245, 245, 245, .09);
    border-radius: 11cqw;
    background: linear-gradient(160deg, rgba(245, 245, 245, .055), transparent 52%), #050505;
    box-shadow: 0 2rem 4.5rem rgba(5, 5, 5, .62);
}

/* No reflection drifting across the glass: an ambient shimmer is a light with no cause, and a house
   whose whole idiom is a hairline and a still object does not sparkle. The only light on this stage is
   the one that crosses the address row as the name in it is re-cut — that one has a reason, and it
   stops when the reason does. */

/* The two things that say „phone" before anything on the screen does. Drawn rather than written —
   a running clock would be a second thing changing on a page that already has enough of them. */
.addr-island {
    display: block;
    width: 26cqw;
    height: 3.2cqw;
    margin: 0 auto .8cqw;
    border-radius: 3cqw;
    background: var(--black);
}

.addr-status {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 3.4cqw 1.6cqw;
}

    .addr-status em {
        color: rgba(245, 245, 245, .45);
        font-family: var(--font-mono);
        font-size: 3.3cqw;
        font-style: normal;
    }

    .addr-status span {
        display: flex;
        align-items: flex-end;
        gap: .7cqw;
    }

    .addr-status i {
        width: 1cqw;
        background: rgba(245, 245, 245, .3);
    }

    .addr-status i:nth-child(1) {
        height: 1.4cqw;
    }

    .addr-status i:nth-child(2) {
        height: 2.1cqw;
    }

    .addr-status i:nth-child(3) {
        height: 2.8cqw;
    }

/* The gesture bar, static because it is static on a real phone. It is here for the same reason the
   island and the status bar are: details a reader recognises without looking. */
.addr-home {
    position: absolute;
    bottom: 2cqw;
    left: 50%;
    z-index: 3;
    display: block;
    width: 32cqw;
    height: 1cqw;
    border-radius: 1cqw;
    background: rgba(245, 245, 245, .22);
    pointer-events: none;
    transform: translateX(-50%);
}

.addr-screen {
    /* The height of the address row, and therefore how far each half of an act has to stand clear of
       it. Written once here because both halves and the row itself are measured from it. */
    --addr-row-h: 14.5cqw;
    position: relative;
    display: grid;
    flex: 1;
    border-radius: 8cqw;
    background: #050505;
    overflow: hidden;
    place-items: center;
}

/* THE ADDRESS ROW. One node, outside every act and stacked over all six: never faded, never moved,
   never duplicated. An act builds its app around it and strikes it again, and the name does not
   shift by a pixel. Six acts each fading in their own copy of the address were six slides, whatever
   the easing — which is the whole reason this row is not part of any of them. */
/* THE NAME IS THE ONLY THING IN THE ROW, and it is centred on the row itself. This is what makes
   „the address does not move" literally true rather than nearly true.

   Centring the row's contents as a GROUP — one flex line, justified centre — makes the name's own position
   depend on everything beside it AND on its own width, so every step change moves the address: a name one
   character longer slides the whole group left, and in the mailbox step „kontakt@" visibly jumps as each new
   domain arrives. The cause is the layout, not the prefix's reveal or the engraving.

   Three tracks stood here next — an empty one, the name, an empty one — so that an affordance in
   the left track could hug the name without pushing it off centre. Nothing stands beside the name
   any more: the mailbox step engraves its local part into the name itself, and act one's padlock is
   gone. One centred cell makes the name's centre the row's centre by construction, which is the
   same guarantee with nothing left to keep level. */
.addr-row {
    position: relative;
    z-index: 2;
    display: grid;
    width: calc(100% - 9cqw);
    height: var(--addr-row-h);
    place-items: center;
    border: 1px solid var(--hairline-mid);
    border-radius: 3cqw;
    background: linear-gradient(150deg, var(--tint-raised), transparent 62%), #050505;
    box-shadow: 0 1.4cqw 3cqw rgba(5, 5, 5, .6);
    overflow: hidden;
}

    /* The light that passes over the row as it is re-engraved. It hangs on the name change and not
       on an act, because the row belongs to no act — the light is what says the same address is
       still there under a new name. */
    .addr-row::after {
        content: "";
        position: absolute;
        top: 0;
        bottom: 0;
        left: 0;
        width: 40%;
        background: linear-gradient(100deg, transparent, rgba(245, 245, 245, .08), transparent);
        opacity: 0;
        pointer-events: none;
    }

/* The width is the NAME's width, not a box fixed at the longest name in the cast. A fixed box is
   right only while a timer changes the name in the middle of a step; here one step is one address, so
   the name changes at a step boundary where the whole app around it changes too and there is no drift
   to protect against. What the fixed box costs is visible: the text sits centred inside a box far wider than
   itself, so act one's padlock — which hugs the box — stands a finger's width from the address it belongs
   to.

   The swap is invisible even so: by the time the incoming name is written, every outgoing character
   has already been cut to nothing, so nothing is standing at the old width when the width changes. */
.addr-name {
    display: block;
    width: max-content;
    max-width: 100%;
    color: var(--gold);
    font-family: var(--font-mono);
    font-size: 5.8cqw;
    letter-spacing: .03em;
    text-align: center;
    /* Act seven puts a mailbox in front of the name and the name gives up a notch of size to make
       room for it. Transitioned, because the step change would otherwise resize the address in one
       frame, in the one element that must never appear to be redrawn. */
    transition: font-size .55s var(--ease-house);
    white-space: nowrap;
}

    /* One character per span, put there by space.js, so the name can be cut out and cut back in a
       character at a time rather than swapped. */
    .addr-name i {
        display: inline-block;
        font-style: normal;
        white-space: pre;
    }

/* ONE ROW, SIX ROLES — and not one of them is an object standing beside the address any more.
   Nothing is added to the row: what changes is what the row IS.

   Three affordances belong nowhere here, each for the same reason. Act one's padlock is browser chrome
   quoting a browser, and on a stage where gold is what we sell it reads as a mark of ours; the search step's
   „1" reads as a rendering fault rather than as a rank, and being first is already said by the address
   standing above the other results; the mailbox step's „contact@" is a second box printing the address in
   two pieces, so it is engraved into the name instead. What is left is the one mark that is not an object:
   act three's underline, which is a property of the name rather than a thing next to it. */
/* Act three: a model is citing the address, and what a citation looks like on a phone is a link. */
.addr-arena[data-addr-act-index="3"] .addr-name {
    text-decoration: underline;
    text-decoration-color: rgba(var(--gold-rgb), .5);
    text-decoration-thickness: 1px;
    text-underline-offset: .3em;
}

/* How far through this step the reader is, on the device's own bottom edge — the same bar the Soul
   page's case theatre carries, driven the same way and for the same reason: the scroll is what
   deals the steps, so the thing that shows the scroll belongs on the thing being dealt. A pinned
   section with no visible clock reads as stuck.

   The fill has no transition of its own. Under the scroll it is written every frame and any easing
   would lag the reader's own hand; where nothing is pinned the script hands it a duration. */
.addr-progress {
    display: block;
    width: 100%;
    height: 2px;
    background: var(--hairline);
    overflow: hidden;
}

    .addr-progress i {
        display: block;
        width: 100%;
        height: 100%;
        background: var(--gold);
        transform: scaleX(0);
        transform-origin: left center;
        transition: transform 0s linear;
    }
/* #endregion */

/* #region The six apps */
/* Every act is two halves that meet exactly at the screen's centre, which is where the address row
   is, and each half stands its content clear of the row by half the row's height. So an act never
   has to know how tall the row is — only that it is in the middle. */
/* An app arriving comes UP into the screen and the one it replaces leaves upward, which is what a phone does
   when you move forward through it. A cross-fade alone is what a slide deck does, and this section's whole
   argument is that these are six places rather than six slides. The address row is not part of any of this:
   it sits above the sets and does not
   move, so the world slides behind a name that stays put. */
.addr-set {
    position: absolute;
    z-index: 1;
    display: grid;
    inset: 0;
    grid-template-rows: 1fr 1fr;
    opacity: 0;
    pointer-events: none;
    transform: translate3d(0, 4%, 0);
    transition: opacity .45s ease, transform .65s var(--ease-house);
    visibility: hidden;
}

/* The apps are what the argument is drawn with, not what it says: the plain reading does without
   them and loses nothing but the picture. The bar goes with them — there the reader is not scrolling
   through anything, so a bar counting that scroll would be a stray rule under the phone. */
.addr-theatre:not(.is-theatre) .addr-set,
.addr-theatre:not(.is-theatre) .addr-progress {
    display: none;
}

.addr-over,
.addr-under {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2.4cqw;
    padding: 0 4.5cqw;
}

.addr-over {
    justify-content: flex-end;
    padding-bottom: calc(var(--addr-row-h) / 2 + 3.2cqw);
}

.addr-under {
    justify-content: flex-start;
    padding-top: calc(var(--addr-row-h) / 2 + 3.2cqw);
}

    /* The message stands further off the address than any other act's lower half. In a mailbox the
       row IS the sender's line, and a subject set tight under it read as part of that line rather
       than as the message it opens. */
    .addr-set.is-inbox .addr-under {
        padding-top: calc(var(--addr-row-h) / 2 + 7cqw);
    }

    /* And the code stands further off it than any other act's upper half, for the mirror reason:
       the plate is the largest, lightest object any step puts on this screen, and set close it
       crowded the one line the step is about. */
    .addr-set.is-scan .addr-over {
        padding-bottom: calc(var(--addr-row-h) / 2 + 7cqw);
    }

/* ACT 1 — the browser. The tabs above say which app this is; below, the three places the venue
   already sells from light up one after another as the traffic reaches them. The argument is that
   nothing has to be rebuilt, and what the reader sees is a page opening. */
.addr-tabs {
    display: flex;
    gap: 1.4cqw;
}

    .addr-tabs i {
        width: 9cqw;
        height: 5.6cqw;
        border: 1px solid var(--hairline);
        border-radius: 1.4cqw;
        background: #050505;
    }

    /* The open tab is the current one, so it keeps the gold edge. */
    .addr-tabs i.is-front {
        border-color: rgba(var(--gold-rgb), .38);
        background: var(--black-mid);
    }

/* The line carries a dot that runs down it: traffic being sent somewhere, rather than a line simply drawn. A
   drawn line says a diagram was built; a dot arriving says something moved. */
.addr-drop {
    --addr-fan-drop: 7cqw;
    position: relative;
    width: 1px;
    height: 7cqw;
}

    .addr-drop i {
        position: absolute;
        inset: 0;
        background: var(--hairline);
        transform: scaleY(0);
        transform-origin: top;
    }

    .addr-drop b {
        position: absolute;
        top: 0;
        left: -1.4cqw;
        width: 2.8cqw;
        height: 2.8cqw;
        border-radius: 50%;
        background: var(--gold);
        opacity: 0;
    }

.addr-tiles {
    display: grid;
    width: 100%;
    gap: 2cqw;
}

.addr-tile {
    display: flex;
    align-items: center;
    gap: 2.4cqw;
    padding: 2.6cqw 3cqw;
    border: 1px solid var(--hairline);
    border-radius: 2.4cqw;
    background: #050505;
    opacity: 0;
}

    .addr-tile i {
        width: 5cqw;
        height: 5cqw;
        flex: none;
        border-radius: 1.4cqw;
        background: linear-gradient(150deg, var(--hairline-strong), var(--tint));
    }

    .addr-tile em {
        color: rgba(245, 245, 245, .66);
        font-size: 3.9cqw;
        font-style: normal;
    }

/* ACT 2 — the sponsored post. Everybody has seen a link cut off with „…" at the foot of an advert,
   which is exactly why this is the surface: the long address is put in that line first and does not
   fit, and then the same line holds the whole name. The comparison happens inside one advert rather
   than between two abstract boxes, and the text is masked at its right edge rather than clipped
   square, because an address that is cut off has to look like it continues. */
.addr-adtag {
    align-self: flex-start;
    color: rgba(245, 245, 245, .38);
    font-family: var(--font-mono);
    font-size: 3cqw;
    letter-spacing: .16em;
    text-transform: uppercase;
}

/* The advert's headline, which is the service — the same fact the address states, said in words
   directly under it. In a search advert this line is the one thing a reader actually reads, so it
   carries the weight: the display address above it and two lines of description under it are what
   frame it. */
.addr-adhead {
    align-self: flex-start;
    color: var(--white);
    font-family: var(--font-display);
    font-size: 4.6cqw;
    font-weight: 300;
    line-height: 1.25;
    text-wrap: balance;
}

.addr-oldline {
    display: block;
    width: 100%;
    padding: 2cqw 2.6cqw;
    border: 1px solid var(--hairline);
    border-radius: 2cqw;
    background: #050505;
    opacity: .5;
    overflow: hidden;
}

    .addr-oldline em {
        position: relative;
        display: block;
        color: var(--text-muted);
        font-family: var(--font-mono);
        font-size: 3.7cqw;
        font-style: normal;
        mask-image: linear-gradient(90deg, #050505 78%, transparent);
        white-space: nowrap;
    }

        /* The long address is STRUCK OUT, not slid aside. Drifting it left reads as a rendering fault
           rather than as a judgement — a reader who sees text in the wrong place assumes the page is
           at fault, not the address. A line drawn through it says exactly one thing, and it is the thing
           meant: this is the name being given up. It travels rather than appearing, because a strike that is
           simply there reads as a fact rather than as a decision. */
        .addr-oldline em::after {
            content: "";
            position: absolute;
            top: 50%;
            right: 0;
            left: 0;
            height: 1px;
            background: var(--text-muted);
            transform: scaleX(0);
            transform-origin: left center;
        }

/* ACTS 7–9, the three places an address is seen that the first six do not reach: a message that
   arrives instead of landing in spam, a name said out loud, and the last thing a buyer reads before
   they pay. They are built from the vocabulary the earlier steps already established — a bubble, a
   row of bars, a button — because a step that invents its own pieces is a step the reader has to
   learn. */

/* ACT 7 — the inbox. The sender that never arrived, greyed and labelled, over the one that did. */
.addr-junk {
    display: flex;
    width: 100%;
    align-items: center;
    gap: 2.4cqw;
    padding: 2.6cqw 0;
    border-bottom: 1px solid rgba(245, 245, 245, .05);
    opacity: .45;
}

    .addr-junk em {
        flex: none;
        padding: .8cqw 2cqw;
        border: 1px solid rgba(245, 245, 245, .14);
        border-radius: 1.2cqw;
        color: rgba(245, 245, 245, .5);
        font-family: var(--font-mono);
        font-size: 2.6cqw;
        font-style: normal;
        letter-spacing: .14em;
        text-transform: uppercase;
    }

    /* The bar beside the SPAM tag, and it DRAINS: full at the moment the row appears, then down to
       a tenth of itself. Standing still it is scenery — a grey bar in the shape of a subject line — and
       this step's whole claim is about what happens to mail sent from a mailbox that
       authenticates nothing. Scaled rather than resized, so nothing in the row reflows, and it
       stops at a tenth instead of at nothing: some of it does arrive, and a bar that emptied would
       claim otherwise. */
    .addr-junk i {
        flex: 1;
        height: 2.2cqw;
        border-radius: 1cqw;
        background: rgba(245, 245, 245, .08);
        transform-origin: left center;
    }

.addr-set.is-playing .addr-junk i {
    animation: addr-drain 1.3s cubic-bezier(.4, 0, .2, 1) .55s both;
}

/* The message itself: a subject, two sentences and a signature. What this step argues is that the
   message was read, and that only lands if there is something to read — two grey bars said „a
   message" and left the rest to the reader's imagination. */
.addr-subject {
    align-self: flex-start;
    color: var(--white);
    font-size: 3.9cqw;
    font-weight: 400;
}

.addr-message {
    align-self: flex-start;
    color: rgba(245, 245, 245, .6);
    font-size: 3.4cqw;
    font-weight: 300;
    line-height: 1.55;
}

.addr-sign {
    align-self: flex-start;
    color: rgba(245, 245, 245, .42);
    font-family: var(--font-display);
    font-size: 3.4cqw;
    font-style: italic;
}

/* ACT 8 — the telephone. The bar at the top is a call in progress; under it the long address is
   dictated and does not finish. */
.addr-callbar {
    display: flex;
    width: 100%;
    align-items: center;
    gap: 2.4cqw;
    padding: 2.4cqw 3cqw;
    border-radius: 6cqw;
    background: rgba(245, 245, 245, .05);
}

    .addr-callbar i {
        width: 2.6cqw;
        height: 2.6cqw;
        flex: none;
        border-radius: 50%;
        background: var(--gold);
    }

    .addr-callbar em {
        color: rgba(245, 245, 245, .72);
        font-size: 3.7cqw;
        font-style: normal;
        font-weight: 300;
    }

/* What somebody actually says when the address is long: a lead-in and then the name, letter after
   letter, cut off by the width of the screen — which is the joke and the argument at once. */
.addr-spell {
    display: flex;
    width: 100%;
    align-self: flex-start;
    flex-direction: column;
    gap: 1cqw;
    opacity: 0;
}

    .addr-spell em,
    .addr-spell b {
        color: var(--text-muted);
        font-family: var(--font-mono);
        font-size: 3.2cqw;
        font-style: normal;
        font-weight: 300;
        letter-spacing: .16em;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

        /* What is dictated is STRUCK OUT — the same line, and the same reason, as the address given
           up in the advert step: the reader has to see that this is the thing not being spelled down
           a telephone, and text merely set in grey is text still in use. BOTH lines carry it:
           „w-w-w-kropka…" is half of what somebody says out loud, so striking only the name leaves
           the spelling standing as if it were still needed. The row underneath is what is said
           instead, in one breath. */
        .addr-spell em,
        .addr-spell b {
            position: relative;
            /* Hugging the text, not the column: a stretched box would carry the line on past the
               last letter — the block is a flex column, so a child stretches by default. */
            align-self: flex-start;
            max-width: 100%;
        }

            .addr-spell em::after,
            .addr-spell b::after {
                content: "";
                position: absolute;
                top: 50%;
                right: 0;
                left: 0;
                height: 1px;
                background: var(--text-muted);
                transform: scaleX(0);
                transform-origin: left center;
            }

.addr-close {
    color: var(--white);
    font-family: var(--font-mono);
    font-size: 3cqw;
    letter-spacing: .18em;
    opacity: 0;
    text-transform: uppercase;
}

/* ACT 9 — the payment screen. The amount is drawn and never written: a figure here would be a price
   for something this section is not selling. */
.addr-paylabel {
    align-self: flex-start;
    color: rgba(245, 245, 245, .38);
    font-family: var(--font-mono);
    font-size: 2.9cqw;
    letter-spacing: .16em;
    text-transform: uppercase;
}

.addr-amount {
    display: flex
;
    width: 100%;
    align-self: flex-start;
    flex-direction: column;
    gap: 2cqw;
}

    .addr-amount i {
        height: 1.6cqw;
        border-radius: 1cqw;
        background: rgba(245, 245, 245, .1);
    }

    .addr-amount i:first-child {
        width: 54%;
        height: 3.4cqw;
        background: rgba(245, 245, 245, .16);
    }

    .addr-amount i:last-child {
        width: 32%;
    }

.addr-paycta {
    display: block;
    width: 100%;
    padding: 3cqw;
    border-radius: 2cqw;
    background: var(--tint-raised);
    color: var(--white);
    font-size: 3.7cqw;
    letter-spacing: .04em;
    text-align: center;
}

/* THE CODE, and it is a real one — the page's own address, generated server-side. The plate carries
   no colour of its own: the picture's ground IS the paper, chosen in QrCodeHelpers, and the code's
   quiet zone is what draws the margin, so the tone is defined once. This box only clips the corners —
   nothing here draws a code out of positioned squares.

   No image-rendering override on purpose. The picture is larger than the box, so the browser
   downscales it, and its own smoothing is what keeps the modules clean — nearest-neighbour on a
   fractional downscale drops whole module rows, which is how a code stops scanning. */
.addr-code {
    display: block;
    width: 34cqw;
    height: 34cqw;
    border-radius: 1.4cqw;
    overflow: hidden;
}

    .addr-code img {
        display: block;
        width: 100%;
        height: 100%;
    }

.addr-open {
    display: block;
    width: 100%;
    padding: 3cqw;
    border-radius: 2cqw;
    background: var(--tint-raised);
    color: var(--white);
    font-size: 3.7cqw;
    letter-spacing: .04em;
    text-align: center;
}

/* The mailbox, for the one step where the address is a sender. */
/* „kontakt@", and it OPENS rather than appears. Switched with `display` — none until act seven, inline from
   it — the mailbox pops into the line and shoves the address sideways in a single frame, because display is
   the one property no transition can touch. On the one stage whose entire claim is that the address does not
   move, that reads as a fault.

   So it is always in the row and collapsed to nothing: zero max-width with the overflow hidden, and
   a negative margin that swallows the row's own 2cqw gap while there is nothing to separate — a
   zero-width flex item still takes its gap, which would leave the name a hair off centre in the
   other nine acts. Growing max-width and giving the gap back are both transitioned, so the name
   glides aside as the mailbox is written in front of it. The cap is generous, so the box stops at
   the text's own width part-way through the transition — the same bargain the typed query makes,
   and for the same reason: a translation must never be clipped. */
/* The local part of the mailbox step's address. It is not an element of its own any more — space.js
   engraves „contact@" with the name, one character per span like every other letter — so all that is
   left to say is that it is not the part we are letting: the domain stays gold, the local part is
   the grey of everything on this screen that belongs to the phone rather than to us. */
.addr-name i.is-local {
    color: rgba(245, 245, 245, .55);
}

/* The cost of a click, and it draws a DIRECTION rather than a value — no figure and no percentage
   anywhere near it. The mechanism is real and is all the copy claims: people click a link they
   understand, and the ad platforms price on click-through. What a campaign actually costs is decided
   by the campaign, which is why the terms under this section name the cost of a click among the
   things we do not guarantee. A number here would be a promise we have no measurement for. */
.addr-cost {
    display: flex;
    width: 100%;
    align-items: center;
    gap: 2cqw;
    opacity: 0;
}

    .addr-cost em {
        flex: none;
        color: rgba(245, 245, 245, .38);
        font-family: var(--font-mono);
        font-size: 2.9cqw;
        font-style: normal;
        letter-spacing: .12em;
        text-transform: uppercase;
    }

    /* The track it shrinks inside, so the drop is legible against the full length. */
    .addr-cost i {
        display: block;
        flex: 1;
        height: 1.4cqw;
        border-radius: 1cqw;
        background: rgba(245, 245, 245, .06);
        overflow: hidden;
    }

    .addr-cost b {
        display: block;
        width: 100%;
        height: 100%;
        border-radius: 1cqw;
        background: linear-gradient(90deg, var(--hairline-strong), var(--white-soft));
        transform-origin: left center;
    }

/* ACT 3 — the chat with an assistant. The question stands on its own side, because a model
   answering is a conversation and a conversation has two sides. No bubble carries the address: the
   row in the middle IS what the model came back with, and the rest of the reply runs on under it. */
.addr-bubble {
    max-width: 86%;
    padding: 2.6cqw 3.2cqw;
    border-radius: 3.4cqw;
    color: rgba(245, 245, 245, .72);
    font-size: 3.9cqw;
    font-weight: 300;
    line-height: 1.5;
}

    .addr-bubble.is-ask {
        align-self: flex-end;
        border: 1px solid var(--hairline-mid);
        border-bottom-right-radius: .8cqw;
        background: var(--black-mid);
    }

    .addr-bubble.is-reply {
        align-self: flex-start;
        border: 1px solid rgba(245, 245, 245, .07);
        border-bottom-left-radius: .8cqw;
        background: #050505;
        opacity: 0;
    }

.addr-think {
    display: flex;
    align-self: flex-start;
    gap: 1.2cqw;
    opacity: 0;
}

    .addr-think i {
        width: 1.8cqw;
        height: 1.8cqw;
        border-radius: 50%;
        background: var(--gold);
        opacity: .25;
    }

/* Text nobody is meant to read, wherever it appears: a rounded grey bar, never a hairline. A 1px
   rule reads as a divider — which is how the search step's results were reported — so every
   placeholder in this section is the same shape as a line of type instead. */
.addr-lines {
    display: flex;
    width: 100%;
    align-self: flex-start;
    flex-direction: column;
    gap: 1.8cqw;
}

    .addr-lines i {
        height: 2.2cqw;
        border-radius: 1cqw;
        background: rgba(245, 245, 245, .08);
        opacity: 0;
    }

    .addr-lines i:first-child {
        width: 78%;
    }

    .addr-lines i:last-child {
        width: 46%;
        height: 1.6cqw;
        background: rgba(245, 245, 245, .05);
    }

/* ACT 4 — the contact list. Uniqueness drawn the way a phone actually shows it: three entries
   nobody could tell apart fall away one after another, and one is left that could only be this
   house. They are shapes rather than names, for the reason the view states. */
.addr-entry {
    display: flex;
    width: 100%;
    align-items: center;
    gap: 2.6cqw;
    padding: 2.2cqw 0;
    border-bottom: 1px solid rgba(245, 245, 245, .05);
}

    .addr-entry i {
        width: 6.4cqw;
        height: 6.4cqw;
        flex: none;
        border-radius: 50%;
        background: #141414;
    }

    .addr-entry em {
        position: relative;
        min-width: 0;
        color: rgba(245, 245, 245, .4);
        font-family: var(--font-mono);
        font-size: 3.5cqw;
        font-style: normal;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

        /* The strike, drawn on the name itself rather than on the row: a line across the whole entry
           would cross the avatar too, and what is rejected is the name. The box hugs the text — the
           element is a flex item that neither grows nor is stretched — so the line is as long as the
           name and no longer. */
        .addr-entry em::after {
            content: "";
            position: absolute;
            top: 50%;
            right: 0;
            left: 0;
            height: 1px;
            background: rgba(245, 245, 245, .55);
            transform: scaleX(0);
            transform-origin: left center;
        }

.addr-only {
    color: var(--white);
    font-family: var(--font-mono);
    font-size: 3.2cqw;
    letter-spacing: .2em;
    opacity: 0;
    text-transform: uppercase;
}

/* ACT 5 — the saved contact card, which is what a business card becomes an hour after it is handed
   over. The printed card is already the subject of the flip section above this one, so repeating it
   here would argue the same thing twice with the same picture; the card in the client's phone is the
   half nothing else on the page shows. */
.addr-avatar {
    display: block;
    width: 17cqw;
    height: 17cqw;
    border: 1px solid var(--hairline-mid);
    border-radius: 50%;
    background: linear-gradient(150deg, var(--tint-raised), transparent 60%), #050505;
}

.addr-person {
    color: var(--white);
    font-family: var(--font-display);
    font-size: 5.2cqw;
    font-weight: 300;
}

.addr-fieldlabel {
    align-self: flex-start;
    margin-top: 1.2cqw;
    color: rgba(245, 245, 245, .32);
    font-family: var(--font-mono);
    font-size: 2.9cqw;
    letter-spacing: .18em;
    text-transform: uppercase;
}

/* ACT 6 — the search. The field is at the top where a phone puts it, the word is typed rather than
   printed, and the row in the middle is the first result with the two nobody reads under it. */
.addr-field {
    display: flex;
    width: 100%;
    align-items: center;
    gap: 2cqw;
    padding: 2.6cqw 3cqw;
    border: 1px solid rgba(245, 245, 245, .08);
    border-radius: 6cqw;
    background: #101010;
    color: var(--white);
    font-family: var(--font-mono);
    font-size: 3.9cqw;
}

.addr-glass {
    width: 3.2cqw;
    height: 3.2cqw;
    flex: none;
    border: 1px solid rgba(245, 245, 245, .38);
    border-radius: 50%;
}

    /* The word itself, revealed a character at a time.

       The width is the TEXT's width and the typing animates max-width over it. A fixed `chars × 1ch` box
       puts the caret a visible gap past the last letter, because ch is the width of a zero and this face is
       proportional: every lowercase
       letter is narrower than that, so the text ended well before the box did and the caret, sitting
       after the box, blinked in empty space. With max-content the box is exactly the word and the
       caret is glued to it; while the animation is still under the text's own width it is the clip
       edge that travels, which is what typing looks like. The cap is generous on purpose, so no
       translation is ever clipped — it means the word finishes a little before the animation does,
       which is invisible, whereas a cap measured too tight would truncate a word for ever. */
    .addr-field em {
        width: max-content;
        max-width: calc(var(--addr-chars, 14) * 1ch);
        overflow: hidden;
        font-style: normal;
        white-space: nowrap;
    }

.addr-caret {
    width: 1px;
    height: 1em;
    flex: none;
    background: var(--gold);
}

/* The other results. Grey blocks in the shape of a result — a title and a shorter line under it —
   and never names: a plausible address printed as the one nobody clicked may well belong to
   somebody, and a reader who can read the losers starts comparing them instead of seeing that the
   answer is at the top. */
.addr-hit {
    display: flex;
    width: 100%;
    flex-direction: column;
    gap: 1.4cqw;
    opacity: 0;
}

    .addr-hit i {
        height: 2.2cqw;
        border-radius: 1cqw;
        background: rgba(245, 245, 245, .08);
    }

    .addr-hit i:first-child {
        width: 66%;
    }

    .addr-hit i:last-child {
        width: 42%;
        height: 1.6cqw;
        background: rgba(245, 245, 245, .05);
    }
/* #endregion */

/* #region The argument and the meter */
/* The figure is the section's rhythm now that nothing is boxed. Muted at rest; the act being played
   carries it in gold. */
.addr-num {
    color: rgba(245, 245, 245, .5);
    font-family: var(--font-display);
    font-size: clamp(1.6rem, 3vw, 2.6rem);
    font-style: italic;
    line-height: 1;
}

.addr-act.is-live .addr-num,
.addr-act.is-playing .addr-num {
    color: var(--gold);
}

/* Display type, not a mono label in capitals. Six lines of small uppercase read as six tags on six boxes; in
   the house's own editorial face they read as six headings, which is what they are. */
.addr-title {
    margin: 0;
    color: var(--white);
    font-family: var(--font-display);
    font-size: clamp(1.15rem, 1.8vw, 1.55rem);
    font-weight: 300;
    letter-spacing: -.01em;
    line-height: 1.25;
    /* „Jeden egzemplarz na świecie" otherwise sets as a full line and a single orphaned word, and a
       display heading with one word on its last line reads as a fault in a house whose typography is
       part of the product. Balanced, the browser evens the lines out for us. */
    text-wrap: balance;
}

/* The house's own body size, the same declaration .explore-intro carries — so the sentence that
   argues each step reads at the size of the lead that opened the section. A step smaller and a shade lighter
   makes the one line the reader is meant to agree with the quietest type on the stage. The terms below keep
   their smaller size: those are terms, not the argument. */
.addr-desc {
    margin: 0;
    color: var(--text-muted);
    font-size: clamp(1rem, 1.05vw, 1.05rem);
    font-weight: 300;
    line-height: 1.75;
}

.addr-argument {
    position: relative;
    display: flex;
    width: 100%;
    flex-direction: column;
    gap: clamp(1.8rem, 3vh, 2.6rem);
    grid-area: argument;
}

.addr-act {
    display: grid;
    gap: clamp(.7rem, 1.4vh, 1.1rem) clamp(1.1rem, 2vw, 1.8rem);
    grid-template-columns: auto minmax(0, 1fr);
    padding-top: clamp(1rem, 2vh, 1.6rem);
    border-top: 1px solid var(--hairline);
}

    .addr-act .addr-num {
        grid-column: 1;
        grid-row: 1;
    }

    .addr-act .addr-title {
        grid-column: 2;
        grid-row: 1;
    }

    .addr-act .addr-desc {
        grid-column: 2;
        grid-row: 2;
    }

/* The plain reading gets the same cascade as the staged one — the figure, then the heading, then
   the sentence — played by the observer as each act is scrolled to. Without it the observer would be
   adding a class nothing answers, and a phone would get six blocks of type standing still. */
.addr-theatre:not(.is-theatre) .addr-act.is-playing .addr-num,
.addr-theatre:not(.is-theatre) .addr-act.is-playing .addr-title,
.addr-theatre:not(.is-theatre) .addr-act.is-playing .addr-desc {
    animation: addr-rise .7s var(--ease-house) both;
}

.addr-theatre:not(.is-theatre) .addr-act.is-playing .addr-title {
    animation-delay: .1s;
}

.addr-theatre:not(.is-theatre) .addr-act.is-playing .addr-desc {
    animation-delay: .2s;
}

/* The step markers, and since the terms moved into the argument column this holds nothing else.
   Hidden by default: a position among ten steps exists only while the steps are being played, so
   in the plain stacked reading — and on a phone, where the stage does not run — there is nothing
   here to show and an empty column would still take its share of the row. */
.addr-meter {
    display: none;
    grid-area: meter;
}

/* Where the reader stands among the six. It appears only once the staging is on — in the plain
   stacked reading there is no position to be in. */
.addr-rail {
    display: none;
}

/* The terms, at the foot of the argument column — beside the claims they qualify, not on the far
   side of the stage where they shared a column with the step markers. Set small and quiet on
   purpose: they are in view for the whole time the steps are playing, which is the only moment they
   matter, and they have to be readable there without competing with the object in the middle. In
   the plain reading the same paragraph simply closes the list of steps. */
.addr-note {
    max-width: 60rem;
    margin: 0;
    color: var(--text-muted);
    font-size: .78rem;
    font-weight: 300;
    line-height: 1.7;
    opacity: .75;
}
/* #endregion */

/* #region The staged reading */
/* Room to scroll through, and the number of steps decides it: the view hands down --addr-steps, so
   adding a place an address is seen costs a step and nothing else.

   The figure has come down twice as steps were added, and for one reason: the total is what a reader
   feels, not the share. Six steps carried seven tenths of a screen each; at nine that ran past six
   screens of scroll, and at twelve two thirds each would have been nearly eight — a single section
   longer than most whole pages. Just over half a screen each keeps ten of them at about five and a
   half, which is what this section may take. Beyond a dozen steps the answer is not a smaller
   figure, it is fewer steps: a place an address is seen that cannot earn half a screen was not worth
   a step, which is why the last two were struck rather than squeezed — the name that can be checked,
   and the job advert that made the paid advert's argument a second time. */
.addr-theatre.is-theatre {
    /* The device's width, written once because three things are measured from it: the phone itself,
       the argument column's height and — through that — where the terms sit. 36vh of width is a
       phone about seven tenths of the screen tall; 2.055 is the 9:18.5 the device is drawn at, so
       the column beside it is exactly as tall as the object it stands next to. */
    --addr-device-w: min(21rem, 36vh);
    position: relative;
    height: calc(var(--addr-steps, 6) * 54vh);
}

/* The section's own foot, and it is the ONE place the house's section rhythm is wrong for a section.
   Every other one ends on its last line of type, so `--section-space` beneath it is the right
   distance. This one ends on a stage pinned for a whole window: the last step finishes with the phone
   still standing in ninety vertical hundredths of empty screen, and the standard foot lands on top of
   all that air.

   Guarded by exactly the condition that decides whether the stage is pinned at all (space.js reads
   the same two queries), because in the stacked reading the section really does end on a paragraph
   and really does want the full measure. */
/* :has(), because the reason for the short foot is the stage INSIDE the section, not the section's
   class — and that class is worn by the family pages too, where there is no theatre. Scoped to the
   class alone it takes their bottom spacing away; scoped like this, a section with no pinned stage in
   it keeps the house's full measure. */
@media (min-width: 1001px) and (prefers-reduced-motion: no-preference) {
    .strategy-section:has(.addr-theatre) {
        padding-bottom: clamp(1.5rem, 3vh, 2.5rem);
    }
}

    .addr-theatre.is-theatre .addr-fixed {
        position: sticky;
        top: 5vh;
        min-height: 90vh;
    }

    /* Three columns, and the middle one is the address. The argument is off to one side because the
       middle of the screen belongs to the plate — which is also the only arrangement in which the
       plate is genuinely at the centre of what the reader is looking at. */
    .addr-theatre.is-theatre .addr-frame {
        align-items: center;
        min-height: 90vh;
        gap: clamp(1.4rem, 3vw, 3.4rem);
        grid-template-areas: "argument arena meter";
        grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    }

    /* A square arena, like every other image on this site. */
    /* The device is sized off the viewport's height here, because a phone is tall and the frame it
       stands in is one screen: a width in rem alone would run the phone off the bottom on a laptop.
       Its own width follows from that through the aspect ratio, and every length inside it follows
       from the width.

       36vh of width is a phone about seven tenths of the screen tall, and it must not go much below
       that: this section is pinned for a whole screen, so at 27vh the object takes a quarter of it and
       reads as a widget on a page of full-bleed sections rather than as the subject of one. */
    .addr-theatre.is-theatre .addr-device {
        width: var(--addr-device-w);
    }

    /* Act seven engraves a local part with the name, so the row's one token is nine characters
       longer here than anywhere else — „contact@transplantologist.com" is twenty-nine of them, about
       seventy of the row's ninety-one at this size. A notch smaller is what keeps the longest
       address inside the plate; it costs nothing in the other nine steps, which never see it. */
    .addr-theatre.is-theatre .addr-arena[data-addr-act-index="7"] .addr-name {
        font-size: 4.6cqw;
    }

    .addr-theatre.is-theatre .addr-set.is-live {
        opacity: 1;
        transform: none;
        visibility: visible;
    }

    /* Every act's argument stands in the same place and only one is lit. */
    /* Exactly the device's own height, so both columns are as tall as the object between them —
       which is what lets the terms sit level with the phone's bottom edge rather than somewhere
       near it. */
    .addr-theatre.is-theatre .addr-argument {
        display: block;
        justify-self: end;
        max-width: 30rem;
        min-height: calc(var(--addr-device-w) * 2.055);
    }

    .addr-theatre.is-theatre .addr-act {
        position: absolute;
        top: 50%;
        right: 0;
        display: grid;
        width: 100%;
        padding: 0;
        border: 0;
        gap: clamp(.6rem, 1.2vh, 1rem);
        grid-template-columns: minmax(0, 1fr);
        opacity: 0;
        transform: translateY(-50%);
        transition: opacity .45s ease;
        visibility: hidden;
    }

        .addr-theatre.is-theatre .addr-act.is-live {
            opacity: 1;
            visibility: visible;
        }

        .addr-theatre.is-theatre .addr-act .addr-num,
        .addr-theatre.is-theatre .addr-act .addr-title,
        .addr-theatre.is-theatre .addr-act .addr-desc {
            grid-column: 1;
            grid-row: auto;
        }

    .addr-theatre.is-theatre .addr-num {
        font-size: clamp(2.1rem, 3.6vw, 3.2rem);
    }

    .addr-theatre.is-theatre .addr-title {
        font-size: clamp(1.6rem, 2.8vw, 2.5rem);
    }

    .addr-theatre.is-theatre .addr-desc {
        font-size: clamp(1rem, 1.2vw, 1.18rem);
    }

    /* The argument arrives as three things a beat apart — the figure, then what the job is called,
       then what it means. Sliding in as one block is what makes a change of act read as a slide
       changing rather than as somebody turning to the next point. */
    .addr-theatre.is-theatre .addr-act.is-playing .addr-num,
    .addr-theatre.is-theatre .addr-act.is-playing .addr-title,
    .addr-theatre.is-theatre .addr-act.is-playing .addr-desc {
        animation: addr-rise .7s var(--ease-house) both;
    }

    .addr-theatre.is-theatre .addr-act.is-playing .addr-title {
        animation-delay: .1s;
    }

    .addr-theatre.is-theatre .addr-act.is-playing .addr-desc {
        animation-delay: .2s;
    }

    /* Six hairlines standing on end: the section is built of rules and this is six more of them. */
    /* Stretched to the device's height. The rail is a position indicator, so it belongs beside the
       MIDDLE of the object it indexes — pinned to the top by a space-between it reads as floating far
       above the phone. One child, so a flex box is enough: the rail centres against the phone and
       there is nothing else in the column to arrange around it. A two-row grid is what this needs only
       while the terms share the column, and they sit at the foot of the section instead. */
    .addr-theatre.is-theatre .addr-meter {
        display: flex;
        align-items: center;
        justify-self: start;
    }

        /* Level with the phone's bottom edge, which is what the column's min-height is for: the
           argument column is exactly as tall as the device, so the foot of one is the foot of the
           other. Absolute, because the acts above are absolute too — the terms must not be pushed
           about by whichever of the ten steps is currently lit. */
        /* Flush with the LEFT edge of the column, on the same margin the ten steps are set to.
           Pinned right and capped narrower than the steps, as it first was, the paragraph started
           four rem inside them — which reads as a block that is not aligned to anything. */
        .addr-theatre.is-theatre .addr-note {
            position: absolute;
            left: 0;
            bottom: 0;
            width: 100%;
            max-width: none;
            text-align: left;
        }

    .addr-theatre.is-theatre .addr-rail {
        display: flex;
        flex-direction: column;
        margin: 0;
        padding: 0;
        gap: .5rem;
        list-style: none;
    }

        /* Every rung keeps its box, and the live one is scaled rather than grown. Growing it from
           30px to 44px pushes every rung below it fourteen pixels down and back on each step, so with
           ten of them anchored at the top of the column the whole rail visibly shifts. A transform
           paints outside the box without resizing it: the rung being read is longer and none of the
           others moves. */
        .addr-rail li {
            width: 1px;
            height: 32px;
            background: var(--hairline);
            transition: background .45s var(--ease-house), transform .45s var(--ease-house);
        }

            .addr-rail li.is-live {
                background: var(--gold);
                transform: scaleY(1.4);
            }
/* #endregion */

/* #region The scenery in motion */
/* An act plays when the reader reaches it, and plays again if they come back: space.js takes the
   class off, forces a reflow and puts it back, because an animation that has already finished does
   not restart on its own.

   Everything below is a thing happening rather than a thing appearing. Six sets all fading up from
   below are six of the same gesture, and a gesture repeated six times stops being read at all — so
   the traffic travels down the lines, the long address visibly runs out of the line, the model pauses
   before it answers, the plate's frame is staked, the paper is laid under it and the query is typed.

   Nothing here touches the plate's position. The only animations the plate itself carries are the
   characters of its name being cut out and cut back in, and the light passing over it while that
   happens — and both belong to the name change, not to any act. */

/* THE ENGRAVING. The name is not swapped: the outgoing characters are cut out of the plate one by
   one and the incoming ones are cut in behind them, so the change reads as the plate being
   re-engraved rather than as a slide advancing. The per-character delay is set by space.js, which
   is also the only place that knows how many characters there are. */
@keyframes addr-cut-out {
    from {
        opacity: 1;
        transform: none;
    }

    to {
        opacity: 0;
        transform: translateY(-.34em);
    }
}

@keyframes addr-cut-in {
    from {
        opacity: 0;
        transform: translateY(.42em);
    }

    to {
        opacity: 1;
        transform: none;
    }
}

@keyframes addr-rise {
    from {
        opacity: 0;
        transform: translateY(14px);
    }

    to {
        opacity: 1;
        transform: none;
    }
}

@keyframes addr-draw {
    from {
        transform: scaleY(0);
    }

    to {
        transform: scaleY(1);
    }
}

/* The traffic itself, running down the line into the place it is being sent. Without it the fan is three
   rules being drawn, which says a diagram was built — not that anything moved through it. */
@keyframes addr-travel {
    0% {
        opacity: 0;
        transform: translateY(0);
    }

    15%, 85% {
        opacity: 1;
    }

    100% {
        opacity: 0;
        transform: translateY(var(--addr-fan-drop, 2.6rem));
    }
}

/* The one name left, and the plate's own frame is what claims it: the passe-partout rule brightens
   to full gold and settles back. A second ring drawn around the plate says a border was added rather
   than that this object is the only one. */
@keyframes addr-stake {
    from {
        border-color: var(--hairline-mid);
    }

    35% {
        border-color: var(--gold);
    }

    to {
        border-color: var(--hairline-mid);
    }
}

/* What reaches a mailbox from a sender that authenticates nothing: the bar starts full and runs
   down to a tenth of itself. Not to zero — some of it does arrive, and this house does not make a
   claim it cannot measure. */
@keyframes addr-drain {
    from {
        transform: scaleX(1);
    }

    to {
        transform: scaleX(.1);
    }
}

/* A look-alike name settling into a rejection: it stays exactly where it is and only loses weight,
   because the strike through it is what says „not this one". Fading it out to nothing said instead
   that the phone had lost the entry. */
@keyframes addr-reject {
    from {
        opacity: 1;
    }

    to {
        opacity: .42;
    }
}

/* The line drawn through the address being given up. It travels rather than appearing, because a strike
   that is simply there reads as a fact rather than as a decision — and it is a strike rather than a drift to
   the left, which reads as a rendering fault rather than as a judgement. */
@keyframes addr-strike {
    from {
        transform: scaleX(0);
    }

    to {
        transform: scaleX(1);
    }
}


/* The cost of a click coming down. Deliberately not to zero and not to a round fraction that could
   be read as a figure: it stops at a little under half, which says „less" and refuses to say „how
   much". A bar that emptied would be a promise. */
@keyframes addr-cheaper {
    from {
        transform: scaleX(1);
    }

    to {
        transform: scaleX(.44);
    }
}

/* Light moving across the row as the name in it is re-cut. */
@keyframes addr-sheen {
    from {
        transform: translateX(-120%);
    }

    to {
        transform: translateX(220%);
    }
}

/* The model taking a moment. A question answered the instant it is asked is a lookup; the pause is
   what makes the scene read as something reasoning. */
@keyframes addr-think {
    0%, 80%, 100% {
        opacity: .25;
    }

    40% {
        opacity: 1;
    }
}

/* Typed, not printed: the reader watches somebody look for a service. Steps, so it advances a
   character at a time — the count comes from the view, because the word is a translation and its
   length changes with the language.

   It animates MAX-WIDTH, never width. Width to `chars × 1ch` leaves the query followed by a wide band of
   empty space with the caret blinking at the far end of it: this
   house has no monospace face — `--font-mono` resolves to the body font — so 1ch is the width of a
   zero while every letter and every space in „solidity audit" is narrower. Fourteen zeros are far
   wider than the fourteen characters actually drawn. With max-width the element keeps `width:
   max-content`, so the box is exactly the word at every moment: what travels is the clip edge, and
   once it passes the word's own width the box simply stops growing and the caret stays glued to the
   last letter. The generous cap then costs nothing — it only has to be wide enough that no
   translation is ever truncated. */
@keyframes addr-type {
    from {
        max-width: 0;
    }

    to {
        max-width: calc(var(--addr-chars, 14) * 1ch);
    }
}

@keyframes addr-hold {
    0% {
        opacity: 0;
    }

    12%, 82% {
        opacity: 1;
    }

    100% {
        opacity: 0;
    }
}

@keyframes addr-blink {
    0%, 45% {
        opacity: 1;
    }

    50%, 95% {
        opacity: 0;
    }

    100% {
        opacity: 1;
    }
}

/* THE NAME CHANGE. The only motion the address row itself carries, and it belongs to no act: the
   characters are cut out, the next name is cut in behind them, and the light passes over the row
   while it happens. space.js sets the per-character delay and takes the classes off again. */
.addr-name.is-cutting i {
    animation: addr-cut-out .26s ease-in both;
}

.addr-name.is-setting i {
    animation: addr-cut-in .34s var(--ease-house) both;
}

.addr-row.is-engraving::after {
    opacity: 1;
    animation: addr-sheen 1.4s cubic-bezier(.4, 0, .2, 1) both;
}

/* THE PHONE'S OWN BREATH. A phone in somebody's hand is never perfectly still, and an object that
   is perfectly still on a page reads as a photograph of an object. Deliberately small — this
   section has to be read, not admired — and it stops while the reader is pointing at the device,
   because a screen somebody is trying to read should not be moving. */
@keyframes addr-breathe {
    0%, 100% {
        transform: perspective(70rem) rotateY(-2deg) rotateX(.9deg);
    }

    50% {
        transform: perspective(70rem) rotateY(2deg) rotateX(-.5deg);
    }
}

.addr-theatre.is-theatre .addr-phone {
    animation: addr-breathe 17s ease-in-out infinite;
}

.addr-device[href]:hover .addr-phone {
    animation-play-state: paused;
}

/* ACT 1 — the browser. The tab strip arrives first and says which app this is; then the line under
   the bar is drawn, the traffic runs down it, and only as it lands do the three places the venue
   already sells from light up in turn. A destination that answers before the request arrives is a
   diagram, not a gateway. */
.addr-set.is-playing .addr-tabs {
    animation: addr-rise .55s var(--ease-house) both;
}

.addr-set.is-playing .addr-drop i {
    animation: addr-draw .4s ease .5s both;
}

.addr-set.is-playing .addr-drop b {
    animation: addr-travel .6s ease-in-out .8s both;
}

.addr-set.is-playing .addr-tile {
    animation: addr-rise .55s var(--ease-house) both;
}

    .addr-set.is-playing .addr-tile:nth-child(1) {
        animation-delay: 1.3s;
    }

    .addr-set.is-playing .addr-tile:nth-child(2) {
        animation-delay: 1.45s;
    }

    .addr-set.is-playing .addr-tile:nth-child(3) {
        animation-delay: 1.6s;
    }

/* ACT 2 — the paid advert, built in the order a reader reads one: „Sponsorowane", the display
   address, the headline, the description. The old address is struck out once it has been read, and
   only then does the cost of a click come down — in that order and not the other way round, because
   the bar is the consequence of a link somebody understood. */
.addr-set.is-playing .addr-adtag,
.addr-set.is-playing .addr-oldline {
    animation: addr-rise .55s var(--ease-house) both;
}

.addr-set.is-playing .addr-oldline {
    animation-delay: .18s;
}

.addr-set.is-playing .addr-adhead {
    animation: addr-rise .55s var(--ease-house) .35s both;
}

/* The strike travels across the long address once it has been read, and only then does the cost of a
   click come down: the name is given up first, and the saving is the consequence. */
.addr-set.is-playing .addr-oldline em::after {
    animation: addr-strike .7s cubic-bezier(.4, 0, .2, 1) 1.1s both;
}

.addr-set.is-playing .addr-cost {
    animation: addr-rise .55s var(--ease-house) 1.5s both;
}

.addr-set.is-playing .addr-cost b {
    animation: addr-cheaper .9s var(--ease-house) 2.3s both;
}

/* ACT 3 — the chat. The pause has to end, or the scene reads as a model that never finished
   thinking, so the dots run twice and go; the reply follows, and the rest of it settles under the
   address the model named. */
.addr-set.is-playing .addr-bubble.is-ask {
    animation: addr-rise .6s var(--ease-house) both;
}

.addr-set.is-playing .addr-think {
    animation: addr-hold 1.9s ease .35s both;
}

.addr-set.is-playing .addr-think i {
    animation: addr-think 1.1s ease-in-out .45s 2;
}

    .addr-set.is-playing .addr-think i:nth-child(2) {
        animation-delay: .6s;
    }

    .addr-set.is-playing .addr-think i:nth-child(3) {
        animation-delay: .75s;
    }

.addr-set.is-playing .addr-bubble.is-reply {
    animation: addr-rise .6s var(--ease-house) 2.1s both;
}

.addr-set.is-playing .addr-lines i {
    animation: addr-rise .5s var(--ease-house) both;
}

    .addr-set.is-playing .addr-lines i:first-child {
        animation-delay: 2.7s;
    }

    .addr-set.is-playing .addr-lines i:last-child {
        animation-delay: 2.85s;
    }

/* ACT 4 — the contact list. The look-alike entries are STRUCK OUT one by one and stay on the list,
   the way the address given up in the advert step is struck rather than moved. Fading them away to nothing
   argues the wrong thing: three rows disappearing from a contact list reads as the phone losing entries, and
   by the end the comparison the step is making has left the screen — the reader is looking at one name with
   nothing to compare it to. Struck and
   left in place, all four names are visible at once and the judgement is on the screen rather than
   in the reader's memory. Then the row acknowledges: its own edge takes full gold for a moment and
   settles back. The stake reaches the row through the sibling combinator — the row follows all
   ten acts in the markup, which is what lets an act touch it without owning it, and it is a
   change of colour rather than of position, so the address still does not move. */
.addr-set.is-playing .addr-entry {
    animation: addr-reject .55s ease both;
}

    .addr-set.is-playing .addr-entry em::after {
        animation: addr-strike .55s cubic-bezier(.4, 0, .2, 1) both;
    }

    .addr-set.is-playing .addr-entry:nth-child(1),
    .addr-set.is-playing .addr-entry:nth-child(1) em::after {
        animation-delay: .5s;
    }

    .addr-set.is-playing .addr-entry:nth-child(2),
    .addr-set.is-playing .addr-entry:nth-child(2) em::after {
        animation-delay: .75s;
    }

    .addr-set.is-playing .addr-entry:nth-child(3),
    .addr-set.is-playing .addr-entry:nth-child(3) em::after {
        animation-delay: 1s;
    }

.addr-set.is-single.is-playing ~ .addr-row {
    animation: addr-stake 1.6s ease 1.9s both;
}

.addr-set.is-playing .addr-only {
    animation: addr-rise .6s var(--ease-house) 2.2s both;
}

/* ACT 5 — the saved card, filled in the order somebody actually fills one: the picture, the name,
   and last the field the address goes in. */
.addr-set.is-playing .addr-avatar,
.addr-set.is-playing .addr-person,
.addr-set.is-playing .addr-fieldlabel {
    animation: addr-rise .6s var(--ease-house) both;
}

.addr-set.is-playing .addr-person {
    animation-delay: .12s;
}

.addr-set.is-playing .addr-fieldlabel {
    animation-delay: .24s;
}

/* ACT 6 — the search. The word is typed, and only then do the results nobody reads settle under the
   one that answered. */
.addr-set.is-playing .addr-field {
    animation: addr-rise .6s var(--ease-house) both;
}

.addr-set.is-playing .addr-field em {
    animation: addr-type 1.1s steps(var(--addr-chars, 14), end) .4s both;
}

.addr-set.is-playing .addr-caret {
    animation: addr-blink 1.1s steps(1, end) infinite;
}

.addr-set.is-playing .addr-hit {
    animation: addr-rise .5s var(--ease-house) both;
}

    .addr-set.is-playing .addr-hit:nth-of-type(1) {
        animation-delay: 1.9s;
    }

    .addr-set.is-playing .addr-hit:nth-of-type(2) {
        animation-delay: 2.05s;
    }

/* ACT 7 — the inbox. The sender that never arrived is there first, so the one that did arrives
   against it rather than on its own. */
.addr-set.is-playing .addr-junk {
    animation: addr-rise .55s var(--ease-house) both;
}

.addr-set.is-playing .addr-subject,
.addr-set.is-playing .addr-message,
.addr-set.is-playing .addr-sign {
    animation: addr-rise .55s var(--ease-house) both;
}

.addr-set.is-playing .addr-subject {
    animation-delay: .9s;
}

.addr-set.is-playing .addr-message {
    animation-delay: 1.05s;
}

.addr-set.is-playing .addr-sign {
    animation-delay: 1.25s;
}

/* ACT 8 — the telephone. The question, then the dictation, then the row said instead of it. */
.addr-set.is-playing .addr-callbar {
    animation: addr-rise .55s var(--ease-house) both;
}

.addr-set.is-playing .addr-spell {
    animation: addr-rise .55s var(--ease-house) .7s both;
}

    /* Struck only once it has been read, and before the row below says what is said instead — the
       order is the argument: this is what you spell today, and this is what you would say instead. */
    .addr-set.is-playing .addr-spell em::after,
    .addr-set.is-playing .addr-spell b::after {
        animation: addr-strike .6s cubic-bezier(.4, 0, .2, 1) 1.4s both;
    }

.addr-set.is-playing .addr-close {
    animation: addr-rise .55s var(--ease-house) 2s both;
}

/* ACT 9 — the payment screen. The amount, then the button somebody is about to press. */
.addr-set.is-playing .addr-paylabel,
.addr-set.is-playing .addr-amount i {
    animation: addr-rise .55s var(--ease-house) both;
}

.addr-set.is-playing .addr-amount i:first-child {
    animation-delay: .12s;
}

.addr-set.is-playing .addr-amount i:last-child {
    animation-delay: .24s;
}

.addr-set.is-playing .addr-paycta {
    animation: addr-rise .55s var(--ease-house) 1.1s both;
}

/* STEP 10 — the camera. The code arrives, and only once it has been read does the address settle and
   the button to open it appear. */
.addr-set.is-playing .addr-code {
    animation: addr-rise .55s var(--ease-house) .12s both;
}

.addr-set.is-playing .addr-open {
    animation: addr-rise .55s var(--ease-house) 1.1s both;
}

/* A visitor who asked for less movement gets the plain reading: the phone standing with one address
   on it and the ten arguments listed under it. space.js neither stages the section nor rotates the
   name for them, so what is left to switch off is the light on the row and the device's own breath —
   and the characters are neutralised in case the classes ever arrive by another route. */
@media (prefers-reduced-motion: reduce) {
    .addr-row::after {
        display: none;
    }

    .addr-name i {
        opacity: 1;
        animation: none;
        transform: none;
    }

    .addr-phone {
        animation: none;
    }
}
/* #endregion */


/* #endregion */

/* #region OpEx vs CapEx */
.fin-grid {
    display: grid;
    grid-template-columns: 1.2fr 1fr;
    gap: 8vw;
    align-items: center;
    max-width: none;
    margin: 0 auto;
}

.fin-content h2 {
    font-family: var(--font-display);
    font-size: var(--section-title-size);
    color: var(--white);
    font-weight: 300;
    letter-spacing: -.035em;
    margin-bottom: 3vh;
    line-height: var(--section-title-line-height);
}

    .fin-content h2 i {
        color: var(--gold);
        font-weight: 300;
    }

.fin-content p {
    font-size: 1.05rem;
    font-weight: 200;
    color: var(--text-muted);
    line-height: 1.8;
    margin-bottom: 2vh;
}

.fin-list {
    list-style: none;
    margin-top: 4vh;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 15px;
}

    .fin-list li {
        display: flex;
        align-items: center;
        gap: 12px;
        font-size: 1rem;
        color: var(--text-muted);
        font-weight: 200;
    }

        .fin-list li span {
            color: rgba(245, 245, 245, .5);
            font-size: 1.2rem;
        }

        /* The emphasised line is the list's one accent: white text, its mark in gold. */
        .fin-list li.emphasis {
            color: var(--white);
            font-weight: 400;
        }

            .fin-list li.emphasis span {
                color: var(--gold);
            }

.fin-chart {
    background: linear-gradient(145deg, var(--tint), transparent 55%), var(--surface-card);
    border: 1px solid var(--hairline);
    padding: clamp(2.5rem, 5vw, 5rem);
}

.bar-wrap {
    display: flex;
    align-items: center;
    gap: 20px;
    margin-bottom: 3vh;
}

    .bar-wrap:last-child {
        margin-bottom: 0;
    }

.bar-lbl {
    width: 80px;
    font-family: var(--font-mono);
    font-size: 0.65rem;
    text-transform: uppercase;
    letter-spacing: 3px;
    color: var(--text-muted);
}

    .bar-lbl.gold {
        color: var(--white);
    }

.bar-track {
    flex: 1;
    height: 1px;
    background: var(--white-subtle);
    position: relative;
}

.bar-fill {
    position: absolute;
    top: -10px;
    left: 0;
    height: 20px;
    background: var(--white-subtle);
    transition: width 2s var(--ease-house);
}

    /* The leased bar is drawn in white; the chart's one gold is the lease's value beside it. */
    .bar-fill.gold {
        background: var(--white);
    }

    /* The two widths are the comparison itself — buying an address against renting one — so they are fixed
       proportions of the chart, not data. They live here rather than on the element for the same reason the
       colours do. */
    .bar-fill.is-full {
        width: 100%;
    }

    .bar-fill.is-subscription {
        width: 8%;
    }

/* Shown in place of the portfolio while no address is published. Its colour is a real token:
   --white-muted is defined nowhere, so a declaration naming it is dropped and the notice silently
   inherits whatever it stands in. */
.bar-val {
    font-family: var(--font-display);
    font-size: 1.5rem;
    color: var(--white);
    min-width: 150px;
    text-align: right;
}

    .bar-val.gold {
        color: var(--gold);
    }
/* #endregion */

/* #region Full asset catalog */
.portfolio-header {
    text-align: left;
    margin-bottom: 8vh;
}

    .portfolio-header h2 i {
        color: var(--gold);
        font-weight: 300;
    }

.portfolio-desc {
    font-size: 1.05rem;
    color: var(--text-muted);
    font-weight: 200;
    line-height: 1.8;
    max-width: 700px;
    margin: 0 0 8vh;
}

/* The pixel of overlap is deliberate. The header's height is a measured value, so it can land a
   fraction of a pixel short of where the header actually ends, and the strip then parks under a
   hairline of page — which reads as a seam, not as a bar stuck to the header. Pulling it up by one
   also swallows the strip's own top border under the header, so the two never draw a double line. */
.sticky-nav-cat-wrap {
    position: sticky;
    top: calc(var(--site-header-h, 72px) - 1px);
    z-index: 100;
    margin-bottom: 8vh;
    background: rgba(5, 5, 5, .96);
    backdrop-filter: blur(18px);
    border-top: 1px solid var(--hairline);
    border-bottom: 1px solid var(--hairline);
}

.sticky-nav-cat {
    width: min(90vw, var(--section-content-max));
    max-width: none;
    margin-inline: auto;
    padding: 1.5rem 0;
    display: flex;
    gap: 2vw;
    overflow-x: auto;
    scrollbar-width: none;
    /* safe: when the seven links are wider than the strip, centring would push the first one past the
       left edge, where a scroller cannot reach it. */
    justify-content: safe center;
}

    .sticky-nav-cat::-webkit-scrollbar {
        display: none;
    }

.nav-cat-link {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    margin-block: -10px;
    font-family: var(--font-mono);
    font-size: 0.65rem;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 3px;
    text-decoration: none;
    white-space: nowrap;
    transition: color 0.3s var(--ease-house);
}

    .nav-cat-link:hover {
        color: var(--gold);
    }

/* A jump to a category lands its heading below the sticky strip, not behind it. */
.cat-group {
    scroll-margin-top: 5rem;
    margin-bottom: clamp(5rem, 10vw, 9rem);
    max-width: 1400px;
    margin-left: auto;
    margin-right: auto;
}

    .cat-group:last-child {
        margin-bottom: 0;
    }

.cat-title {
    font-family: var(--font-display);
    font-size: clamp(1.6rem, 7vw, 2.2rem);
    color: var(--white);
    font-weight: 300;
    margin-bottom: 4vh;
    border-bottom: 1px solid var(--hairline-mid);
    padding-bottom: 1.5vh;
}

/* Columns as wide as the longer names need, not a fixed four: at four a thirty-letter address broke
   mid-word on every laptop. The count follows the width, up to four. */
.domain-grid {
    columns: 17rem 4;
    column-gap: clamp(2rem, 4vw, 4rem);
    list-style: none;
}

    .domain-grid li {
        margin-bottom: 15px;
        break-inside: avoid;
    }

        .domain-grid li a {
            display: inline-block;
            padding-block: 8px;
            margin-block: -8px;
            font-family: var(--font);
            font-size: 1.05rem;
            font-weight: 200;
            color: var(--white-bright);
            text-decoration: none;
            transition: color var(--motion-quick) var(--ease-house);
            cursor: pointer;
            overflow-wrap: anywhere;
        }

            /* A strongest name is set in white at a heavier weight; its star is the gold marker. */
            .domain-grid li a.highlight {
                color: var(--white);
                font-weight: 600;
                opacity: 1;
            }

                .domain-grid li a.highlight::after {
                    content: ' \2726';
                    color: var(--gold);
                    font-size: 0.8em;
                    vertical-align: top;
                    opacity: 0.7;
                }

            .domain-grid li a:hover {
                color: var(--white);
                text-decoration: underline;
                text-underline-offset: 4px;
                text-decoration-thickness: 1px;
                text-decoration-color: var(--gold-border);
            }

            .domain-grid li a.highlight:hover {
                color: var(--white);
            }
/* #endregion */

/* #region Usage */
.usage-mosaic-header {
    text-align: left;
    margin-bottom: 8vh;
}

    .usage-mosaic-header h2 i {
        color: var(--gold);
        font-weight: 300;
    }

.usage-mosaic-desc {
    font-size: 1.05rem;
    color: var(--text-muted);
    font-weight: 200;
    line-height: 1.8;
    max-width: 700px;
    margin: 0;
    text-align: left;
}

/* The disclosure under the mosaic's introduction. Quieter than the lead it follows, but on the
   same measure and left edge — it belongs to the section, not to the fine print at the bottom. */
.usage-mosaic-note {
    max-width: 700px;
    margin: .9rem 0 0;
    color: var(--text-muted);
    font-size: .78rem;
    font-weight: 300;
    line-height: 1.7;
    text-align: left;
    opacity: .78;
}

/* Six columns rather than five, because the mosaic's largest tiles are two columns wide: at five a
   feature takes two fifths of the row and the pattern reads as a grid at fault rather than a composed
   one. Dense, so the small tiles backfill the holes a feature leaves above it — without it every
   feature opens a gap the height of itself. */
.usage-mosaic-grid {
    max-width: none;
    margin: 0 auto;
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    grid-auto-flow: dense;
    gap: clamp(.55rem, .9vw, .9rem);
}

/* Twice the size, and square. Never a tall or a wide tile: the address is printed inside the
   photograph, so any shape but the picture's own crops it — and the first thing lost is the name
   the whole section exists to show. Which four are featured is decided in the view, by address. */
.usage-tile.is-large {
    grid-column: span 2;
    grid-row: span 2;
}

/* The mosaic is the one place on this page where an address is shown doing its job, so a tile
   answers the cursor properly: a printed gold frame appears inside the picture, the colour comes
   back and the address rises from the bottom edge. The tile itself does not lift. Brightening a little and
   fading a caption in is true to the house's quiet and indistinguishable from nothing happening. */
.usage-tile {
    position: relative;
    display: block;
    aspect-ratio: 1;
    overflow: hidden;
    background: var(--surface-card);
    border: 1px solid var(--hairline);
    text-decoration: none;
    cursor: pointer;
    transition: border-color var(--motion) var(--ease-house);
}

    .usage-tile img {
        width: 100%;
        height: 100%;
        object-fit: cover;
        display: block;
        filter: var(--photo-mute) var(--photo-at-rest);
        transition: transform 1.8s var(--ease-house), filter var(--motion-slow) var(--ease-house);
    }

    /* The frame is drawn inside the picture rather than around the tile: on a grid this dense a
       border that thickens on hover only makes the neighbours look crooked. */
    .usage-tile::after {
        content: "";
        position: absolute;
        inset: .6rem;
        z-index: 2;
        border: 1px solid var(--photo-frame-hover);
        opacity: 0;
        transition: opacity var(--motion) var(--ease-house);
        pointer-events: none;
    }

.usage-tile-overlay {
    position: absolute;
    inset: 0;
    z-index: 3;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    justify-content: flex-end;
    gap: 0.4vh;
    /* Clear of the frame drawn inside the picture: the rule sits .6rem in, so at .7rem of padding the
       address and its label stood on the line rather than inside it. */
    padding: 1.5rem;
    background: linear-gradient(180deg, rgba(5,5,5,0) 45%, rgba(5,5,5,0.85) 100%);
    opacity: 0;
    transform: translateY(14px);
    transition: opacity var(--motion-quick) var(--ease-house), transform var(--motion) var(--ease-house);
}

.usage-tile-domain {
    font-family: var(--font-display);
    font-size: clamp(0.68rem, 2.4vw, 0.85rem);
    font-weight: 500;
    color: var(--white);
    line-height: 1.2;
    overflow-wrap: anywhere;
}

.usage-tile-label {
    font-family: var(--font-mono);
    font-size: 0.6rem;
    text-transform: uppercase;
    letter-spacing: 2px;
    color: var(--gold);
}

/* The address arrives first, the label a beat later — the order somebody reads them in. */
.usage-tile-domain,
.usage-tile-label {
    opacity: 0;
    transform: translateY(8px);
    transition: opacity var(--motion-quick) var(--ease-house), transform var(--motion) var(--ease-house);
}

.usage-tile:hover,
.usage-tile:focus-visible {
    border-color: var(--hairline-strong);
}

    .usage-tile:hover::after,
    .usage-tile:focus-visible::after {
        opacity: 1;
    }

    .usage-tile:hover img,
    .usage-tile:focus-visible img {
        transform: scale(1.025);
        filter: var(--photo-lifted);
    }

    .usage-tile:hover .usage-tile-overlay,
    .usage-tile:focus-visible .usage-tile-overlay {
        opacity: 1;
        transform: none;
    }

    .usage-tile:hover .usage-tile-domain,
    .usage-tile:focus-visible .usage-tile-domain,
    .usage-tile:hover .usage-tile-label,
    .usage-tile:focus-visible .usage-tile-label {
        opacity: 1;
        transform: none;
    }

    .usage-tile:hover .usage-tile-domain,
    .usage-tile:focus-visible .usage-tile-domain {
        transition-delay: .08s;
    }

    .usage-tile:hover .usage-tile-label,
    .usage-tile:focus-visible .usage-tile-label {
        transition-delay: .16s;
    }

/* Nothing to hover with: the address is simply there. */
@media (hover: none) {
    .usage-tile-overlay,
    .usage-tile-domain,
    .usage-tile-label {
        opacity: 1;
        transform: none;
    }
}

@media (prefers-reduced-motion: reduce) {
    .usage-tile,
    .usage-tile img,
    .usage-tile::after,
    .usage-tile-overlay,
    .usage-tile-domain,
    .usage-tile-label {
        transition: none;
    }

    .usage-tile:hover img,
    .usage-tile:focus-visible img {
        transform: none;
    }
}
/* #endregion */

/* #region Lease Terms Certificate */
.space-lease-rights {
    position: relative;
    overflow: hidden;
    /* This section opens the page's closing movement after the mosaic, so it takes the full section
       measure. A clipped top edge belongs to a section standing directly under the dark „lease
       declaration", where the two are meant to read as one unfolding. */
    padding: var(--section-space) 0;
    border-bottom: 1px solid var(--section-divider);
    background: radial-gradient(circle at 78% 35%, var(--tint-raised), transparent 28%), var(--surface-editorial);
}

    .space-lease-rights-heading h2 {
        color: var(--white);
        font-family: var(--font-display);
        font-size: var(--section-title-size);
        font-weight: 300;
        letter-spacing: -.045em;
        line-height: var(--section-title-line-height);
    }

        .space-lease-rights-heading h2 i {
            color: var(--gold);
            font-family: var(--font-serif);
            font-weight: 400;
        }

    /* The house's lattice, not a graph paper. A square grid of white hairlines stood here, and it
       read as a technical drawing behind a page about a contract — the diamonds are the pattern
       every hero on the site opens with, so the terms are set on the same ground as the product.

       The geometry is the hero's, declaration for declaration: two hairlines at 45 and -45 degrees,
       centred, on the hero's own 72px cell, so the two surfaces cannot drift out of step. What is
       this section's own is the weight. Carried across a whole section behind body copy, a lattice
       at the hero's weight is wallpaper, so the alpha stays near where the squares were: white at
       .02, a resting hairline like every other one in the house.

       The mask is unchanged: the pattern arrives from the left, so it is thinnest where the heading
       stands and fullest under the ledger. */
    .space-lease-rights::after {
        position: absolute;
        inset: 0;
        background-image: linear-gradient(45deg, transparent calc(50% - .5px), rgba(245, 245, 245, .02) 50%, transparent calc(50% + .5px)), linear-gradient(-45deg, transparent calc(50% - .5px), rgba(245, 245, 245, .02) 50%, transparent calc(50% + .5px));
        background-position: center;
        background-size: 72px 72px;
        content: "";
        pointer-events: none;
        -webkit-mask-image: linear-gradient(90deg, transparent 15%, #050505 75%);
        mask-image: linear-gradient(90deg, transparent 15%, #050505 75%);
    }

.space-lease-certificate {
    position: relative;
    z-index: 1;
    padding-block: 0 clamp(.5rem, 1.2vw, 1.25rem);
}

.space-lease-rights-heading {
    display: grid;
    grid-template-columns: 1fr;
    margin-bottom: clamp(4.5rem, 9vw, 9rem);
}

    /* No eyebrow rule of its own: that measure is --section-tag-gap, and this heading is where the site's
       value was tuned rather than a place that restates it. */
    .space-lease-rights-heading > p {
        max-width: 52ch;
        margin-top: var(--section-lead-gap);
        padding-bottom: .5rem;
        color: var(--text-muted);
        font-size: clamp(1rem, 1.15vw, 1.08rem);
        font-weight: 200;
        line-height: 1.85;
    }

.space-lease-ledger {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: clamp(4rem, 9vw, 10rem);
}

.space-lease-ledger-group > header {
    padding-bottom: 1.25rem;
    margin-bottom: 1rem;
    border-bottom: 1px solid var(--hairline);
}

    .space-lease-ledger-group > header h3 {
        color: var(--white);
        font-family: var(--font-display);
        font-size: clamp(1.45rem, 2vw, 2.1rem);
        font-weight: 300;
        letter-spacing: -.025em;
    }

.space-lease-ledger-group article small.h-tag {
    margin-bottom: .8rem;
}

.space-lease-ledger-group article {
    padding: clamp(1.75rem, 3.5vw, 3rem) 0;
    border-bottom: 1px solid var(--line);
}

    .space-lease-ledger-group article h4 {
        margin: .75rem 0 .8rem;
        color: var(--white);
        font-family: var(--font-display);
        font-size: clamp(1.25rem, 1.7vw, 1.85rem);
        font-weight: 300;
        letter-spacing: -.025em;
        line-height: 1.2;
    }

    .space-lease-ledger-group article p {
        color: var(--text-muted);
        font-size: .86rem;
        font-weight: 200;
        line-height: 1.75;
    }

.space-lease-ledger-security {
    margin-top: clamp(3rem, 7vw, 7rem);
}

/* The section paraphrases the terms in its own words, so it points at them outright — quietly, as a
   footnote, and not as a second call to action beside the buy button. */
/* The document itself, under the two columns that summarise it. As a thin underlined line left of
   a wide ledger it read as a stray link somebody forgot to style; as a bordered plate it reads as
   what it is — the contract the section paraphrases, one click away and centred under both halves. */
/* The house's link to a document, in the house's own idiom (.home-product-link): a hairline under
   the words that turns gold under the hand, and an arrow that travels. A bordered pill in body type is neither the outline button the
   house uses for a destination nor the quiet link it uses for a document, and would be the only one of
   its kind on the site. */
.space-terms-source {
    display: flex;
    justify-content: center;
    margin-top: clamp(2.5rem, 5vw, 4rem);
}

    .space-terms-source .home-product-link {
        margin-top: 0;
    }

/* The point of contact: a quiet line under the terms link, never a second call to action. */
/* What an address's name is not, and whose the names quoted in its text are — said small, under the terms
   link on the Space page and above the report link on every address's page. */
.space-name-disclaimer {
    max-width: 46rem;
    margin: 1.2rem auto 0;
    color: var(--text-muted);
    font-size: .74rem;
    line-height: 1.6;
    text-align: center;
}

.space-abuse-link {
    display: flex;
    justify-content: center;
    margin-top: 1.2rem;
}

    .space-abuse-link a {
        color: var(--text-muted);
        font-size: .78rem;
        letter-spacing: .04em;
        text-decoration: underline;
        text-underline-offset: .25em;
    }

        .space-abuse-link a:hover,
        .space-abuse-link a:focus-visible {
            color: var(--gold);
        }

    .space-lease-ledger-security > header {
        border-bottom-color: var(--hairline-strong);
    }

/* .container carries no padding of its own, so these sections need the shared width treatment
   or their copy touches the screen edge on phones. */
.space-lease-rights > .container {
    width: min(90vw, var(--section-content-max));
    max-width: none;
    margin-inline: auto;
    padding-inline: 0;
}
/* #endregion */

/* #region Responsive */
@media (max-width: 1000px) {
    /* Stacked, both arguments keep the left edge every other section reads from: centred, their
       paragraphs ran ragged on both sides and the ticked list drifted with each line's length. */
    .flip-grid {
        grid-template-columns: 1fr;
    }

    .fin-grid {
        grid-template-columns: 1fr;
    }

    /* The profession pages' three steps, one under the other. */
    .strat-grid {
        grid-template-columns: 1fr;
        gap: 8vh;
    }

    /* No staging below this width. The staged reading puts an argument beside the arena and a rail
       on the other side of it, and half a tablet does not hold three columns; space.js never adds
       the class here, and these rules undo it if a window is resized down while the section is
       open. The plate stays, and so does its clock — one object being re-engraved is a small,
       contained thing that costs a phone nothing. */
    .addr-theatre.is-theatre {
        height: auto;
    }

        .addr-theatre.is-theatre .addr-fixed {
            position: static;
            min-height: 0;
        }

        .addr-theatre.is-theatre .addr-frame {
            min-height: 0;
            grid-template-areas: "arena" "argument" "meter";
            grid-template-columns: minmax(0, 1fr);
        }

        .addr-theatre.is-theatre .addr-device {
            width: min(15rem, 66vw);
        }

        .addr-theatre.is-theatre .addr-set {
            display: none;
        }

        .addr-theatre.is-theatre .addr-argument {
            display: flex;
            justify-self: stretch;
            max-width: none;
            min-height: 0;
        }

        .addr-theatre.is-theatre .addr-act {
            position: static;
            display: grid;
            align-content: start;
            grid-template-columns: auto minmax(0, 1fr);
            padding-top: clamp(1rem, 2vh, 1.6rem);
            border-top: 1px solid var(--hairline);
            opacity: 1;
            transform: none;
            visibility: visible;
        }

            .addr-theatre.is-theatre .addr-act .addr-num {
                grid-column: 1;
                grid-row: 1;
            }

            .addr-theatre.is-theatre .addr-act .addr-title {
                grid-column: 2;
                grid-row: 1;
            }

            .addr-theatre.is-theatre .addr-act .addr-desc {
                grid-column: 2;
                grid-row: 2;
            }

        /* No stage on a phone, so no position among the steps and nothing left in this column. */
        .addr-theatre.is-theatre .addr-meter {
            display: none;
        }

        .addr-theatre.is-theatre .addr-rail {
            display: none;
        }

        /* The steps stack here, so the terms close the list rather than standing at a column's foot
           — there is no column and no phone edge to be level with. */
        .addr-theatre.is-theatre .addr-note {
            position: static;
            max-width: none;
        }

    .domain-grid {
        column-count: 2;
    }

    /* Three columns, and the double tiles go back to being ordinary ones. Thirty equal tiles divide
       into three columns exactly, which is what keeps the bottom edge straight; at four they do
       not, and with a double tile in play nothing below six columns closes evenly. */
    .usage-mosaic-grid {
        grid-template-columns: repeat(3, 1fr);
    }

    .usage-tile.is-large {
        grid-column: auto;
        grid-row: auto;
    }

    .usage-tile-overlay,
    .usage-tile-domain,
    .usage-tile-label {
        opacity: 1;
        transform: none;
    }

    .sticky-nav-cat {
        justify-content: flex-start;
    }

    .fin-list {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
    }

    .space-lease-rights-heading > p {
        max-width: 50ch;
    }

    .space-lease-ledger {
        grid-template-columns: 1fr;
        gap: clamp(4rem, 9vh, 7rem);
    }

    .space-lease-ledger-security {
        margin-top: 0;
    }
}

/* Label and value share the first row; the bar takes its own full-width row below, at every width. In
   one row each track got whatever its label and value left — a different length per row, a few pixels
   on a tablet — so the 100% and the 8% stopped being a comparison. The gap clears the fill, which
   stands ten pixels above its hairline. */
.bar-wrap {
    flex-wrap: wrap;
    row-gap: calc(10px + .6rem);
}

.bar-lbl {
    width: auto;
}

.bar-track {
    order: 3;
    flex-basis: 100%;
}

.bar-val {
    min-width: 0;
    margin-left: auto;
}

@media (max-width: 600px) {
    .domain-grid {
        column-count: 1;
    }

    .bar-val {
        font-size: clamp(1.1rem, 4.5vw, 1.5rem);
    }

    /* The flip card's faces are absolutely positioned, so a fixed aspect ratio decides the height
       regardless of content; letting the front face size the card keeps the text inside. */
    .identity-card {
        aspect-ratio: auto;
    }

    .card-face {
        position: relative;
    }

    .face-pro {
        position: absolute;
        inset: 0;
        height: 100%;
    }

    .c-header {
        gap: 14px;
        margin-bottom: 20px;
    }

    .c-avatar {
        width: 48px;
        height: 48px;
    }

    .c-name {
        font-size: clamp(1.25rem, 6vw, 1.8rem);
    }

    .c-email {
        font-size: 1rem;
        overflow-wrap: anywhere;
    }

    /* Thirty into two columns is fifteen rows, again exactly. The double tiles are already off from
       the breakpoint above. */
    .usage-mosaic-grid {
        grid-template-columns: repeat(2, 1fr);
    }


    .space-lease-ledger-group article {
        grid-template-columns: 3.25rem 1fr;
        gap: 1rem;
    }
}

@media (prefers-reduced-motion: reduce) {
    .space-lease-certificate {
        transition: none !important;
    }
}
/* #endregion */

/* #region Domain Grid & Usage Tiles */
.domain-grid a.is-taken {
    opacity: .55;
}

.domain-taken-mark {
    font-size: .62rem;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.usage-tile:not([href]) {
    cursor: default;
}
/* #endregion */

/* #region Profession catalogs */
/* The family landing pages are built like a product page and carry their own stylesheet
   (space-profession.css); what stays here is the portfolio page's own link across to them. */

/* The heading row of a category in the portfolio. The rule under it belongs to the row, not to the
   heading, so the link to the profession catalogue can stand at the far right of the same line —
   inside the <h3> it inherited the display face and read as a stray fragment of the title.
   The family pages use the same row for a price-class heading and its monthly rate. */
.cat-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: .6rem 2rem;
    margin-bottom: 4vh;
    padding-bottom: 1.5vh;
    border-bottom: 1px solid var(--hairline-mid);
}

    .cat-head .cat-title {
        margin-bottom: 0;
        padding-bottom: 0;
        border-bottom: 0;
    }

/* The site's link idiom — uppercase, tracked, an arrow that steps forward on hover. */
.cat-head-link {
    display: inline-flex;
    align-items: center;
    min-height: 32px;
    margin-left: auto;
    color: var(--text-muted);
    font-family: var(--font-sans);
    font-size: .68rem;
    font-weight: 400;
    letter-spacing: .2em;
    text-decoration: none;
    text-transform: uppercase;
    white-space: nowrap;
    transition: color var(--motion-quick) var(--ease-house);
}

    .cat-head-link span {
        display: inline-block;
        transition: transform var(--motion-quick) var(--ease-house);
    }

    .cat-head-link:hover,
    .cat-head-link:focus-visible {
        color: var(--gold);
    }

        .cat-head-link:hover span,
        .cat-head-link:focus-visible span {
            transform: translateX(5px);
        }

@media (prefers-reduced-motion: reduce) {
    .cat-head-link span,
    .cat-head-link:hover span,
    .cat-head-link:focus-visible span {
        transition: none;
        transform: none;
    }
}
/* #endregion */
