html {
    font-family: var(--custom-font), var(--fallback-font);
    /* Anti-Aliasing / Sleek Fonts */
    font-synthesis: none;
    -moz-font-feature-settings: "kern";
    font-feature-settings: "kern";
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;

    font-size: 20px;

    /* Prevent horizontal scrolling (also prevents issues with tunnel proxies injecting content) */
    overflow-x: hidden;
}

* {
    line-height: 1.675;
    font-variant-emoji: text;
}

body {
    margin: 1rem 6%;
    background: var(--site-color-bg);
    color: var(--site-color-text);
    color-scheme: light;
}

body[color-scheme="dark"] {
    color-scheme: dark;
}

/* Animation-led pages place the glass navigation over the canvas so the
   visual begins at the physical top of the page. While the language-mismatch
   banner is visible (see localePreference.js, which zeroes the custom
   property back out once the banner scroll-hides), it pushes the nav down
   by its own height so the two never overlap.
   --sticky-offset-extra reports that push separately from the base 1rem
   inset: the navigation menu's own tiny-mode scroll detection (see
   visual-states.js) needs to tell "how far the nav sits from the true top
   of the page" apart from "how much of that is banner accommodation" -
   otherwise, whenever the banner inflates `top` past the sentinel's own
   resting position, the sentinel can never be detected as "back at the top"
   again and the menu gets stuck in tiny mode. */
body[layout="immersive"] > navigation-menu#main-navigation {
    position: fixed;
    inset-inline: 6%;
    --sticky-offset-extra: var(--language-mismatch-banner-height, 0px);
    top: calc(1rem + var(--sticky-offset-extra));
}

/* Opt an element out of its centered content column and into the viewport. */
[full-viewport-width] {
    box-sizing: border-box;
    width: 100vw;
    max-width: none;
    margin-inline: calc(50% - 50vw);
}

/* Keep content aligned to the site rail inside an edge-to-edge surface. */
[full-viewport-width][content-aligned] {
    padding-inline: var(--site-content-viewport-inset);
}

@supports (width: 100dvw) {
    [full-viewport-width] {
        width: 100dvw;
        margin-inline: calc(50% - 50dvw);
    }
}

/* Hand `<card-gallery>` back the two properties style-reset.css takes off its
   slides. The component styles every slide as a padded card whose content
   settles into the bottom-left corner, but those defaults reach the slide
   through `::slotted()` in its shadow tree — and a normal declaration in this,
   the outer tree, beats one from an inner tree whatever the specificity. So
   the reset's `padding: 0`, and its `display: block` for figure/section/
   article, would silently flatten every gallery card. The rest of what the
   component sets through `::slotted()` survives, the reset being silent on it.
   A page can still override either per gallery — its own selectors outrank
   this one. An inline `<style>` is skipped: `withInjection` copies it into the
   shadow root but leaves the original in place, and it must stay unrendered. */
card-gallery > *:not(style) {
    display: flex;
    padding: var(--card-gallery-card-padding);
}

.language-mismatch-banner {
    box-sizing: border-box;
    position: relative;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: end;

    gap: 0.75rem 1rem;
    padding: 0.875rem 3rem 0.875rem 1rem;
    /* Same gap as BANNER_NAV_GAP in localePreference.js - on immersive pages
       that constant drives it instead (this margin is a no-op there, since
       the banner is taken out of flow by position:fixed). */
    margin-bottom: 16px;
    color: var(--site-color-row-text);
    font-size: 0.95rem;

    /* Same frosted-glass treatment as the nav, on every page. */
    background: var(--site-surface-glass);
    -webkit-backdrop-filter: var(--site-backdrop-blur-strong);
    backdrop-filter: var(--site-backdrop-blur-strong);
    box-shadow: var(--site-shadow-glass);
    border-radius: var(--site-radius-panel);
}

/* On animation-led pages the banner floats fixed above the hero and stays
   out of flow so the hero (via its "header" wrapper) still starts at the
   physical top of the page. The hero establishes its own stacking context
   (isolation: isolate) with z-index:auto, so any explicit z-index here is
   enough to render in front of it regardless of DOM order - nothing close
   to the nav's is needed since the nav is pushed down (see the rule above)
   and the two no longer overlap. */
body[layout="immersive"] > .language-mismatch-banner {
    position: fixed;
    top: 1rem;
    inset-inline: 6%;
    z-index: 1;
}

/* Hidden while scrolled past a small threshold, reappearing at the top of the
   page. The movement itself is no longer done here: the prompt service plays
   its own show/dismiss animation in reverse for this, through the Web
   Animations API with fill: forwards, and eases the nav-offset property
   alongside it so the navigation travels with the banner rather than after it.
   Setting "top" or "filter" here would fight that persisted animation effect,
   so this rule now only stops a hidden banner from taking pointer input. */
body[layout="immersive"] > .language-mismatch-banner[data-scroll-hidden] {
    pointer-events: none;
}

.language-mismatch-banner__label {
    margin-right: auto;
    line-height: 1;
    margin-left: 1rem;
}

.language-mismatch-banner__actions {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    min-width: 0;
}

.language-mismatch-banner__select {
    width: clamp(9rem, 20vw, 14rem);
    min-width: 0;
    min-height: 2.35rem;
    padding: 0.45rem 0.75rem;
    border: 1px solid var(--site-color-field-border);
    border-radius: var(--site-radius-control);
    background: var(--site-color-field-bg);
    color: var(--site-color-field-text);
    font: inherit;
    line-height: 1.2;
}

.language-mismatch-banner__continue {
    flex: none;
    white-space: nowrap;
}

.language-mismatch-banner__dismiss {
    position: absolute;
    top: 50%;
    right: 0.65rem;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    border: 1px solid transparent;
    border-radius: var(--site-radius-control);
    background: transparent;
    color: var(--site-color-row-text);
    font: inherit;
    font-weight: 700;
    line-height: 1;
}

main,
header {
    box-sizing: border-box;
    margin: 3rem auto;
    max-width: var(--site-content-max);
    padding-inline: var(--site-content-gutter);
}

/* For width like iPhone SE */
@media (max-width: 768px) {

    main,
    header {
        margin: 1rem;
        padding-inline: var(--site-content-gutter);
    }
}

header {
    font-weight: 900;
    font-size: 2em;
}

main {
    min-height: 85vh;
}

/* header:not(#home){
    text-transform: uppercase;
} */

/* 
Case: about.html header and info.html header has no text content until page is switched, when header is added only for context in page transition. 
Opacity is used in page switch animation so opacity: 0; won't work in transition declaration for opacity, therefore using filter: opacity.
*/
header {
    filter: opacity(1);
    transition: filter 0.2s linear;
}

header:empty {
    filter: opacity(0);
}

/*
A header wrapping a real visual component (not just a short page-title label)
gets a calm, content-appropriate reset instead of the bold placeholder-label
styling above. This is opt-in simply by giving the header an element child -
no page-specific class or body attribute required.
*/
header:has(> *) {
    margin-block: 1rem;
    padding: 0;
    font-size: 1rem;
    font-weight: 400;
}

body[layout="immersive"] > header:has(> *) {
    margin-block-start: -1rem;
}

/* The analytics preference strip wears the site's own surface and control
   styling rather than a private one: the navigation's frosted glass for the
   panel (see .language-mismatch-banner above, which does the same) and the
   shared [visual-mode="button"] contract for its choices, so Allow and
   Discard are the same control the rest of the site uses. */
section[analytics-preference] {
    position: fixed;
    inset-inline: clamp(.5rem, 2vw, 1.5rem);
    /* Clear of the sticky audio player rather than over it. The offset is
       republished from the player's rendered geometry (analyticsPreference.js),
       so it follows the player between its full-size and compact states. */
    --analytics-bottom-inset: calc(max(.5rem, env(safe-area-inset-bottom)) + var(--analytics-player-offset, 0px) + var(--analytics-player-gap, 0px));
    /* What the chrome above occupies: the navigation's 1rem top inset and its
       5rem box, a gap below it, and the language banner's height on top of all
       of it - the banner pushes the navigation down by exactly this property
       (see the immersive nav rule above), and it is published on the root for
       as long as the banner is up. The navigation's own height is an allowance
       rather than a measurement, which is all a cap needs: it comes into play
       only on a viewport too short to seat both surfaces, and a notice that
       ends up clipped by it yields to its bubble (analyticsPreference.js). */
    --analytics-headroom: calc(6.75rem + var(--language-mismatch-banner-height, 0px));
    bottom: var(--analytics-bottom-inset);
    /* Behind the audio player (100) and the navigation (max), above ordinary
       page content. Not a negative value: that would drop it behind the page
       background and take its controls out of reach. */
    z-index: 50;
    display: flex;
    /* The text and the choices share a row only while both actually fit: the
       row wraps on its own once the wording needs more than its basis, so the
       shape follows the content rather than a width breakpoint. Without this
       the text column was squeezed to a one-word ribbon whenever the viewport
       was too narrow to seat both. */
    flex-wrap: wrap;
    align-items: center;
    gap: .75rem 1.5rem;
    box-sizing: border-box;
    height: auto;
    /* Never taller than the room between that chrome and the player: grown
       past it the notice would be drawn under the navigation's glass, which is
       above it in the stack, and its title would be the part that disappears.
       The floor keeps a clamped notice legible on a landscape phone, where it
       scrolls the last line or two rather than losing them. */
    max-height: max(5rem, calc(100dvh - var(--analytics-headroom) - var(--analytics-bottom-inset)));
    overflow-y: auto;
    margin: 0;
    padding: .875rem 2.25rem;
    color: var(--site-color-row-text);
    text-align: start;

    /* Same frosted-glass treatment as the nav and the language prompt. */
    background: var(--site-surface-glass);
    -webkit-backdrop-filter: var(--site-backdrop-blur-strong);
    backdrop-filter: var(--site-backdrop-blur-strong);
    box-shadow: var(--site-shadow-glass);
    border-radius: var(--site-radius-panel);
}
/* A reading measure, not a column that stretches across a desktop: the text
   grows to 26rem, stops at a comfortable line length, and never shrinks below
   the width at which its words break apart - narrower than that, the row wraps
   and the text gets the whole line instead. */
section[analytics-preference] > div:first-child { flex: 1 1 26rem; min-width: min(100%, 14rem); max-width: 60ch; }
section[analytics-preference] h2 { margin: 0; font-size: 1rem; line-height: 1.3; }
section[analytics-preference] p { margin: .2rem 0 0; font-size: .78rem; line-height: 1.45; }
/* The answer is acknowledged on the control that was pressed - green for allow,
   red for discard - and held for a beat before the panel leaves, so the colour
   is read as a reply rather than a flicker. The transition restates the shared
   control's own list, since replacing the shorthand would otherwise drop it.
   An answered panel stops taking input while it departs. */
section[analytics-preference] [visual-mode="button"] {
    transition: box-shadow 0.375s ease, transform 0.1s ease, border 0.5s ease,
        background-color 0.2s ease, color 0.2s ease;
}
section[analytics-preference] [visual-mode="button"][answered] { color: var(--site-color-text-inverse); }
section[analytics-preference] [visual-mode="button"][answered="accepted"] { background-color: var(--site-color-success); }
section[analytics-preference] [visual-mode="button"][answered="discarded"] { background-color: var(--site-color-error); }
section[analytics-preference][answering] { pointer-events: none; }

/* The details link is introduced by its own wording ("See ...") rather than a
   rule under the text, which competes with the panel's edges on this busy,
   semi-transparent surface. The underline returns on hover so the link is still
   recognisable as one. */
section[analytics-preference] a { color: inherit; text-decoration: none; }
section[analytics-preference] a:hover { text-decoration: underline; }
/* The shared action row goes full-width below 768px, which inside this strip
   would claim the whole line and crush the text beside it; here it is only ever
   as wide as its line allows. It keeps to the end of a shared row and fills a
   line of its own once the row has wrapped. */
section[analytics-preference] [page-list-actions] {
    flex: 1 1 auto;
    width: auto;
    justify-content: flex-end;
}
/* The shared control leaves its focus ring commented out, and this strip floats
   over arbitrary page content, so it keeps its own visible one. */
section[analytics-preference] :focus-visible { outline: 2px solid currentColor; outline-offset: 3px; }

/* --- Collapsed bubble -----------------------------------------------------
   Scrolling collapses the strip to a bubble in the bottom corner, keeping the
   same panel surface and the same player offset; activating it expands the
   strip again. Only the strip's own box changes - nothing is remounted. */
/* The box itself is morphed between the two shapes by a FLIP animation in
   analyticsPreference.js; what the stylesheet owns is the cross-fade of the
   two sets of contents and the clipping that keeps the panel's text inside the
   shrinking box. Visibility (not display) does the hiding, so the fade has
   something to animate while the hidden half still leaves the accessibility
   tree and the tab order. */
section[analytics-preference] > div {
    transition: opacity .22s ease .06s, visibility 0s;
}
section[analytics-preference] > [analytics-preference-bubble] {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 0;
    border-radius: 50%;
    color: inherit;
    background: none;
    cursor: pointer;
    opacity: 0;
    visibility: hidden;
    transition: opacity .14s ease, visibility 0s linear .14s;
}
section[analytics-preference][collapsed] {
    inset-inline: auto clamp(.5rem, 2vw, 1.5rem);
    width: 3rem;
    height: 3rem;
    padding: 0;
    overflow: clip;
    border-radius: 50%;
    justify-content: center;
}
section[analytics-preference][collapsed] > div {
    opacity: 0;
    visibility: hidden;
    transition: opacity .12s ease, visibility 0s linear .12s;
}
section[analytics-preference][collapsed] > [analytics-preference-bubble] {
    opacity: 1;
    visibility: visible;
    transition: opacity .2s ease .08s, visibility 0s;
}
section[analytics-preference] > [analytics-preference-bubble] > svg {
    width: 1.5rem;
    height: 1.5rem;
    fill: currentColor;
}
/* Below this the strip has long since wrapped into two lines by itself; what
   the query still owns is the phone's tighter frame and label size. */
@media (max-width: 680px) {
    section[analytics-preference] { padding-inline: 1rem; border-radius: var(--site-radius-area); }
    section[analytics-preference][collapsed] { padding: 0; border-radius: 50%; }
    /* The choices share one row on a phone. A wrapped action row is what makes
       this strip grow tallest, so the control's label is allowed to sit smaller
       here - its height, shape and shadow stay the shared ones. */
    section[analytics-preference] [page-list-actions] { flex-wrap: nowrap; flex-shrink: 1; }
    section[analytics-preference] [visual-mode="button"] {
        flex: 1 1 0;
        min-width: 0;
        justify-content: center;
        text-align: center;
        padding-inline: .5rem;
        font-size: .8rem;
    }
}

/* On the narrowest phones the German labels no longer fit three-across at the
   size above; the label shrinks once more rather than wrapping onto a second
   line and doubling the row's height. */
@media (max-width: 360px) {
    section[analytics-preference] [visual-mode="button"] { padding-inline: .35rem; font-size: .7rem; }
}

/* A landscape phone is the one shape where height, not width, is what runs
   out: the navigation, the notice and the player all want the same 400-odd
   pixels. The text settles for a shorter line so it keeps the row it shares
   with the choices - two lines of notice instead of three - and the panel
   breathes a little less. Nothing is dropped; the wording and the link to the
   privacy section read the same. */
@media (max-height: 560px) and (min-width: 520px) {
    section[analytics-preference] { padding-block: .625rem; }
    section[analytics-preference] > div:first-child { flex-basis: 18rem; }
}
site-footer {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.4rem;
    margin-top: 1em;
    padding-block: 1.5rem;
}

site-footer>div {
    display: flex;
    gap: 1rem;
}

site-footer a {
    color: inherit;
    opacity: 0.5;
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    transition: opacity 0.2s ease;
}

site-footer a:hover {
    opacity: 0.85;
}

site-footer p {
    margin: 0;
    font-size: 0.65rem;
    opacity: 0.35;
    letter-spacing: 0.03em;
}

section {
    text-align: justify;
    margin-bottom: 2rem;
}

#call-synaikido {
    box-sizing: border-box;
    display: grid;
    gap: 1rem;
    max-width: 600px;
    margin-top: 2.5rem;
    padding: clamp(1rem, 3vw, 1.5rem);
    border: 1px solid var(--site-color-row-border);
    border-radius: var(--site-radius-area);
    background: var(--site-color-row-bg);
    color: var(--site-color-row-text);
    text-align: left;
}

#call-synaikido > h3 {
    margin: 0;
    text-wrap: balance;
}

#call-synaikido > a {
    justify-self: start;
    padding-inline: 0.75rem;
    font-size: 0.85rem;
}

#call-synaikido svg {
    flex-shrink: 0;
}

@media (max-width: 360px) {
    #call-synaikido > a {
        flex-direction: column;
        width: 100%;
        padding-inline: 0.5rem;
        font-size: 0.75rem;
    }
}

b {
    font-weight: 900;
}

strong {
    font-weight: 600;
}

h-thin {
    font-weight: 600;
}

blockquote,
p,
h1,
h2,
h3,
h4,
h5,
h6,
ul,
ol {
    margin-bottom: 1rem;
}

h1,
h2,
h3,
h4,
h5,
h6 {
    font-weight: 900;
    text-align: left;
}

h1 {
    font-size: 2em;
}

h2,
blockquote {
    font-size: 1.5em;
}

h3 {
    font-size: 1.25em;
}

h4 {
    font-size: 1.125em;
}

blockquote {
    font-weight: 600;
}

blockquote strong {
    font-weight: 900;
}

span[type="icon"] {
    margin-right: 0.5rem;
}

ul {
    list-style: none;
    padding-left: 0;
}

ul>li::before {
    content: "\2714";
    margin-right: 0.5rem;
    margin-left: 1em;
}

select,
input,
textarea {
    all: initial;
    appearance: none;
    border-radius: 1.5em;
    padding: 0.5rem 1rem;
    font-size: 1rem;
    line-height: 1.35;
}

input[type="checkbox"] {
    display: inline-grid;
    place-content: center;
    flex-shrink: 0;
    width: 1.05rem;
    height: 1.05rem;
    min-width: 1.05rem;
    min-height: 1.05rem;
    margin: 0 0.35rem 0 0;
    padding: 0;
    border: var(--site-button-border);
    border-radius: 0.35rem;
    box-sizing: border-box;
    background-color: rgba(255, 255, 255, 0.05);
    color: var(--site-color-field-text);
    box-shadow: var(--site-shadow-control);
    cursor: pointer;
    vertical-align: middle;
    transition: background-color 0.2s ease, border-color 0.2s ease, box-shadow 0.375s ease;
}

input[type="checkbox"]::before {
    content: "";
    width: 0.2rem;
    height: 0.5rem;
    margin-top: -0.1rem;
    border: solid currentColor;
    border-width: 0 0.14rem 0.14rem 0;
    opacity: 0;
    transform: rotate(45deg) scale(0.75);
    transform-origin: center;
    transition: opacity 0.16s ease, transform 0.16s ease;
}

input[type="checkbox"]:checked {
    border-color: var(--site-color-field-border);
    background-color: var(--site-color-field-bg);
}

input[type="checkbox"]:checked::before {
    opacity: 1;
    transform: rotate(45deg) scale(1);
}

input[type="checkbox"]:hover {
    box-shadow: var(--site-shadow-control-hover);
}

input[type="checkbox"]:disabled {
    opacity: 0.45;
    cursor: not-allowed;
}

input:focus,
select:focus,
textarea:focus {
    border-color: var(--site-color-focus);
}

input:focus-visible,
select:focus-visible,
textarea:focus-visible {
    outline: 2px solid rgba(0, 0, 0, 0.05);
    outline-offset: 0px;
}


.landing-kicker {
    display: inline-flex;
    align-items: center;
    gap: 0.55rem;
    margin: 0 0 0.9rem;
    color: var(--landing-muted);
    font-size: 0.78rem;
    font-weight: 800;
    line-height: 1.15;
    text-transform: uppercase;
}

.landing-kicker::before {
    content: "";
    width: 2.5rem;
    height: 2px;
    background: currentColor;
}

.landing-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    margin-top: 1.5rem;
}

.landing-actions a[visual-mode="button"] {
    text-decoration: none;
}

.landing-final .landing-actions a[visual-mode="button"] {
    border-color: #fff;
    background: #fff;
    color: #111;
    box-shadow: 0 0.85rem 2rem rgba(0, 0, 0, 0.28);
}

.landing-actions .landing-secondary,
.landing-final .landing-actions .landing-secondary {
    border-color: currentColor;
    background: transparent;
    color: inherit;
}

.landing-final .landing-actions .landing-secondary {
    border-color: rgba(255, 255, 255, 0.78);
    background: rgba(0, 0, 0, 0.34);
    color: #fff;
}

.landing-proof {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 1px;
    margin-top: -2rem;
    margin-bottom: clamp(3rem, 8vw, 5.5rem);
    border: 1px solid var(--landing-line);
    border-radius: 8px;
    overflow: hidden;
    background: var(--landing-line);
    box-shadow: var(--site-shadow-subtle);
}

.landing-proof p {
    margin: 0;
    padding: 1rem;
    background: var(--landing-panel);
    font-size: clamp(0.95rem, 1.8vw, 1.12rem);
    line-height: 1.35;
}

.landing-section {
    margin-bottom: clamp(3rem, 8vw, 6rem);
}

.landing-split {
    display: grid;
    grid-template-columns: minmax(0, 0.8fr) minmax(0, 1fr);
    gap: clamp(1.5rem, 5vw, 4rem);
    align-items: start;
}

.landing-split h2,
.landing-section__heading h2,
.landing-final h2 {
    max-width: 14ch;
    font-size: clamp(2rem, 5vw, 4.25rem);
    line-height: 0.98;
}

.landing-copy {
    max-width: 40rem;
    color: var(--landing-muted);
    font-size: 1.05rem;
}

.landing-section__heading {
    display: grid;
    grid-template-columns: minmax(0, 0.72fr) minmax(0, 1fr);
    gap: 1.5rem;
    align-items: end;
    margin-bottom: 1.4rem;
}

.landing-section__intro {
    display: flex;
    min-width: 0;
    flex-direction: column;
    align-items: flex-start;
}

.landing-emblem {
    display: block;
    width: clamp(6.25rem, 10vw, 8rem);
    aspect-ratio: 1;
    margin-top: clamp(1.25rem, 3vw, 2rem);
    opacity: 0.9;
    pointer-events: none;
}

.landing-split>div:first-child .landing-emblem {
    margin-right: clamp(0rem, 4vw, 3rem);
    margin-left: auto;
}

.landing-section__intro .landing-emblem {
    margin-left: clamp(0rem, 4vw, 3rem);
}

.landing-service-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 1rem;
}

.landing-card {
    position: relative;
    min-height: 22rem;
    padding: 1.15rem;
    border: 1px solid var(--landing-line);
    border-radius: 8px;
    overflow: hidden;
    background: #111;
    color: #fff;
    text-decoration: none;
    box-shadow: var(--site-shadow-subtle);
    transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.landing-card:hover {
    transform: translateY(-0.18rem);
    box-shadow: var(--site-shadow-elevated);
}

.landing-card::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    background:
        linear-gradient(180deg, rgba(0, 0, 0, 0.08), rgba(0, 0, 0, 0.9)),
        var(--landing-card-image);
    background-position: var(--landing-card-position, center);
    background-size: cover;
    transition: transform 0.4s ease;
}

.landing-card:hover::before {
    transform: scale(1.04);
}

.landing-card--mixing {
    --landing-card-image: url("/Assets/Images/studio/studio-warm-angle.webp");
    --landing-card-position: 58% center;
}

.landing-card--mastering {
    --landing-card-image: url("/Assets/Images/studio/studio-cool.webp");
    --landing-card-position: 58% center;
}

.landing-card--sounddesign {
    --landing-card-image: url("/Assets/Images/studio/studio-space.webp");
    --landing-card-position: 52% center;
}

.landing-card>* {
    position: relative;
    z-index: 1;
}

.landing-card span {
    display: block;
    margin-bottom: 8rem;
    color: rgba(255, 255, 255, 0.66);
    font-size: 0.78rem;
    font-weight: 800;
}

.landing-card h3 {
    margin-bottom: 0.55rem;
    font-size: clamp(1.35rem, 3vw, 2rem);
    line-height: 1;
}

.landing-card p {
    color: rgba(255, 255, 255, 0.8);
    line-height: 1.35;
}

.landing-card strong {
    display: inline-block;
    margin-top: 0.5rem;
    color: #fff;
    font-weight: 900;
}

.landing-studio {
    display: grid;
    grid-template-columns: minmax(0, 1.12fr) minmax(0, 0.88fr);
    gap: clamp(1.5rem, 5vw, 4rem);
    align-items: center;
}

.landing-studio picture,
.landing-studio img {
    display: block;
    width: 100%;
}

.landing-studio img {
    aspect-ratio: 16 / 11;
    border-radius: 8px;
    object-fit: cover;
    box-shadow: 0 1rem 2rem rgba(0, 0, 0, 0.14);
}

.landing-studio__copy {
    max-width: 42rem;
}

.landing-studio__copy h2 {
    font-size: clamp(2rem, 5vw, 4rem);
    line-height: 1;
}

.landing-checklist,
.landing-process {
    padding: 0;
    list-style: none;
}

.landing-checklist {
    display: grid;
    gap: 0.65rem;
    margin-top: 1.2rem;
}

.landing-checklist li {
    padding: 0.8rem 0.9rem;
    border-left: 3px solid var(--site-color-index-mark-2);
    background: var(--landing-soft);
    border-radius: 0 8px 8px 0;
}

.landing-process {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 1rem;
    counter-reset: landing-process;
}

.landing-process li {
    position: relative;
    counter-increment: landing-process;
    min-height: 10.5rem;
    padding: 1.15rem 3.2rem 1.15rem 1.15rem;
    border: 1px solid var(--landing-line);
    border-radius: 8px;
    background: var(--landing-panel);
    box-shadow: var(--site-shadow-subtle);
}

.landing-process li::after {
    content: "0" counter(landing-process);
    position: absolute;
    top: 1.15rem;
    right: 1.15rem;
    color: var(--landing-muted);
    font-size: 0.8rem;
    font-weight: 800;
}

.landing-process span {
    display: block;
    margin-bottom: 0.5rem;
    font-size: 1.45rem;
    font-weight: 900;
    line-height: 1.05;
}

.landing-process p {
    color: var(--landing-muted);
    line-height: 1.35;
}

.landing-final {
    position: relative;
    isolation: isolate;
    padding: clamp(2rem, 6vw, 4rem) 0;
    color: #fff;
}

.landing-final::before {
    content: "";
    position: absolute;
    z-index: -1;
    inset: 0 50%;
    width: 100vw;
    margin-left: -50vw;
    background:
        linear-gradient(90deg, rgba(0, 0, 0, 0.88), rgba(0, 0, 0, 0.42)),
        url("/Assets/Images/optimized/personal-1280.webp");
    background-position: center;
    background-size: cover;
}

.landing-final .landing-kicker,
.landing-final p {
    color: rgba(255, 255, 255, 0.82);
}

.landing-final p:not(.landing-kicker) {
    max-width: 35rem;
    font-size: 1.1rem;
}

text-highlight {
    border: 1px solid var(--site-color-highlight-border);
    background: linear-gradient(171deg,
            var(--site-color-highlight-grad-1) 0%,
            var(--site-color-highlight-grad-2) 44%,
            var(--site-color-highlight-grad-3) 100%);
    padding: 0.125em 0.375em;
    border-radius: 1em;

    /* Force standard rendering of ↔ on iOS. Otherwise it replaces it with an emoji arrow. */
    font-family: var(--custom-font), var(--system-fonts), var(--fallback-font);
    font-variant-emoji: text;
}

@media (max-width: 900px) {
    .landing-proof,
    .landing-split,
    .landing-section__heading,
    .landing-service-grid,
    .landing-studio {
        grid-template-columns: 1fr;
    }

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

    .landing-proof {
        margin-top: -1.5rem;
    }

    .landing-card {
        min-height: 16rem;
    }

    .landing-card span {
        margin-bottom: 5rem;
    }

    .landing-split>div:first-child .landing-emblem,
    .landing-section__intro .landing-emblem {
        margin-left: 0;
    }
}

@media (max-width: 520px) {
    .landing-actions {
        display: grid;
        grid-template-columns: 1fr;
    }

    .landing-actions a[visual-mode="button"] {
        width: 100%;
    }

    .landing-proof p,
    .landing-process li {
        padding: 0.9rem;
    }

    .landing-process {
        grid-template-columns: 1fr;
        gap: 0.7rem;
    }

    .landing-process li {
        min-height: auto;
        padding-right: 3rem;
    }

    .landing-process li::after {
        top: 0.9rem;
        right: 0.9rem;
    }

    .landing-studio img {
        aspect-ratio: 16 / 11;
    }

    .landing-emblem {
        width: 5.75rem;
    }
}

/* ─── Shared Page Body Controls ─────────────────────────────────────
   Base styling for reusable page-body UI primitives. Page stylesheets may add
   local layout or density adaptations, but these plain tags/attributes define
   the common button, field, status, verification, and row treatment. */

[page-action] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.45rem;
    max-width: 100%;
    min-height: 2.35rem;
    padding: 0.55rem 1.1rem;
    font: inherit;
    font-size: 0.95rem;
    font-weight: 600;
    line-height: 1.2;
    text-align: center;
    text-decoration: none;
    overflow-wrap: anywhere;
    cursor: pointer;
}

[page-action][disabled],
[page-action][aria-disabled="true"] {
    opacity: 0.45;
    cursor: not-allowed;
    pointer-events: none;
}

/* The link handler's Continue prompt (SPAgify continuePrompt.js) renders a
   plain <button>; it takes the shared control as it is. The module's own
   button defaults carry no specificity, so these apply although its stylesheet
   loads later. */
[visual-mode="button"],
spa-continue-prompt > button {
    all: initial;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.45rem;
    max-width: 100%;
    min-height: 2.35rem;
    padding: 0.55rem 1.25rem;
    border-radius: var(--site-radius-control);
    color: inherit;
    font: inherit;
    font-size: 0.95rem;
    font-weight: 600;
    line-height: 1.2;
    text-align: left;
    text-decoration: none;
    overflow-wrap: anywhere;
    /* cursor: pointer; */
    cursor: default;
    background-color: rgba(255, 255, 255, 0.05);

    box-sizing: border-box;

    transition: box-shadow 0.375s ease, transform 0.1s ease, border 0.5s ease;

    border: var(--site-button-border);

    /* Comic */
    /* box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.06) inset, 0px 0px 2px rgba(0, 0, 0, 0.5); */

    /* Smooth */
    box-shadow: var(--site-shadow-control);
    /* box-shadow: 0px 5px 10px rgba(0, 0, 0, 0.02) inset, 0px -5px 10px rgba(0, 0, 0, 0.02) inset, 0px 0px 2px rgba(0, 0, 0, 0.2); */

    /* Aqua */
    /* background-color: rgba(0,0,0,0.1);
    box-shadow: 0px -2px 20px rgba(255, 255, 255, 0.4) inset, 0px 2px 20px rgba(255, 255, 255, 0.4) inset, 0px -12px 10px rgba(255, 255, 255, 0.5) inset, 0px 12px 10px rgba(255, 255, 255, 0.5) inset, 0px 0px 2px rgba(0, 0, 0, 0.2); */
}

[visual-mode="button"]:hover,
spa-continue-prompt > button:hover {
    /* Comic */
    /* box-shadow: 0px 0px 0.5rem rgba(0, 0, 0, 0.06) inset, 0px 0px 6px rgba(0, 0, 0, 0.2); */
    /* box-shadow: 0px 0px 0.5rem rgba(0, 0, 0, 0.06) inset, 0px 0px 6px rgba(0, 0, 0, 0.1); */
    /* box-shadow: 0px 0px 0.5rem rgba(0, 0, 0, 0.06) inset, 0px 0px 4px rgba(0, 0, 0, 0.5); */
    /* box-shadow: 0px 0px 0.5rem rgba(0, 0, 0, 0.06) inset, 0px 0px 3px rgba(0, 0, 0, 0.5); */
    /* box-shadow: 0px 0px 0.5rem rgba(0, 0, 0, 0.06) inset, 0px 0px 2px rgba(0, 0, 0, 0.8); */

    /* Smooth */
    box-shadow: var(--site-shadow-control-hover);


    /* Aqua */
    /* box-shadow: 0px -2px 20px rgba(255, 255, 255, 0.8) inset, 0px 2px 20px rgba(255, 255, 255, 0.8) inset, 0px -12px 10px rgba(255, 255, 255, 0.2) inset, 0px 12px 10px rgba(255, 255, 255, 0.2) inset, 0px 0px 4px rgba(0, 0, 0, 0.2); */
}

[visual-mode="button"]:active,
spa-continue-prompt > button:active {
    box-shadow: var(--site-shadow-control-active);
    transform: scale(0.99);
}

/* [visual-mode="button"]:focus-visible {
    outline: 2px solid var(--site-color-button-border);
    outline-offset: 2px;
} */

[visual-mode="button"][disabled],
[visual-mode="button"][aria-disabled="true"] {
    opacity: 0.45;
    cursor: not-allowed;
    pointer-events: none;
}

/* The shared control sets display: flex, which outranks the UA's
   [hidden] { display: none } - so `element.hidden = true` left the control on
   screen (e.g. the settings page's "revoke all other sessions" action, which is
   meant to disappear when there are no other sessions). */
[visual-mode="button"][hidden] {
    display: none;
}

/* Primary/destructive action variants: a color layer only, added on top of
   the shared control above - its shape, radius, border, and box-shadow are
   untouched. The ::after sits inside the padding box (inset: 0 on a
   position: relative + z-index: 0 host, i.e. its own stacking context) so it
   paints above the host's own background but below its border and label
   text/icons. Concrete tint/text values are supplied per-surface
   (admin.css/profile.css --site-color-action-*) so a surface that doesn't
   define them (e.g. marketing pages) renders no tint at all. */
[visual-mode="button"][page-action="primary"],
[visual-mode="button"][page-action="destructive"],
[visual-mode="button"][page-action="facebook"],
[visual-mode="button"][page-action="google"] {
    position: relative;
    z-index: 0;
}

[visual-mode="button"][page-action="primary"]::after,
[visual-mode="button"][page-action="destructive"]::after,
[visual-mode="button"][page-action="facebook"]::after,
[visual-mode="button"][page-action="google"]::after {
    content: "";
    position: absolute;
    inset: -1px;
    z-index: -1;
    border-radius: inherit;
    pointer-events: none;
}

[visual-mode="button"][page-action="primary"]::after {
    background: var(--site-color-action-primary-tint, transparent);
}

[visual-mode="button"][page-action="destructive"]::after {
    background: var(--site-color-action-destructive-tint, transparent);
}

/* Provider brand cues, dialled a shade off the official hex values. Neither
   fills the button's face - each paints a colour ring: a background masked
   down to a thin band that traces the pill's outline (padding sets the ring
   width; the content-box/border-box mask pair cuts out everything but that
   band), with the ordinary button face and text still showing through the
   middle. Facebook's ring is one solid blue; Google's guidelines forbid a
   coloured/gradient fill behind the button, so its ring is a four-colour
   conic gradient instead of a flat tint. */
[visual-mode="button"][page-action="facebook"]::after,
[visual-mode="button"][page-action="google"]::after {
    padding: 3px;
    box-sizing: content-box;
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask-composite: exclude;
}

/* The generic [page-action] rule above sets text-align: center, but the
   later, equal-specificity [visual-mode="button"] rule sets text-align: left
   and wins on source order - harmless while the label never wraps, but
   worth pinning explicitly for these two. */
[visual-mode="button"][page-action="facebook"],
[visual-mode="button"][page-action="google"] {
    text-align: center;
}

[visual-mode="button"][page-action="facebook"]::after {
    background: var(--site-color-action-facebook-tint, transparent);
}

[visual-mode="button"][page-action="google"]::after {
    background: conic-gradient(from 0deg,
            var(--site-color-action-google-blue) 0deg 90deg,
            var(--site-color-action-google-red) 90deg 180deg,
            var(--site-color-action-google-yellow) 180deg 270deg,
            var(--site-color-action-google-green) 270deg 360deg);
}

[visual-mode="button"][page-action="primary"] {
    color: var(--site-color-action-primary-text, inherit);
}

[visual-mode="button"][page-action="destructive"] {
    color: var(--site-color-action-destructive-text, inherit);
}

textarea[visual-mode="button"] {
    border-radius: var(--site-radius-area);
    padding: 0.625rem 1rem;
}

page-field {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}

page-field[hidden] {
    display: none;
}

page-field>label,
page-field>span {
    font-size: 0.85rem;
    font-weight: 700;
}

/* The `all: initial` reset above discards each control's width, so a text or
   number input falls back to its intrinsic default size (~20 characters, i.e.
   a fixed 223px here) no matter how narrow its field is. In any multi-column
   form that made controls spill out of their grid cell and land on top of the
   neighbouring field. Size them to the field instead - min-width: 0 is what
   actually lets a grid/flex item shrink below its intrinsic minimum.
   Checkboxes and radios are excluded so they keep their own fixed box. */
page-field>:is(input:not([type="checkbox"]):not([type="radio"]), select, textarea),
[admin-field]>:is(input:not([type="checkbox"]):not([type="radio"]), select, textarea) {
    box-sizing: border-box;
    width: 100%;
    min-width: 0;
}

page-field textarea,
textarea[visual-mode="button"] {
    min-height: 6rem;
    resize: vertical;
}

page-dropzone {
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 2rem 1rem;
    border: 2px dashed var(--profile-color-info-border, var(--site-color-row-border));
    border-radius: var(--site-radius-area);
    background: transparent;
    color: var(--profile-color-info-text, var(--site-color-muted));
    text-align: center;
    transition: border-color 0.15s ease, background-color 0.15s ease;
}

page-dropzone[dragover] {
    border-color: var(--site-color-text);
    background: var(--profile-color-info-box-bg, var(--site-color-row-bg));
}

page-dropzone input[type="file"][hidden] {
    display: none !important;
}

page-hint {
    display: block;
    margin: 0.15rem 0 0;
    color: var(--site-color-muted);
    font-size: 0.8rem;
}

page-status {
    display: block;
    margin: 0;
    min-height: 1.1rem;
    color: var(--site-color-status);
    font-size: 0.85rem;
}

page-status[status="error"] {
    color: var(--site-color-error);
}

page-status[status="notice"] {
    color: var(--site-color-notice);
}

page-status[status="success"] {
    color: var(--site-color-success);
}

page-status[status="warning"] {
    color: var(--site-color-warning);
}

page-toast {
    position: fixed;
    left: 50%;
    bottom: 1.5rem;
    z-index: 1000;
    max-width: calc(100vw - 2rem);
    padding: 0.65rem 1.25rem;
    border-radius: var(--site-radius-pill);
    background: var(--site-color-banner-bg);
    color: var(--site-color-text-inverse);
    font-size: 0.9rem;
    text-align: center;
    box-shadow: var(--site-shadow-elevated);
    cursor: pointer;
    opacity: 0;
    pointer-events: none;
    transform: translate(-50%, 0.5rem);
    transition: opacity 0.2s ease, transform 0.2s ease;
}

page-toast[show] {
    opacity: 1;
    pointer-events: auto;
    transform: translate(-50%, 0);
}

page-toast[status="error"] {
    color: #ff8a80;
}

page-toast[status="success"] {
    color: #8fd694;
}

.page-verification {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    justify-content: flex-start;
    min-height: calc(65px + 1.35rem);
    margin: 0.25rem 0 0.75rem;
}

.turnstile-verification__mount {
    min-height: 65px;
}

.turnstile-verification__loading {
    min-height: 1rem;
    margin: 0.35rem 0 0;
    color: var(--site-color-muted);
    font-size: 0.85rem;
    line-height: 1rem;
}

turnstile-verification[hidden] {
    display: none;
}

page-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}

page-list>*::before,
page-list-row::before,
[page-list-row]::before {
    content: none;
    margin: 0;
}

page-list-row,
[page-list-row] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.75rem 0.9rem;
    border: 1px solid var(--site-color-row-border);
    border-radius: 8px;
    background: var(--site-color-row-bg);
    color: var(--site-color-row-text);
}

page-list-main,
[page-list-main] {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    flex-direction: column;
}

/* When the offer title gets very long, the "Chat" button wraps and shows Ch-at in two lines - hotfix, not pretty */
button[page-action="secondary"][page-action-size="compact"] {
    white-space: nowrap;
}

page-list-meta,
[page-list-meta] {
    display: block;
    margin-top: 0.15rem;
    color: var(--site-color-muted);
    font-size: 0.78rem;
}

page-list-actions,
[page-list-actions] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.45rem;
}

@media (max-width: 768px) {

    page-list-row,
    [page-list-row] {
        align-items: stretch;
        flex-direction: column;
    }

    page-list-actions,
    [page-list-actions] {
        justify-content: flex-start;
        width: 100%;
    }

    page-list-actions > [page-action],
    page-list-actions > [visual-mode="button"],
    [page-list-actions] > [page-action],
    [page-list-actions] > [visual-mode="button"] {
        flex: 1 1 9rem;
    }

    page-dropzone {
        padding: 1.35rem 0.75rem;
    }

    page-dropzone > button {
        width: 100%;
    }
}

/* Page reveal ---------------------------------------------------------------
   Scroll motion for the blocks directly under <main>; pageReveal.js sets the
   attributes, this file owns the look. Until the script runs, or with reduced
   motion, everything is simply visible.

   Statements (page-highlight, blockquote) fade up from nothing whenever they
   cross the middle of the viewport, and fade away again as they leave.

   Page chapters, sections and tails keep their heading in place; the rest of
   their content fades in as it scrolls into view, each element a beat after
   the one before (--page-reveal-delay, set per element by the script), and
   fades out again as it leaves. */
:root {
    --page-statement-duration: 720ms;
    --page-statement-easing: cubic-bezier(0.2, 0.75, 0.2, 1);
    --page-statement-rise: 1.5rem;
    --page-cascade-duration: 800ms;
    --page-cascade-easing: cubic-bezier(0.16, 1, 0.3, 1);
    --page-cascade-rise: 1rem;
}

main > :is(page-highlight, blockquote)[data-enhanced] {
    opacity: 0;
    transform: translateY(var(--page-statement-rise));
    transition:
        opacity var(--page-statement-duration) var(--page-statement-easing),
        transform var(--page-statement-duration) var(--page-statement-easing);
}

main > page-chapter[data-enhanced] > div > *,
main > :is(page-section, page-tail)[data-enhanced] > :not(h1, h2, h3) {
    opacity: 0;
    transform: translateY(var(--page-cascade-rise));
    transition:
        opacity var(--page-cascade-duration) var(--page-cascade-easing) var(--page-reveal-delay, 0ms),
        transform var(--page-cascade-duration) var(--page-cascade-easing) var(--page-reveal-delay, 0ms);
}

/* Keyboard focus never lands on something invisible. */
main > :is(page-highlight, blockquote)[data-enhanced]:is([data-visible], :focus-within),
main > page-chapter[data-enhanced] > div > :is([data-visible], :focus-within),
main > :is(page-section, page-tail)[data-enhanced] > :not(h1, h2, h3):is([data-visible], :focus-within) {
    opacity: 1;
    transform: none;
}

@media print, (prefers-reduced-motion: reduce) {
    main > :is(page-highlight, blockquote)[data-enhanced],
    main > page-chapter[data-enhanced] > div > *,
    main > :is(page-section, page-tail)[data-enhanced] > :not(h1, h2, h3) {
        opacity: 1;
        transform: none;
        transition: none;
    }
}
