/* =========================================================
   ExiomAI (Task 8, recoloured in Task 16, chat set inside
   the brain in Task 17)

   One family, Mona Sans, used across its width and weight:
   heavy and expanded for display, normal for reading. The
   palette is "signal fire" (Task 16.6, restored in 16.11):
   black, lit by blue (the mind), orange and amber (the
   energy) and ice only for what is live (the chain, pulses,
   the core, focus).

   Shared by templates/index.html and templates/usage.html.
   ========================================================= */

@font-face {
    font-family: "Mona Sans";
    font-style: normal;
    font-display: swap;
    font-weight: 200 900;
    font-stretch: 75% 125%;
    src: url("fonts/mona-sans-latin-wdth.woff2?v=5.3.0") format("woff2-variations"),
         url("fonts/mona-sans-latin-wdth.woff2?v=5.3.0") format("woff2");
}

/* Inter sets ExiomAI's answers only: the nearest free match
   to OpenAI Sans, the face of ChatGPT's answers. */

@font-face {
    font-family: "Inter";
    font-style: normal;
    font-display: swap;
    font-weight: 100 900;
    src: url("fonts/inter-latin-wght.woff2?v=5.2.5") format("woff2-variations"),
         url("fonts/inter-latin-wght.woff2?v=5.2.5") format("woff2");
}

/* Audiowide sets only the name on the landing, the nearest
   free match to the logo's wordmark (Task 16.13). */

@font-face {
    font-family: "Audiowide";
    font-style: normal;
    font-display: swap;
    font-weight: 400;
    src: url("fonts/audiowide-latin.woff2?v=22") format("woff2");
}

:root {
    --deep: #020409;
    --raised: #0B1322;
    --ink: #F3F6FC;
    --muted: #98A8C4;
    --blue: #3D8BFF;
    --orange: #FF7A1A;
    --amber: #FFB23F;
    --ice: #8FE6FF;
    --danger: #FF7B72;
    --on-hot: #1A0B00;

    --deep-rgb: 2, 4, 9;
    --ink-rgb: 243, 246, 252;
    --blue-rgb: 61, 139, 255;
    --orange-rgb: 255, 122, 26;
    --amber-rgb: 255, 178, 63;
    --ice-rgb: 143, 230, 255;
    --line: rgba(var(--blue-rgb), 0.16);
    --wash: rgba(var(--blue-rgb), 0.08);
    --glass: rgba(var(--ink-rgb), 0.06);
    --glass-edge: rgba(var(--ink-rgb), 0.12);

    --hot: linear-gradient(100deg, #FF5B14, var(--orange) 45%, var(--amber));
    --spring: cubic-bezier(0.34, 1.56, 0.64, 1);

    --font: "Mona Sans", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
    --gutter: clamp(16px, 4vw, 48px);
    --column: 46rem;

    color-scheme: dark;
}

*,
*::before,
*::after {
    box-sizing: border-box;
}

[hidden] {
    display: none !important;
}

html {
    -webkit-text-size-adjust: 100%;
}

body {
    margin: 0;
    min-height: 100vh;
    min-height: 100dvh;
    background: var(--deep);
    color: var(--ink);
    font-family: var(--font);
    font-size: 1rem;
    line-height: 1.6;
    font-feature-settings: "ss01", "kern";
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
}

button,
input,
textarea {
    font: inherit;
    color: inherit;
}

button {
    cursor: pointer;
}

a {
    color: var(--blue);
    text-underline-offset: 0.18em;
    text-decoration-thickness: 1px;
}

:focus-visible {
    outline: 2px solid var(--ice);
    outline-offset: 3px;
    border-radius: 6px;
}

::selection {
    background: rgba(var(--orange-rgb), 0.4);
}

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


/* ---------------------------------------------------------
   SHARED SHELL
   --------------------------------------------------------- */

.container {
    width: min(100% - 2 * var(--gutter), 64rem);
    margin-inline: auto;
}

.topbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    min-height: 72px;
    border-bottom: 1px solid var(--line);
}

.brand {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    margin: 0;
    font-size: 0.9375rem;
    font-weight: 600;
    font-stretch: 115%;
    letter-spacing: 0.01em;
    line-height: 1;
    white-space: nowrap;
}

.brand-mark {
    width: 30px;
    height: 30px;
    flex: none;
}

/* The chat's logo leads home to the intro (Task 9). Disabled
   when the intro can't run, it reads as plain text. */

.brand-button {
    display: inline-flex;
    align-items: center;
    gap: inherit;
    margin: -4px;
    padding: 4px;
    border: 0;
    border-radius: 999px;
    background: none;
    font: inherit;
    letter-spacing: inherit;
}

.brand-button .brand-mark {
    width: 36px;
    height: 36px;
}

/* The name beside the logo, set like the landing's title
   (Audiowide, the same flowing colours). */

.brand-name {
    font-family: "Audiowide", var(--font);
    font-size: 1.25rem;
    font-weight: 400;
    font-stretch: normal;
    letter-spacing: 0;
}

.brand-button:disabled {
    cursor: default;
}

.brand-mark {
    transition: filter 0.25s ease, transform 0.4s var(--spring);
}

.brand-button:enabled:hover .brand-mark {
    filter: drop-shadow(0 0 6px rgba(var(--blue-rgb), 0.8));
    transform: rotate(-12deg);
}

.chip {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 6px 12px;
    border: 1px solid var(--glass-edge);
    border-radius: 999px;
    background: var(--glass);
    -webkit-backdrop-filter: blur(12px);
    backdrop-filter: blur(12px);
    color: var(--ink);
    font-size: 0.8125rem;
    font-variant-numeric: tabular-nums;
    line-height: 1.2;
    text-decoration: none;
    white-space: nowrap;
    transition: border-color 0.2s ease;
}

a.chip:hover {
    border-color: rgba(var(--ice-rgb), 0.45);
}

.chip-dot,
.live-dot {
    width: 7px;
    height: 7px;
    flex: none;
    border-radius: 50%;
    background: var(--ice);
    box-shadow: 0 0 10px rgba(var(--ice-rgb), 0.8);
    animation: beat 2.4s ease-in-out infinite;
}

.chip.is-status {
    border-color: rgba(var(--ice-rgb), 0.5);
    background: rgba(var(--ice-rgb), 0.12);
    color: var(--ice);
}

.chip-dot {
    background: var(--orange);
    box-shadow: 0 0 10px rgba(var(--orange-rgb), 0.8);
}

.chip.is-offline {
    color: var(--muted);
}

.chip.is-offline .chip-dot {
    background: var(--muted);
    box-shadow: none;
    animation: none;
}

@keyframes beat {
    50% { opacity: 0.35; }
}



/* The start button: the page's main action, so the only
   thing that moves on its own besides the brain. A colour
   wheel turns behind it; the pointer lights it from where it
   is (--mx, --my, set by the script). */

@property --spin {
    syntax: "<angle>";
    inherits: false;
    initial-value: 0deg;
}

.button-primary {
    position: relative;
    isolation: isolate;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.8em;
    padding: 0.36em 0.36em 0.36em 1.3em;
    border: 0;
    border-radius: 999px;
    background: var(--hot);
    color: var(--on-hot);
    font-size: 1.5rem;
    font-size: max(1.25rem, calc(0.36 * var(--title-size)));
    font-weight: 800;
    font-stretch: 118%;
    letter-spacing: -0.01em;
    line-height: 1;
    box-shadow: 0 14px 44px -10px rgba(var(--orange-rgb), 0.7);
    transition: transform 0.45s var(--spring), box-shadow 0.3s ease;
}

.button-primary::before {
    content: "";
    position: absolute;
    inset: -4px;
    z-index: -1;
    border-radius: inherit;
    background: conic-gradient(
        from var(--spin),
        var(--orange), var(--amber), var(--ice), var(--blue), var(--orange)
    );
    filter: blur(16px);
    opacity: 0.7;
    animation: spin 5s linear infinite;
    transition: opacity 0.3s ease, inset 0.3s ease;
}

/* The face, with the pointer's light on it. Inside the
   button's own stacking context a negative layer paints over
   the button's background, so the face is a layer too, laid
   after the wheel; without it the wheel washes the face. */

@property --light {
    syntax: "<number>";
    inherits: false;
    initial-value: 0;
}

.button-primary::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: inherit;
    background:
        radial-gradient(
            120px circle at var(--mx, 50%) var(--my, 50%),
            rgba(255, 255, 255, var(--light)),
            transparent 70%
        ),
        var(--hot);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.5);
    transition: --light 0.25s ease;
    pointer-events: none;
}

.button-primary > * {
    position: relative;
    z-index: 1;
}

.button-primary:hover {
    transform: translateY(-2px) scale(1.03);
    box-shadow: 0 20px 60px -10px rgba(var(--orange-rgb), 0.9);
}

.button-primary:hover::before {
    inset: -8px;
    opacity: 1;
}

.button-primary:hover::after {
    --light: 0.35;
}

.button-primary:active {
    transform: scale(0.97);
    transition-duration: 0.1s;
}

.button-primary:focus-visible {
    outline-offset: 6px;
}

/* The opening you dive into, riding inside the button: a
   dark mouth with an amber lip and the core deep inside. */

.cta-core {
    display: grid;
    place-items: center;
    width: 2.1em;
    height: 2.1em;
    border-radius: 50%;
    background: radial-gradient(circle, #0E1A33, var(--on-hot) 70%);
    box-shadow:
        inset 0 0 0 2px rgba(var(--amber-rgb), 0.85),
        inset 0 0 10px 3px rgba(var(--orange-rgb), 0.55);
    transition: transform 0.45s var(--spring);
}

.cta-core::before {
    content: "";
    width: 0.4em;
    height: 0.4em;
    border-radius: 50%;
    background: var(--ice);
    box-shadow: 0 0 0 5px rgba(var(--ice-rgb), 0.18), 0 0 16px var(--ice);
    animation: beat 2.4s ease-in-out infinite;
}

.button-primary:hover .cta-core {
    transform: rotate(90deg) scale(1.08);
}

@keyframes spin {
    to { --spin: 360deg; }
}


/* ---------------------------------------------------------
   INTRO STAGE (Task 9)

   Visible from the first paint. The script marks it live
   (cancelling the fail-safe) or removes it. If the script
   never runs, the fail-safe fades it out so the chat is
   never stuck behind it.
   --------------------------------------------------------- */

.stage {
    position: fixed;
    inset: 0;
    z-index: 20;
    overflow: hidden;
    background:
        radial-gradient(50% 55% at 64% 47%, rgba(var(--blue-rgb), 0.24), transparent 70%),
        radial-gradient(45% 50% at 0% 100%, rgba(var(--orange-rgb), 0.16), transparent 70%),
        radial-gradient(40% 40% at 0% 0%, rgba(var(--blue-rgb), 0.1), transparent 70%),
        var(--deep);
    touch-action: none;
    animation: stage-failsafe 0.6s ease 8s forwards;
}

.stage.is-live {
    animation: none;
}

@keyframes stage-failsafe {
    to {
        opacity: 0;
        visibility: hidden;
    }
}

.stage-canvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
}

/* The network behind the brain (Task 16): a lattice of nodes
   drifting one cell diagonally and looping, with blocks of
   light running along its wires. Transform only, so it costs
   only the compositor; the mask keeps the copy's side quiet. */

.stage-field {
    --cell: 64px;
    position: absolute;
    inset: 0;
    overflow: hidden;
    pointer-events: none;
    -webkit-mask-image: radial-gradient(ellipse 80% 75% at 62% 47%, #000 25%, transparent 100%);
    mask-image: radial-gradient(ellipse 80% 75% at 62% 47%, #000 25%, transparent 100%);
}

.stage-grid {
    position: absolute;
    inset: calc(-1 * var(--cell)) calc(-1 * var(--cell)) 0 0;
    background:
        radial-gradient(circle, rgba(var(--ice-rgb), 0.5) 1px, transparent 1.8px) 0 0 / var(--cell) var(--cell),
        linear-gradient(rgba(var(--blue-rgb), 0.08) 1px, transparent 1px) 0 calc(var(--cell) / 2) / var(--cell) var(--cell),
        linear-gradient(90deg, rgba(var(--blue-rgb), 0.08) 1px, transparent 1px) calc(var(--cell) / 2) 0 / var(--cell) var(--cell);
    animation: lattice 16s linear infinite;
}

.stage-grid > i {
    position: absolute;
    top: calc(var(--row, 3) * var(--cell) + var(--cell) / 2);
    left: 0;
    width: 180px;
    height: 1px;
    background: linear-gradient(90deg, transparent, rgba(var(--orange-rgb), 0.9) 85%, var(--amber));
    box-shadow: 0 0 10px rgba(var(--orange-rgb), 0.7);
    animation: run-x var(--time, 9s) linear var(--delay, 0s) infinite;
}

.stage-grid > i:nth-child(1) { --row: 2; --time: 8s; --delay: -2s; }
.stage-grid > i:nth-child(2) { --row: 6; --time: 11s; --delay: -7s; }
.stage-grid > i:nth-child(3) { --row: 10; --time: 9s; --delay: -4s; }

/* The rest run down the columns. */

.stage-grid > i:nth-child(n + 4) {
    top: 0;
    left: calc(var(--col, 12) * var(--cell) + var(--cell) / 2);
    width: 1px;
    height: 150px;
    background: linear-gradient(transparent, rgba(var(--ice-rgb), 0.85) 85%, #FFFFFF);
    box-shadow: 0 0 10px rgba(var(--ice-rgb), 0.6);
    animation-name: run-y;
}

.stage-grid > i:nth-child(4) { --col: 9; --time: 10s; --delay: -1s; }
.stage-grid > i:nth-child(5) { --col: 15; --time: 7s; --delay: -5s; }
.stage-grid > i:nth-child(6) { --col: 19; --time: 12s; --delay: -9s; }

@keyframes lattice {
    to { transform: translate3d(var(--cell), var(--cell), 0); }
}

@keyframes run-x {
    from { transform: translateX(-180px); }
    to { transform: translateX(calc(100vw + 2 * var(--cell))); }
}

@keyframes run-y {
    from { transform: translateY(-150px); }
    to { transform: translateY(calc(100vh + 2 * var(--cell))); }
}

.stage-ui {
    --title-size: clamp(3.25rem, min(9vw, 14vh), 9.5rem);

    position: relative;
    z-index: 0;
    display: flex;
    flex-direction: column;
    height: 100%;
    padding:
        max(20px, env(safe-area-inset-top))
        var(--gutter)
        max(10px, env(safe-area-inset-bottom));
    pointer-events: none;
}

.stage-bar,
.stage-bar-end {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
}

.stage-bar-end {
    gap: 12px;
}

.stage-bar {
    justify-content: flex-end;
}

.stage-bar a,
.stage-actions,
.maker,
.stage-down,
.stage-foot a {
    pointer-events: auto;
}

/* Wide screens centre the copy beside the brain; narrow ones
   keep it under the brain, at the foot of the screen. */

.stage-hero {
    display: contents;
}

.stage-copy {
    max-width: min(46rem, 50vw);
    margin-block: auto;
}

.stage-title {
    position: relative;
    margin: 0 0 10px;
    font-size: var(--title-size);
    font-weight: 900;
    font-stretch: 125%;
    letter-spacing: -0.04em;
    line-height: 0.92;
}

.stage-title .line {
    display: block;
    overflow: hidden;
    padding-bottom: 0.06em;
}

.stage-title .line > span {
    display: block;
}

.stage-title .line:not(.line-small) {
    font-family: "Audiowide", var(--font);
    font-weight: 400;
    font-stretch: normal;
    letter-spacing: 0;
}

.stage-title .line-small {
    margin-bottom: 0.08em;
    font-size: 0.34em;
    font-weight: 600;
    font-stretch: 112%;
    letter-spacing: -0.01em;
}

/* The logo, without its name, floats over the "m" (16.16).
   The name's line clips only its bottom edge (for the
   rise), so the mark can stand above it. It doesn't move. */

.stage-title .line:not(.line-small) {
    overflow: visible;
    clip-path: inset(-1em -1em 0);
}

/* The mark is placed from the name's start, not from a
   wrapper around the "m": iOS WebKit leaves a positioned
   child's glyphs out of background-clip: text, and the "m"
   vanished (17.11). 2.82em is the middle of the "m" in
   Audiowide: "Exio" is 2.383em wide, "m" 0.874em. 0.73em
   up from the line's foot is where it sat over the "m". */

.stage-title .line:not(.line-small) > span {
    position: relative;
}

.title-mark {
    position: absolute;
    left: 2.82em;
    bottom: 0.73em;
    width: 0.54em;
    height: 0.54em;
    transform: translateX(-50%);
    filter: drop-shadow(0 0 0.06em rgba(var(--blue-rgb), 0.4));
}

/* ExiomAI glows (16.11): a soft blue and orange light behind
   the name, outside the lines that clip the rise. */

.stage-title::after {
    content: "";
    position: absolute;
    inset: 35% -8% -12% -6%;
    z-index: -1;
    background:
        radial-gradient(closest-side at 35% 55%, rgba(var(--blue-rgb), 0.28), transparent),
        radial-gradient(closest-side at 75% 60%, rgba(var(--orange-rgb), 0.16), transparent);
    filter: blur(24px);
    pointer-events: none;
}

/* Gradient type, only where the browser can clip it to the
   glyphs; anywhere else the title stays plain ink. */

@supports ((-webkit-background-clip: text) or (background-clip: text)) {

    .welcome-title {
        background: linear-gradient(100deg, var(--ink) 20%, #A9CCFF 60%, var(--blue) 100%);
        -webkit-background-clip: text;
        background-clip: text;
        -webkit-text-fill-color: transparent;
    }

    /* The name's colours flow slowly through the palette:
       ink, pale blue, blue, orange, amber and back. */

    .stage-title .line:not(.line-small) > span,
    .brand-name {
        background:
            linear-gradient(100deg, var(--ink) 8%, #A9CCFF 24%, var(--blue) 40%, var(--orange) 58%, var(--amber) 68%, var(--blue) 86%, #A9CCFF)
            0 50% / 250% 100%;
        -webkit-background-clip: text;
        background-clip: text;
        -webkit-text-fill-color: transparent;
        animation: title-flow 9s ease-in-out infinite alternate;
    }

}

@keyframes title-flow {
    to { background-position: 100% 50%; }
}

@media (forced-colors: active) {

    .chamber,
    .stage-field {
        display: none;
    }

    .stage-title .line > span,
    .welcome-title {
        background: none;
        -webkit-text-fill-color: currentColor;
    }

}

/* "by Xrypto": the maker's name links to their YouTube
   channel, dressed as a play button that invites the click:
   a ring ripples out of it. Hover fills it. */

.stage-by {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 0 14px;
    color: var(--muted);
    font-size: 0.9375rem;
}

.maker {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 4px 13px 4px 4px;
    border: 1px solid rgba(var(--orange-rgb), 0.6);
    border-radius: 999px;
    background: rgba(var(--orange-rgb), 0.12);
    color: var(--amber);
    font-weight: 750;
    font-stretch: 115%;
    text-decoration: none;
    transition: transform 0.4s var(--spring), background-color 0.2s ease, color 0.2s ease;
}

.maker::before {
    content: "";
    position: absolute;
    inset: -1px;
    border: 1px solid var(--orange);
    border-radius: inherit;
    animation: ripple 2.4s ease-out infinite;
    pointer-events: none;
}

.maker-play {
    width: 22px;
    height: 22px;
    padding: 3px;
    border-radius: 50%;
    background: var(--hot);
    fill: var(--on-hot);
    transition: transform 0.4s var(--spring);
}

.maker:hover {
    background: var(--orange);
    color: var(--on-hot);
    transform: translateY(-2px) scale(1.05);
}

.maker:hover .maker-play {
    transform: scale(1.12);
    background: var(--on-hot);
    fill: var(--amber);
}

.maker:active {
    transform: scale(0.95);
    transition-duration: 0.1s;
}

@keyframes ripple {
    from { transform: scale(1); opacity: 0.9; }
    to { transform: scale(1.3, 1.6); opacity: 0; }
}

/* The lede (16.11): smaller and close under the name, but
   brighter than muted text, with its last line in amber so
   it reads warm, not grey. */

.stage-lede {
    max-width: 42ch;
    margin: 0 0 32px;
    color: #C9D6EC;
    font-size: clamp(0.9375rem, 1.05vw, 1.0625rem);
    line-height: 1.55;    text-wrap: pretty;
}

/* The amber line stands alone under the description
   (16.16). */

.stage-lede strong {
    display: block;
    color: var(--amber);
    font-weight: 650;
}

/* Start chatting leads the copy (17.7): the biggest thing
   on the page after the name. */

/* Start chatting, with the arrow centred under it (16.11). */

.stage-actions {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
}

/* On desktop the arrow sits halfway between Start chatting
   and the foot, whatever the window's height: the copy fills
   the space, an equal share of it goes above the name and
   below the button, and the arrow centres in the lower one. */

@media (min-width: 901px) and (orientation: landscape) {

    .stage-copy {
        flex: 1;
        display: flex;
        flex-direction: column;
        margin-block: 0;
    }

    .stage-copy::before {
        content: "";
        flex: 1 1 auto;
    }

    .stage-actions {
        flex: 1 1 auto;
        align-self: flex-start;
        gap: 0;
    }

    .stage-down {
        margin-block: auto;
    }

}

/* Buy XEQM sits at the top right (16.11), in the status
   chip's old place: blue glass, never fire. */

.button-buy {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-height: 40px;
    padding: 0 14px 0 16px;
    border: 1px solid rgba(var(--blue-rgb), 0.45);
    border-radius: 999px;
    background: rgba(var(--blue-rgb), 0.12);
    -webkit-backdrop-filter: blur(12px);
    backdrop-filter: blur(12px);
    color: var(--ink);
    font-size: 0.9375rem;
    font-weight: 600;
    font-stretch: 112%;
    text-decoration: none;
    transition: transform 0.4s var(--spring), background-color 0.2s ease, border-color 0.2s ease;
}

.button-buy svg {
    width: 16px;
    height: 16px;
    color: var(--ice);
    transition: transform 0.4s var(--spring);
}

.button-buy:hover {
    border-color: var(--blue);
    background: rgba(var(--blue-rgb), 0.3);
    transform: translateY(-2px);
}

.button-buy:hover svg {
    transform: translate(2px, -2px);
}

.button-buy:active {
    transform: scale(0.97);
    transition-duration: 0.1s;
}

.button-buy:focus-visible {
    border-radius: 999px;
    outline-offset: 4px;
}

.stage-down {
    display: grid;
    place-items: center;
    align-self: center;
    flex: none;
    width: 44px;
    height: 44px;
    padding: 0;
    border: 1px solid rgba(var(--blue-rgb), 0.45);
    border-radius: 50%;
    background: rgba(var(--blue-rgb), 0.1);
    color: var(--ice);
    cursor: pointer;
    transition: border-color 0.2s ease, background-color 0.2s ease;
}

.stage-down svg {
    width: 20px;
    height: 20px;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
    animation: sink 1.8s ease-in-out infinite;
}

.stage-down:hover {
    border-color: var(--blue);
    background: rgba(var(--blue-rgb), 0.3);
}

@keyframes sink {
    0%, 100% { transform: translateY(-2px); }
    50% { transform: translateY(3px); }
}


/* The foot of the landing: the maker's links, with Feedback
   and Support just after them (16.11), the project's links
   under them, then the small print, centred, wide and short,
   on the very bottom of the screen (17.7). */

.stage-foot {
    display: grid;
    gap: clamp(20px, 5vh, 56px);
    padding-top: 18px;
    border-top: 1px solid var(--line);
}

.link-rows {
    display: grid;
    gap: 10px;
}

.link-line {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px 22px;
}

.link-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
}

.link-row-name {
    min-width: 8.5em;
    color: var(--muted);
    font-size: 0.8125rem;
}

.link-pill {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    height: 36px;
    border-radius: 999px;
    text-decoration: none;
    transition: transform 0.35s var(--spring), background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease;
}

.link-pill svg {
    width: 18px;
    height: 18px;
    flex: none;
}

.link-pill {
    padding: 0 13px 0 10px;
    border: 1px solid rgba(var(--blue-rgb), 0.45);
    background: rgba(var(--blue-rgb), 0.1);
    color: var(--ink);
    font-size: 0.8125rem;
    font-weight: 600;
}

.link-pill svg {
    color: var(--ice);
}

.link-pill:hover {
    border-color: var(--blue);
    background: rgba(var(--blue-rgb), 0.3);
    transform: translateY(-2px);
}

.link-pill:active {
    transform: scale(0.94);
    transition-duration: 0.1s;
}

.link-pill:focus-visible {
    border-radius: 999px;
}

.disclaimer {
    max-width: 170ch;
    margin: 0 auto;
    color: var(--muted);
    font-size: 0.71875rem;
    line-height: 1.55;
    text-align: center;
    text-wrap: balance;
}

/* Feedback and support (16.10): two quiet words just after
   Xrypto's links (16.11), each opening a small card upwards,
   ending at the words. */

.foot-asks {
    position: relative;
    display: flex;
    align-items: center;
    gap: 22px;
    pointer-events: auto;
}

.ask-toggle {
    min-height: 36px;
    padding: 0 2px;
    border: 0;
    background: none;
    color: var(--ink);
    font: inherit;
    font-size: 0.8125rem;
    font-weight: 600;
    text-decoration: underline dotted rgba(var(--blue-rgb), 0.8);
    text-underline-offset: 0.35em;
    cursor: pointer;
    transition: color 0.2s ease;
}

.ask-toggle:hover,
.ask-toggle[aria-expanded="true"] {
    color: var(--ice);
    text-decoration-style: solid;
    text-decoration-color: var(--ice);
}

.ask-card {
    position: absolute;
    right: 0;
    bottom: calc(100% + 10px);
    z-index: 2;
    display: grid;
    gap: 10px;
    width: min(24rem, calc(100vw - 2 * var(--gutter)));
    padding: 14px 16px 16px;
    border: 1px solid rgba(var(--blue-rgb), 0.45);
    border-radius: 14px;
    background: linear-gradient(var(--wash), var(--wash)), var(--deep);
    box-shadow: 0 18px 50px -14px rgba(var(--ice-rgb), 0.35);
    color: var(--ink);
    font-size: 0.8125rem;
    line-height: 1.5;
    transform-origin: bottom right;
    transition: opacity 0.18s ease, transform 0.35s var(--spring);
}

.ask-card:not(.is-open) {
    display: none;
}

@starting-style {
    .ask-card {
        opacity: 0;
        transform: translateY(6px) scale(0.96);
    }
}

.ask-card p {
    margin: 0;
}

.ask-card a {
    color: var(--ice);
    font-weight: 600;
}

.ask-address {
    padding: 8px 10px;
    border: 1px solid var(--line);
    border-radius: 8px;
    background: var(--wash);
    color: var(--ice);
    font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
    font-size: 0.75rem;
    line-height: 1.45;
    overflow-wrap: anywhere;
    user-select: all;
    -webkit-user-select: all;
}

.ask-copy {
    justify-self: start;
    height: 36px;
    padding: 0 16px;
    border: 1px solid transparent;
    border-radius: 999px;
    background: var(--hot);
    color: var(--on-hot);
    font: inherit;
    font-size: 0.8125rem;
    font-weight: 700;
    cursor: pointer;
    transition: transform 0.35s var(--spring);
}

.ask-copy:active {
    transform: scale(0.94);
    transition-duration: 0.1s;
}

.ask-copy:focus-visible {
    border-radius: 999px;
}


/* ---------------------------------------------------------
   THE ASSISTANT
   --------------------------------------------------------- */

.app {
    --reveal: 0%;

    display: grid;
    grid-template-rows: auto minmax(0, 1fr) auto;
    /* Never wider than the screen: on a 320px phone the
       footer line's width pushed the chat 17px off the
       right edge (17.12). */
    grid-template-columns: minmax(0, 1fr);
    position: relative;
    isolation: isolate;
    overflow: hidden;
    height: 100vh;
    height: 100dvh;
    background:
        radial-gradient(130% 100% at 50% 46%, transparent 50%, rgba(var(--deep-rgb), 0.85) 100%),
        var(--deep);
}

/* Inside the tunnel (Task 17): the light of the core at the
   far end, orange round ice, breathing slowly. The canvas
   above it draws the walls. Transform only, so the breath
   costs the compositor and nothing else. */

.app::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background:
        radial-gradient(14% 12% at 50% 46%, rgba(var(--ice-rgb), 0.16), transparent 70%),
        radial-gradient(36% 32% at 50% 46%, rgba(var(--orange-rgb), 0.2), transparent 72%),
        radial-gradient(70% 60% at 50% 46%, rgba(var(--blue-rgb), 0.16), transparent 75%);
    pointer-events: none;
    animation: breathe 7s ease-in-out infinite alternate;
}

@keyframes breathe {
    to { transform: scale(1.12); }
}

.chamber {
    position: absolute;
    inset: 0;
    z-index: -1;
    width: 100%;
    height: 100%;
    pointer-events: none;
}

/* During the dive the chat sits above the stage, visible
   only inside the circle opening out of the core. Clipped
   areas take no clicks, and the page cannot scroll. */

.is-intro,
.is-intro body {
    overflow: hidden;
}

.is-intro .app {
    position: fixed;
    inset: 0;
    z-index: 30;
    clip-path: circle(var(--reveal) at 50% 50%);
    pointer-events: none;
}

/* The light of the core, clearing as the circle opens. */

.is-intro .app::after {
    content: "";
    position: absolute;
    inset: 0;
    background: radial-gradient(
        circle at 50% 50%,
        #FFFFFF 6%,
        rgba(var(--ice-rgb), 0.5) 28%,
        rgba(var(--orange-rgb), 0.3) 52%,
        transparent 75%
    );
    opacity: var(--flash, 0);
}

.app-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: max(12px, env(safe-area-inset-top)) var(--gutter) 12px;
    border-bottom: 1px solid var(--line);
    background: rgba(var(--deep-rgb), 0.35);
    -webkit-backdrop-filter: blur(16px);
    backdrop-filter: blur(16px);
}

.app-bar-end {
    display: flex;
    align-items: center;
    gap: 14px;
    min-width: 0;
}




/* Conversation log */

.log {
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 8px max(var(--gutter), (100% - var(--column)) / 2) 32px;
    scrollbar-width: thin;
    scrollbar-color: rgba(var(--blue-rgb), 0.25) transparent;
}

.log:focus-visible {
    outline-offset: -3px;
}

.welcome {
    padding-top: clamp(32px, 11vh, 128px);
}

.welcome-title {
    margin: 0 0 12px;
    font-size: clamp(2rem, 5.2vw, 3.25rem);
    font-weight: 780;
    font-stretch: 122%;
    letter-spacing: -0.035em;
    line-height: 1.04;
}

.welcome-lede {
    max-width: 52ch;
    margin: 0 0 36px;
    color: var(--muted);
}

/* Suggestions: glass tiles, each in its topic's colour. The
   live snapshot is ice because it is the one that reads the
   chain; its dot beats like the other live signals. */

.prompts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
    gap: 12px;
}

.prompt {
    --tone: var(--blue-rgb);

    position: relative;
    isolation: isolate;
    overflow: hidden;
    display: grid;
    align-content: start;
    gap: 6px;
    padding: 18px 20px 20px;
    border: 1px solid rgba(var(--tone), 0.22);
    border-radius: 20px;
    background:
        linear-gradient(155deg, rgba(var(--tone), 0.16), rgba(var(--tone), 0.03) 65%),
        var(--glass);
    -webkit-backdrop-filter: blur(14px);
    backdrop-filter: blur(14px);
    text-align: left;
    transition:
        transform 0.45s var(--spring),
        border-color 0.25s ease,
        box-shadow 0.3s ease;
}

.prompt[data-tone="orange"] { --tone: var(--orange-rgb); }
.prompt[data-tone="amber"] { --tone: var(--amber-rgb); }
.prompt[data-tone="ice"] { --tone: var(--ice-rgb); }

/* The pointer's light (--mx, --my, set by the script). */

.prompt::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background: radial-gradient(
        260px circle at var(--mx, 50%) var(--my, 0%),
        rgba(var(--tone), 0.3),
        transparent 70%
    );
    opacity: 0;
    transition: opacity 0.3s ease;
}

.prompt strong {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 1rem;
    font-weight: 650;
    font-stretch: 108%;
}

.prompt strong::before {
    content: "";
    width: 8px;
    height: 8px;
    flex: none;
    border-radius: 50%;
    background: rgb(var(--tone));
    box-shadow: 0 0 10px rgb(var(--tone));
    transition: transform 0.45s var(--spring);
}

.prompt[data-tone="ice"] strong::before {
    animation: beat 2.4s ease-in-out infinite;
}

.prompt small {
    padding-left: 18px;
    color: var(--muted);
    font-size: 0.875rem;
    line-height: 1.45;
}

.prompt:hover {
    transform: translateY(-3px);
    border-color: rgba(var(--tone), 0.6);
    box-shadow: 0 18px 44px -20px rgba(var(--tone), 0.9);
}

.prompt:hover::before {
    opacity: 1;
}

.prompt:hover strong::before {
    transform: scale(1.6);
}

.prompt:active {
    transform: scale(0.98);
    transition-duration: 0.1s;
}

/* Phones: four small tiles, two by two, instead of four
   long rows, all above the message bar with no scrolling
   (17.12). The space above the heading and under the lede
   shrinks, the dot sits beside the title and each tile is
   only as tall as its words. The note goes where the height
   is short. */

@media (max-width: 600px) {

    .welcome {
        padding-top: clamp(8px, 3vh, 32px);
    }

    .welcome .welcome-lede {
        margin-bottom: 16px;
    }

    .prompts {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 8px;
    }

    .prompt {
        align-content: start;
        gap: 4px;
        padding: 11px 12px 12px;
        border-radius: 16px;
    }

    .prompt strong {
        align-items: flex-start;
        gap: 8px;
        font-size: 0.9375rem;
        line-height: 1.2;
    }

    .prompt strong::before {
        margin-top: 0.4em;
    }

    .prompt small {
        display: -webkit-box;
        overflow: hidden;
        -webkit-box-orient: vertical;
        -webkit-line-clamp: 2;
        line-clamp: 2;
        padding-left: 16px;
        font-size: 0.8125rem;
        line-height: 1.3;
    }

}

/* Narrow or short phones: the title says enough on its own. */

@media (max-width: 359px), (max-width: 600px) and (max-height: 600px) {

    .prompt small {
        display: none;
    }

}


/* Messages */

.msg {
    margin: 28px 0;
}

.msg-user {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
}

.bubble {
    max-width: min(85%, 36rem);
    padding: 12px 16px;
    border-radius: 20px 20px 6px 20px;
    background: linear-gradient(135deg, #2563EB, #1B3FA8);
    box-shadow: 0 12px 32px -14px rgba(var(--orange-rgb), 0.7);
    color: #FFFFFF;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.msg-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    margin-bottom: 8px;
    color: var(--muted);
    font-size: 0.8125rem;
    font-weight: 600;
    font-stretch: 112%;
}

.msg-mark {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--hot);
    box-shadow: 0 0 10px rgba(var(--orange-rgb), 0.9);
}

.live-badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 2px 9px;
    border: 1px solid rgba(var(--ice-rgb), 0.3);
    border-radius: 999px;
    color: var(--ice);
    font-weight: 500;
    font-stretch: 100%;
}

.live-dot {
    width: 6px;
    height: 6px;
}

/* Answers a step larger and heavier than the page, in
   Inter; the user's own bubbles keep Mona Sans. */

.msg-body {
    font-family: "Inter", var(--font);
    font-size: 1.0625rem;
    font-weight: 500;
    font-stretch: normal;
    line-height: 1.65;
    overflow-wrap: anywhere;
}

.msg-body p {
    margin: 0 0 0.7em;
}

.msg-body h2,
.msg-body h3,
.msg-body h4 {
    margin: 1.2em 0 0.5em;
    font-stretch: 112%;
    letter-spacing: -0.01em;
    line-height: 1.25;
}

.msg-body h2 { font-size: 1.375rem; font-weight: 650; }
.msg-body h3 { font-size: 1.1875rem; font-weight: 650; }
.msg-body h4 { font-size: 1.0625rem; font-weight: 650; }

.msg-body > :first-child {
    margin-top: 0;
}

.msg-body ul,
.msg-body ol {
    margin: 0 0 0.8em;
    padding-left: 1.35em;
}

.msg-body li {
    margin: 0.3em 0;
    padding-left: 0.2em;
}

.msg-body li::marker {
    color: var(--blue);
}

.msg-body strong {
    font-weight: 700;
}

.msg-body code {
    padding: 0.1em 0.4em;
    border-radius: 6px;
    background: var(--wash);
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.875em;
}

.answer-space {
    height: 0.4em;
}

.is-streaming > :last-child::after {
    content: "";
    display: inline-block;
    width: 0.5em;
    height: 1.05em;
    margin-left: 3px;
    vertical-align: -0.15em;
    border-radius: 2px;
    background: var(--hot);
    animation: caret 1s steps(1) infinite;
}

@keyframes caret {
    50% { opacity: 0; }
}

.error-message {
    color: var(--danger);
}

.msg-source {
    margin: 12px 0 0;
    padding-top: 10px;
    border-top: 1px solid var(--line);
    color: var(--muted);
    font-size: 0.8125rem;
}


/* Copy (16.18): a quiet icon under each message; it turns
   into a tick for a moment once copied. */

.msg-actions {
    display: flex;
    margin-top: 6px;
}

.copy-button {
    display: grid;
    place-items: center;
    width: 32px;
    height: 32px;
    margin-left: -6px;
    padding: 0;
    border: 0;
    border-radius: 8px;
    background: transparent;
    color: var(--muted);
    opacity: 0.7;
    cursor: pointer;
    transition: color 0.2s ease, background 0.2s ease, opacity 0.2s ease;
}

/* The negative margin lines the glyph, not the button's
   hover pad, up with the text edge (or the bubble's). */

.msg-user .copy-button {
    margin-left: 0;
    margin-right: -6px;
}

.copy-button:hover,
.copy-button:focus-visible {
    background: var(--glass);
    color: var(--ink);
    opacity: 1;
}

.copy-button svg {
    grid-area: 1 / 1;
    width: 17px;
    height: 17px;
}

.copy-button .copied-icon,
.copy-button.is-copied .copy-icon {
    visibility: hidden;
}

.copy-button.is-copied .copied-icon {
    visibility: visible;
}

.copy-button.is-copied {
    color: var(--ice);
    opacity: 1;
}


/* Thinking: a signal crossing a synapse. */

.thinking {
    display: inline-flex;
    align-items: center;
    gap: 12px;
    color: var(--muted);
}

.synapse {
    position: relative;
    display: inline-flex;
    justify-content: space-between;
    width: 42px;
}

.synapse::before {
    content: "";
    position: absolute;
    top: 50%;
    left: 3px;
    right: 3px;
    height: 1px;
    background: var(--line);
}

.synapse i {
    position: relative;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--blue);
    opacity: 0.3;
    animation: fire 1.2s ease-in-out infinite;
}

.synapse i:nth-child(2) { animation-delay: 0.2s; }
.synapse i:nth-child(3) { animation-delay: 0.4s; }

@keyframes fire {
    30% {
        opacity: 1;
        background: var(--orange);
        box-shadow: 0 0 12px var(--orange);
    }
}


/* Composer */

.dock {
    padding:
        10px
        max(var(--gutter), (100% - var(--column)) / 2)
        max(14px, env(safe-area-inset-bottom));
    background: linear-gradient(transparent, var(--deep) 30%);
}

.composer {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 8px;
    padding: 7px 7px 7px 20px;
    border: 1px solid transparent;
    border-radius: 26px;
    background:
        linear-gradient(var(--raised), var(--raised)) padding-box,
        linear-gradient(100deg, rgba(var(--blue-rgb), 0.4), rgba(var(--orange-rgb), 0.4), rgba(var(--amber-rgb), 0.3)) border-box;
    box-shadow: 0 18px 50px -20px rgba(0, 0, 0, 0.8);
    transition: box-shadow 0.3s ease;
}

.composer:focus-within {
    background:
        linear-gradient(var(--raised), var(--raised)) padding-box,
        linear-gradient(100deg, var(--blue), var(--orange), var(--amber)) border-box;
    box-shadow:
        0 0 0 5px rgba(var(--orange-rgb), 0.12),
        0 18px 60px -18px rgba(var(--orange-rgb), 0.55);
}

.composer textarea {
    flex: 1;
    min-width: 0;
    max-height: 180px;
    margin: 0;
    padding: 9px 0;
    border: 0;
    background: none;
    font-size: 1rem;
    line-height: 1.5;
    resize: none;
    outline: none;
}

.composer textarea::placeholder {
    color: var(--muted);
    opacity: 1;
}

.composer textarea:disabled {
    opacity: 0.6;
}

.send-button {
    display: grid;
    place-items: center;
    width: 40px;
    height: 40px;
    flex: none;
    border: 0;
    border-radius: 50%;
    background: var(--hot);
    color: var(--on-hot);
    box-shadow: 0 6px 20px -6px rgba(var(--orange-rgb), 0.8);
    transition: transform 0.4s var(--spring), box-shadow 0.25s ease, opacity 0.2s ease;
}

.send-button:enabled:hover {
    transform: translateY(-2px) rotate(-8deg);
    box-shadow: 0 10px 28px -6px rgba(var(--orange-rgb), 1);
}

.send-button:disabled {
    opacity: 0.35;
    box-shadow: none;
    cursor: default;
}

.send-button svg {
    width: 18px;
    height: 18px;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

/* Images (Image Upload plan, Part 3): a tray of chips over
   the textarea, the attach button left of Ask. */

.attachments {
    flex: 0 0 100%;
    min-width: 0;
    padding-top: 4px;
}

.attachments[hidden] {
    display: none;
}

.attach-chips {
    display: flex;
    gap: 8px;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
}

.attach-chips:empty {
    display: none;
}

.attach-chip {
    position: relative;
    flex: none;
    width: 56px;
    height: 56px;
    border-radius: 12px;
    overflow: hidden;
    box-shadow: 0 0 0 1px var(--glass-edge);
}

.attach-chip img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.attach-remove {
    position: absolute;
    top: 3px;
    right: 3px;
    display: grid;
    place-items: center;
    width: 22px;
    height: 22px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: rgba(var(--deep-rgb), 0.78);
    color: var(--ink);
    font-size: 0.6875rem;
    line-height: 1;
}

.attach-remove:hover,
.attach-remove:focus-visible {
    background: var(--danger);
    color: var(--deep);
}

.attach-note {
    margin: 6px 0 0;
    color: var(--muted);
    font-size: 0.75rem;
    line-height: 1.3;
}

.attach-note:empty {
    display: none;
}

.attach-button {
    display: grid;
    place-items: center;
    width: 40px;
    height: 40px;
    flex: none;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: var(--glass);
    color: var(--muted);
    transition: color 0.2s ease, background 0.2s ease, opacity 0.2s ease;
}

.attach-button:enabled:hover,
.attach-button:focus-visible {
    background: var(--wash);
    color: var(--ink);
}

.attach-button:disabled {
    opacity: 0.35;
    cursor: default;
}

.attach-button svg {
    width: 20px;
    height: 20px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.6;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.composer.is-dropping {
    background:
        linear-gradient(var(--raised), var(--raised)) padding-box,
        linear-gradient(100deg, var(--blue), var(--orange), var(--amber)) border-box;
    box-shadow: 0 0 0 5px rgba(var(--blue-rgb), 0.25);
}

.bubble-images {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.bubble-images.has-text {
    margin-bottom: 8px;
}

.bubble-images img {
    display: block;
    width: 88px;
    height: 88px;
    border-radius: 12px;
    object-fit: cover;
}

.privacy-note {
    max-width: 60ch;
    margin: 10px auto 0;
    color: var(--muted);
    font-size: 0.75rem;
    line-height: 1.5;
    text-align: center;
}

/* The note folds to one line and a Small print word at
   every width (16.14; desktop too since): the full text
   opens as a card above the composer. */

.dock {
    position: relative;
}

.privacy-gist {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    margin: 4px 0 0;
    color: var(--muted);
    font-size: 0.6875rem;
    line-height: 1.3;
    white-space: nowrap;
}

.privacy-gist .ask-toggle {
    min-height: 28px;
    font-size: 0.6875rem;
}

.privacy-note {
    position: absolute;
    left: max(var(--gutter), (100% - var(--column)) / 2);
    right: max(var(--gutter), (100% - var(--column)) / 2);
    bottom: calc(100% + 4px);
    z-index: 2;
    max-width: none;
    margin: 0;
    padding: 14px 16px;
    border: 1px solid rgba(var(--blue-rgb), 0.45);
    border-radius: 14px;
    background: linear-gradient(var(--wash), var(--wash)), var(--deep);
    box-shadow: 0 18px 50px -14px rgba(var(--ice-rgb), 0.35);
    color: var(--ink);
    font-size: 0.75rem;
    text-align: left;
}

.privacy-note:not(.is-open) {
    display: none;
}


/* ---------------------------------------------------------
   SMALL SCREENS
   --------------------------------------------------------- */

@media (max-width: 900px), (orientation: portrait) {

    .stage-copy {
        max-width: 40rem;
        margin-block: auto 0;
    }

    /* The copy rises into the brain here; a dusk behind it
       keeps it readable. */

    .stage-ui::before {
        content: "";
        position: absolute;
        inset: 25% 0 0;
        z-index: -1;
        background: linear-gradient(transparent, rgba(var(--deep-rgb), 0.9) 32%);
        pointer-events: none;
    }

    .stage-foot {
        margin-top: 16px;
    }

    /* Tablets (16.11): the words may wrap under Xrypto's
       links, so a card opens from the line's left edge, where
       it always fits. */

    .link-line {
        position: relative;
    }

    .foot-asks {
        position: static;
    }

    .ask-card {
        left: 0;
        right: auto;
        transform-origin: bottom left;
    }

}

@media (max-width: 600px) {

    .stage-down {
        width: 38px;
        height: 38px;
    }

    .stage-by {
        margin-bottom: 12px;
        font-size: 0.875rem;
    }

    .stage-lede {
        margin-bottom: 22px;
        font-size: 0.9375rem;
    }

    .stage-actions {
        display: flex;
        align-items: stretch;
        gap: 12px;
    }

    .stage-actions .button-primary {
        font-size: 1.5rem;
        width: 100%;
        justify-content: space-between;
        padding-left: 28px;
    }

    /* Icons only on phones; the names stay for screen
       readers and show as tooltips. */

    .link-pill {
        width: 36px;
        padding: 0;
    }

    .link-pill span {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip: rect(0 0 0 0);
        white-space: nowrap;
    }

    /* Phones (16.10): one strip of icons, each group under its
       own caption and split by a hairline; the words and the
       small print centre under it, on one axis. The column
       counts match the pills in each row. */

    .stage-foot {
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        justify-content: center;
        gap: 6px 12px;
    }

    .link-rows,
    .link-line {
        display: contents;
    }

    .link-row {
        flex: none;
        max-width: 100%;
        order: 1;
        display: grid;
        grid-template-columns: repeat(3, auto);
        gap: 6px;
    }

    .link-row.is-project {
        flex-basis: auto;
        order: 2;
        grid-template-columns: repeat(5, auto);
        padding-left: 12px;
        border-left: 1px solid var(--line);
    }

    .link-row-name {
        grid-column: 1 / -1;
        min-width: 0;
        font-size: 0.75rem;
        line-height: 1.3;
        white-space: nowrap;
    }

    .foot-asks {
        position: relative;
        flex-basis: 100%;
        order: 3;
        justify-content: center;
    }

    .ask-card {
        right: 0;
        left: 0;
        width: min(24rem, 100%);
        margin-inline: auto;
        transform-origin: bottom center;
    }

    /* Two parts (16.12): the first screen holds only the
       name and the way in; the links, the words and the full
       small print wait a scroll below it, on their own dark
       ground. A swipe scrolls here (the dive listens to the
       wheel only), and the arrow scrolls down to the foot. */

    .stage {
        touch-action: pan-y;
    }

    .stage-ui {
        display: block;
        overflow: hidden auto;
        overscroll-behavior: contain;
        scrollbar-width: none;
        pointer-events: auto;
        touch-action: pan-y;
    }

    .stage-ui::-webkit-scrollbar {
        display: none;
    }

    .stage-title::after {
        inset-inline: 0;
    }

    .stage-hero {
        display: flex;
        flex-direction: column;
        min-height: 100%;
    }

    .stage-foot {
        position: relative;
        margin: max(10px, env(safe-area-inset-bottom)) calc(-1 * var(--gutter)) 0;
        padding: 20px var(--gutter) 8px;
        background: linear-gradient(rgba(var(--deep-rgb), 0.92), var(--deep) 40%);
        row-gap: 14px;
    }

    .foot-asks {
        margin-top: 4px;
    }

    .disclaimer {
        flex-basis: 100%;
        order: 4;
        margin-top: 4px;
        text-wrap: pretty;
    }

    .cta-core {
        width: 52px;
        height: 52px;
    }

    .app-bar {
        padding-inline: 16px;
    }

    .app-bar-end {
        gap: 10px;
    }

    .welcome-lede {
        margin-bottom: 24px;
    }

}

/* Phones: the note is one line, and the full text opens as
   a card above the composer, like the Feedback card. */

@media (max-width: 600px) {

    /* Buy XEQM a tad smaller on phones. */

    .button-buy {
        gap: 5px;
        min-height: 32px;
        padding: 0 10px 0 12px;
        font-size: 0.8125rem;
    }

    .button-buy svg {
        width: 13px;
        height: 13px;
    }

    /* Messages a step under the page's 16px, so a phone
       shows more of an answer (16.15). The textarea stays at
       16px: under that, iOS zooms the page on focus. */

    .msg {
        margin: 18px 0;
        font-size: 0.875rem;
        line-height: 1.55;
    }

    .bubble {
        padding: 8px 13px;
        border-radius: 17px 17px 5px 17px;
    }

    /* A thumb-sized target on phones. */

    .attach-button {
        width: 44px;
        height: 44px;
    }

    .bubble-images img {
        width: 72px;
        height: 72px;
    }

    /* Copy (16.18): a bigger target, its glyph still on the
       text edge. */

    .copy-button {
        width: 40px;
        height: 40px;
        margin-left: -10px;
    }

    .msg-user .copy-button {
        margin-right: -10px;
    }

    .msg-body {
        font-size: 0.9375rem;
        line-height: 1.6;
    }

    .msg-body p {
        margin-bottom: 0.6em;
    }

    /* The chat's network, softly out of focus behind the
       answers on phones. */

    .chamber {
        filter: blur(1.5px);
    }

    .msg-body h2 { font-size: 1.1875rem; }
    .msg-body h3 { font-size: 1.0625rem; }
    .msg-body h4 { font-size: 1em; }

    /* The status chip gives the bar to the name */

    .chip.is-status {
        display: none;
    }

    /* The copy rises to meet the brain; the arrow keeps its
       place at the foot of the screen. */

    .stage-down {
        margin-top: 44px;
    }

}

/* Touch screens keep :hover after a tap; don't leave a tile
   lifted or lit once the finger is gone. */

@media (hover: none) {

    .prompt:hover,
    .button-primary:hover,
    .send-button:enabled:hover {
        transform: none;
    }

    .prompt:hover::before {
        opacity: 0;
    }

    .button-primary:hover::after {
        --light: 0;
    }

    .maker:hover,
    .button-buy:hover,
    .link-pill:hover {
        transform: none;
    }

}

@media (max-width: 400px) {

    /* The icon strip still fits one line down to 355px. */

    .link-pill {
        width: 34px;
        height: 34px;
    }

    .link-row {
        gap: 5px;
    }

    .stage-foot {
        column-gap: 10px;
    }

    .link-row.is-project {
        padding-left: 10px;
    }

}

/* Narrower still, smaller pills keep the strip on one line
   (28px is still above the 24px minimum touch target). Below
   300px the groups stack and lose the rule. */

@media (max-width: 354px) {

    .link-pill {
        width: 28px;
        height: 28px;
    }

    .link-pill svg {
        width: 16px;
        height: 16px;
    }

}

@media (max-width: 299px) {

    .link-row.is-project {
        padding-left: 0;
        border-left: 0;
    }

}

/* Short phones: the copy tightens so the name
   clears the top bar. */

@media (max-width: 600px) and (max-height: 620px) {

    .stage-ui {
        --title-size: 3rem;
    }

    .stage-by {
        margin-bottom: 10px;
    }

    .stage-actions {
        gap: 8px;
    }

    .stage-down {
        margin-top: 0;
    }

    .cta-core {
        width: 44px;
        height: 44px;
    }

}


/* ---------------------------------------------------------
   REDUCED MOTION

   No intro at all, and nothing that loops.
   --------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {

    .stage {
        display: none;
    }

    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }

}
