/* =============================================================================
   InvestProp — App / «اپلیکیشن اینوست پراپ» (the home screen)
   -----------------------------------------------------------------------------
   Used by `site/index/app.blade.php`. Replaces the old `.invest-app-hero`, whose
   CSS block was deleted from home.css (the copies left in the compiled
   mainPage*.css are dead but harmless — nothing else uses that class).

   The section shows the thing it asks for: a phone whose home screen already has
   our icon on it, lit, among the dim placeholders of everything else. The one
   before this was three equal platform cards, two of them greyed out — two
   thirds of the section spent saying "nothing here yet", with no sight of the
   product. Availability is now one row of chips under the button.

   Shape language: the InvestProp mark is a square with its corners cut at 45°,
   and `--ch` cuts exactly ONE thing here — our icon on the phone's home screen,
   where that cut is what marks it out among rounded placeholders alongside the
   colour. The cut is physical (top-left / bottom-right) and does not mirror; the
   logo does not.

   Everything else follows the SITE's system rather than a shape invented for
   this section: the button is `.hx-btn--primary` from home.css (52px, 14px
   radius, the gradient, the glow, and the 1px shine along the top-start edge
   that home.css calls "the house style for the CTA"), and the eyebrow and the
   availability chips are the 999px pill shared by bento / pricing / scorecard /
   atlas. A section that invents its own controls is the odd one out however good
   the shape is.

   The phone is deliberately dark in BOTH themes. It is a device, not a surface
   of the page, and on the light page it reads as a product shot and gives the
   layout something to weigh against.

   Contract with app-install.js
   ----------------------------
     .ap-app.is-live      — the script is running, so the steps may fold away.
     [data-ap-pwa].is-ready     — the browser offered `beforeinstallprompt`.
     [data-ap-pwa].is-installed — already running as an installed app.
     [data-ap-pwa].is-manual    — no programmatic install here (iOS Safari); the
                                  steps stay, because they are the only way in.
   ========================================================================== */

.ap-app {
    /* --- palette (dark = default) ----------------------------------------- */
    --ap-primary: #007BFF;
    --ap-primary-2: #1C8AFF;
    --ap-cyan: #5ED2EC;
    --ap-mint: #3DD68C;

    --ap-surface: rgba(7, 19, 35, .72);
    --ap-line: rgba(141, 196, 255, .16);
    --ap-line-2: rgba(141, 196, 255, .3);
    --ap-text: #EAF2FF;
    --ap-text-2: #C3D4EA;
    --ap-muted: #8FA5C2;

    --ap-sky: #8DC4FF;
    --ap-grad: linear-gradient(94.98deg, #007BFF 4.01%, #1C8AFF 103.03%);
    --ap-glow: 0 10px 40px -12px rgba(0, 123, 255, .55);

    /* --- the device: its own scale, not the page's ------------------------- */
    --ap-shell: #0B1A2E;
    --ap-shell-2: #05101E;
    --ap-glass: rgba(141, 196, 255, .1);
    --ap-glass-2: rgba(141, 196, 255, .16);

    position: relative;
    margin-top: 96px;
    isolation: isolate;
}

html:not(.dark) .ap-app {
    --ap-sky: #0B63D6;
    --ap-cyan: #0C7C9B;
    --ap-primary-2: #0B63D6;
    --ap-mint: #12885A;

    --ap-surface: #FFFFFF;
    --ap-line: rgba(0, 72, 153, .14);
    --ap-line-2: rgba(0, 72, 153, .26);
    --ap-text: #0A1A30;
    --ap-text-2: #2B4463;
    --ap-muted: #5D7492;
}

/* --- the device (the chamfer) --------------------------------------------- */
/* The chamfer is reserved for ONE thing: our icon on the phone's home screen,
   where the cut is what marks it out among rounded placeholders alongside the
   colour. It is not a button style — the controls below follow the site's own
   button and chip system (`.hx-btn` in home.css, and the eyebrow shared by
   bento / pricing / scorecard / atlas), because a section that invents its own
   is the odd one out however good the shape is. */
.ap-app .ap-slot--ours .ap-slot__tile {
    clip-path: polygon(
        var(--ch) 0,
        100% 0,
        100% calc(100% - var(--ch)),
        calc(100% - var(--ch)) 100%,
        0 100%,
        0 var(--ch)
    );
}

.ap-app .ap-sprite {
    position: absolute;
    width: 0;
    height: 0;
    overflow: hidden;
}

.ap-app__glow {
    position: absolute;
    z-index: -1;
    top: 0;
    inset-inline-end: 4%;
    width: min(620px, 70%);
    height: 520px;
    border-radius: 50%;
    filter: blur(150px);
    opacity: .34;
    background: radial-gradient(circle, rgba(0, 123, 255, .6), rgba(0, 123, 255, 0) 70%);
    pointer-events: none;
}

html:not(.dark) .ap-app__glow { opacity: .16; }

/* =============================================================================
   1. Layout
   ========================================================================== */

.ap-layout {
    display: grid;
    gap: 44px;
    align-items: center;
    justify-items: center;
    text-align: center;
}

.ap-copy { max-width: 560px; }

/* =============================================================================
   2. Copy
   ========================================================================== */

.ap-eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 16px;
    padding: 6px 14px;
    border: 1px solid var(--ap-line-2);
    border-radius: 999px;
    background: color-mix(in srgb, var(--ap-primary) 10%, transparent);
    color: var(--ap-sky);
    font-size: 13px;
    font-weight: 700;
    letter-spacing: .02em;
}

.ap-title {
    margin: 0;
    color: var(--ap-text);
    font-size: 26px;
    font-weight: 700;
    line-height: 1.45;
}

.ap-lead {
    margin: 14px 0 0;
    color: var(--ap-text-2);
    font-size: 15px;
    line-height: 2;
}

/* --- the action ----------------------------------------------------------- */
.ap-act { margin-top: 28px; }

/* The install button and — once the admin has set its link — the APK download
   share one row; below a phone's width they stack full-width. */
.ap-act__row {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 12px;
}

@media (min-width: 992px) {
    .ap-act__row { justify-content: flex-start; }
}

/* The APK: the house ghost button with an Android-green accent. It is a plain
   download link, so it never depends on the install prompt's state. */
.ap-apk {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    height: 52px;
    padding-inline: 22px;
    border: 1px solid color-mix(in srgb, var(--ap-mint) 45%, transparent);
    border-radius: 14px;
    background: color-mix(in srgb, var(--ap-mint) 8%, var(--ap-surface));
    color: var(--ap-text);
    font-size: 15px;
    font-weight: 800;
    text-decoration: none;
    transition: transform .18s ease, border-color .25s ease, background-color .25s ease;
}

.ap-apk .ap-install__icon { color: var(--ap-mint); }

.ap-apk:hover,
.ap-apk:focus-visible {
    color: var(--ap-text);
    border-color: var(--ap-mint);
    background: color-mix(in srgb, var(--ap-mint) 14%, var(--ap-surface));
    transform: translateY(-2px);
}

.ap-apk-meta {
    margin: 10px 0 0;
    color: var(--ap-muted);
    font-size: 12.5px;
}

@media (max-width: 479.98px) {
    .ap-act__row > .ap-install,
    .ap-act__row > .ap-apk { flex: 1 1 100%; }
}

/* The house CTA: 52px tall, 14px radius, the gradient, the glow and the 1px
   shine along the top-start edge — the same button as `.hx-btn--primary`. */
.ap-install {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    height: 52px;
    padding-inline: 26px;
    border: 1px solid transparent;
    border-radius: 14px;
    background: var(--ap-grad);
    box-shadow: var(--ap-glow);
    color: #FFFFFF;
    font-size: 15px;
    font-weight: 800;
    font-family: inherit;
    cursor: pointer;
    transition: transform .18s ease, box-shadow .25s ease, background-color .25s ease;
}

.ap-install:hover,
.ap-install:focus-visible {
    color: #FFFFFF;
    transform: translateY(-2px);
    box-shadow: 0 16px 46px -12px rgba(0, 123, 255, .75);
}

.ap-install:active { transform: translateY(0); }

/* The 1px shine along the top-start edge is the house style for the CTA. */
.ap-install::after {
    content: "";
    position: absolute;
    inset: 0;
    padding: 1px;
    border-radius: inherit;
    pointer-events: none;
    background: linear-gradient(106.61deg, #FFFFFF 2.5%, rgba(255, 255, 255, 0) 18.15%);
    -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    -webkit-mask-composite: xor;
    mask-composite: exclude;
}

.ap-install__icon {
    width: 18px;
    height: 18px;
    /* `stroke-width` is inherited, which is the only way into a <use> shadow
       tree — the sprite deliberately sets none. */
    stroke-width: 1.7;
}

/* No prompt to offer, so it drops to the house ghost button rather than the
   primary one — still clearly a control, but no longer the thing to press. */
[data-ap-pwa].is-manual .ap-install,
[data-ap-pwa].is-installed .ap-install {
    border-color: var(--ap-line-2);
    background: var(--ap-surface);
    box-shadow: none;
    backdrop-filter: blur(18px);
    color: var(--ap-text);
    cursor: default;
}

[data-ap-pwa].is-manual .ap-install::after,
[data-ap-pwa].is-installed .ap-install::after { display: none; }

[data-ap-pwa].is-installed .ap-install { color: var(--ap-mint); }

[data-ap-pwa].is-manual .ap-install:hover,
[data-ap-pwa].is-installed .ap-install:hover {
    transform: none;
    box-shadow: none;
}

.ap-steps {
    margin: 12px 0 0;
    color: var(--ap-muted);
    font-size: 12.5px;
    line-height: 1.9;
}

/* Once the script is alive it knows whether the steps are needed; until then
   they stay, because with no script the button cannot do anything. */
.ap-app.is-live [data-ap-pwa]:not(.is-manual) .ap-steps { display: none; }

/* --- availability --------------------------------------------------------- */
.ap-plat {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 8px;
    margin: 26px 0 0;
    padding: 0;
    list-style: none;
}

.ap-plat__item {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 7px 14px;
    border: 1px solid var(--ap-line);
    border-radius: 999px;
    background: var(--ap-surface);
    color: var(--ap-muted);
    font-size: 12.5px;
    font-weight: 700;
}

.ap-plat__icon {
    width: 15px;
    height: 15px;
    stroke-width: 1.7;
}

.ap-plat__name { font-weight: 700; }

.ap-plat__state {
    padding-inline-start: 7px;
    border-inline-start: 1px solid var(--ap-line-2);
}

/* The one that exists. */
.ap-plat__item.is-on {
    border-color: color-mix(in srgb, var(--ap-mint) 45%, transparent);
    background: color-mix(in srgb, var(--ap-mint) 8%, var(--ap-surface));
    color: var(--ap-text-2);
}

.ap-plat__item.is-on .ap-plat__icon { color: var(--ap-mint); }
.ap-plat__item.is-on .ap-plat__state { color: var(--ap-mint); }

.ap-note {
    margin: 18px 0 0;
    color: var(--ap-muted);
    font-size: 13px;
}

/* =============================================================================
   3. The home screen
   -----------------------------------------------------------------------------
   Built from real elements rather than an image: the icon is the actual PWA
   icon and the label under it is real text, so both stay crisp and translatable.
   ========================================================================== */

.ap-stage {
    position: relative;
    display: grid;
    place-items: center;
    width: 100%;
}

/* A pool of brand light under the device. Without it the phone is a dark
   object on a dark page and its silhouette goes soft. */
.ap-stage__halo {
    position: absolute;
    width: 300px;
    height: 320px;
    border-radius: 50%;
    filter: blur(80px);
    opacity: .62;
    background: radial-gradient(circle, rgba(28, 138, 255, .85), rgba(28, 138, 255, 0) 70%);
}

html:not(.dark) .ap-stage__halo { opacity: .3; }

.ap-phone {
    position: relative;
    width: 272px;
    padding: 11px;
    border-radius: 46px;
    /* The frame is metal catching one light from the top-start corner: a bright
       rail down that edge, a dark one down the other. A flat fill reads as a
       cardboard slab. */
    background:
        linear-gradient(145deg, #33496280 0%, transparent 38%),
        linear-gradient(160deg, #2C4157 0%, #101F31 44%, #1A2C41 100%);
    box-shadow:
        0 46px 80px -30px rgba(0, 0, 0, .7),
        0 0 0 1px rgba(141, 196, 255, .12),
        inset 0 1px 1px rgba(255, 255, 255, .22),
        inset 0 -1px 1px rgba(0, 0, 0, .5);
}

/* --- the rails ------------------------------------------------------------ */
.ap-phone__rail {
    position: absolute;
    inset-inline-start: -2px;
    width: 3px;
    border-radius: 3px 0 0 3px;
    background: linear-gradient(180deg, #44608040, #3C5470 22%, #22344A 100%);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .2);
}

.ap-phone__rail--vol  { top: 108px; height: 30px; }
.ap-phone__rail--vol2 { top: 148px; height: 30px; }

.ap-phone__rail--pwr {
    inset-inline-start: auto;
    inset-inline-end: -2px;
    top: 132px;
    height: 52px;
    border-radius: 0 2px 2px 0;
}

/* --- the screen ----------------------------------------------------------- */
.ap-phone__screen {
    position: relative;
    display: flex;
    flex-direction: column;
    height: 424px;
    padding: 8px 13px 10px;
    border-radius: 36px;
    background: #060F1C;
    overflow: hidden;
}

/* The wallpaper: brand light pooling behind the icon that matters, which is
   also the cheapest way to make the screen look lit rather than printed. */
.ap-phone__wall {
    position: absolute;
    inset: 0;
    background:
        radial-gradient(90% 46% at 22% 12%, rgba(28, 138, 255, .5), rgba(28, 138, 255, 0) 62%),
        radial-gradient(70% 40% at 92% 42%, rgba(94, 210, 236, .18), rgba(94, 210, 236, 0) 60%),
        radial-gradient(120% 60% at 50% 108%, rgba(0, 74, 160, .45), rgba(0, 74, 160, 0) 70%),
        linear-gradient(175deg, #0B1B30 0%, #050D18 60%, #030913 100%);
}

html[dir="rtl"] .ap-phone__wall { scale: -1 1; }

/* One diagonal highlight across the glass. */
/* The glass: one diagonal highlight, and a vignette so the corners fall away
   the way they do behind real cover glass. */
.ap-phone__sheen {
    position: absolute;
    inset: 0;
    pointer-events: none;
    background:
        linear-gradient(118deg, rgba(255, 255, 255, .085) 0%, rgba(255, 255, 255, .02) 24%, transparent 46%),
        radial-gradient(120% 84% at 50% 46%, transparent 52%, rgba(0, 0, 0, .42) 100%);
}

.ap-phone__island {
    position: absolute;
    top: 11px;
    left: 50%;
    translate: -50% 0;
    width: 82px;
    height: 24px;
    border-radius: 999px;
    background: #01060D;
    box-shadow: inset 0 -1px 2px rgba(141, 196, 255, .16);
}

/* --- status bar ----------------------------------------------------------- */
.ap-screen__bar {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: space-between;
    height: 24px;
    padding: 0 6px;
    margin-bottom: 14px;
    color: #E8F2FF;
}

.ap-bar__time {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .01em;
    /* A clock is a clock in any locale. */
    direction: ltr;
}

.ap-bar__icons {
    width: 46px;
    height: 12px;
}

/* --- the icon grid -------------------------------------------------------- */
.ap-screen__grid {
    position: relative;
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 14px 9px;
    align-content: start;
}

.ap-slot {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 5px;
}

.ap-slot__tile {
    position: relative;
    display: grid;
    place-items: center;
    width: 100%;
    aspect-ratio: 1;
    border-radius: 26%;
    background: linear-gradient(160deg, rgba(150, 200, 255, .17), rgba(120, 170, 235, .07));
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .13),
        0 2px 5px rgba(0, 0, 0, .3);
    overflow: hidden;
}

/* The gloss every app icon has: light gathering along the top edge. */
.ap-slot__tile::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: linear-gradient(180deg, rgba(255, 255, 255, .16), rgba(255, 255, 255, 0) 46%);
}

/* Four tints and four marks, cycled — enough variety that the screen reads as
   somebody's phone rather than a wireframe, quiet enough that ours still leads.
   `--ours` is excluded from all of it. */
.ap-slot:not(.ap-slot--ours):nth-child(4n+2) .ap-slot__tile {
    background: linear-gradient(160deg, rgba(94, 210, 236, .18), rgba(94, 210, 236, .06));
}

.ap-slot:not(.ap-slot--ours):nth-child(4n+3) .ap-slot__tile {
    background: linear-gradient(160deg, rgba(141, 196, 255, .13), rgba(60, 110, 180, .07));
}

.ap-slot:not(.ap-slot--ours):nth-child(4n) .ap-slot__tile {
    background: linear-gradient(160deg, rgba(61, 214, 140, .13), rgba(61, 214, 140, .04));
}

.ap-slot:not(.ap-slot--ours) .ap-slot__tile::before {
    content: "";
    position: relative;
    width: 42%;
    height: 42%;
    border-radius: 50%;
    /* Tinted to its own tile rather than one grey for all. The difference is
       barely nameable and it is most of what stops the grid looking printed. */
    background: var(--mk, rgba(226, 240, 255, .22));
}

.ap-slot:not(.ap-slot--ours):nth-child(4n+2) .ap-slot__tile { --mk: rgba(160, 235, 250, .26); }
.ap-slot:not(.ap-slot--ours):nth-child(4n+3) .ap-slot__tile { --mk: rgba(186, 218, 255, .24); }
.ap-slot:not(.ap-slot--ours):nth-child(4n) .ap-slot__tile   { --mk: rgba(150, 235, 195, .24); }

.ap-slot:not(.ap-slot--ours):nth-child(3n) .ap-slot__tile::before {
    width: 44%;
    height: 12%;
    border-radius: 999px;
    box-shadow: 0 7px 0 var(--mk, rgba(226, 240, 255, .22));
}

.ap-slot:not(.ap-slot--ours):nth-child(5n) .ap-slot__tile::before {
    width: 40%;
    height: 40%;
    border-radius: 22%;
    rotate: 45deg;
}

.ap-slot:not(.ap-slot--ours):nth-child(7n) .ap-slot__tile::before {
    width: 46%;
    height: 46%;
    border-radius: 50% 50% 50% 4px;
}

/* --- ours ---
   The only lit thing on the screen, the only one with a name, and the only one
   wearing the mark's cut corners. */
.ap-slot--ours { position: relative; }

.ap-slot--ours .ap-slot__tile {
    --ch: 9px;
    border-radius: 0;
    background: var(--ap-grad);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .45),
        0 10px 22px -4px rgba(0, 123, 255, .75);
    overflow: visible;
}

/* The icon throws light onto the wallpaper around it. */
.ap-slot--ours .ap-slot__tile::before {
    content: "";
    position: absolute;
    inset: -46%;
    z-index: -1;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(28, 138, 255, .55), rgba(28, 138, 255, 0) 68%);
}

/* A badge, because a live app has one. Conventionally red — but red is not in
   the house set and this page holds to it, and on a trading app mint is the
   right word anyway. */
.ap-slot__badge {
    position: absolute;
    top: -3px;
    inset-inline-end: -3px;
    width: 11px;
    height: 11px;
    border-radius: 50%;
    background: var(--ap-mint);
    box-shadow: 0 0 0 2px rgba(6, 15, 28, .92), 0 0 10px rgba(61, 214, 140, .8);
}

.ap-slot--ours .ap-slot__tile img {
    width: 66%;
    height: 66%;
    object-fit: contain;
    filter: drop-shadow(0 1px 2px rgba(0, 30, 70, .45));
}

.ap-slot__label {
    color: #E4EFFF;
    font-size: 8.5px;
    line-height: 1;
    white-space: nowrap;
    text-shadow: 0 1px 2px rgba(0, 0, 0, .6);
}

/* --- our widget -----------------------------------------------------------
   Two by two, and the only thing on the screen that says what the app is FOR.
   No words in it on purpose: a mark, a rising line and a delta read the same in
   every locale, and a widget full of English on a Persian page would not. */
.ap-slot--widget {
    grid-column: 1 / span 2;
    grid-row: 3 / span 2;
}

.ap-widget {
    display: flex;
    flex-direction: column;
    width: 100%;
    height: 100%;
    padding: 9px 10px;
    border-radius: 20px;
    background: linear-gradient(160deg, rgba(28, 138, 255, .19), rgba(7, 30, 60, .5));
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .16),
        0 4px 12px rgba(0, 0, 0, .35);
    backdrop-filter: blur(6px);
    overflow: hidden;
}

.ap-widget__top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 6px;
}

.ap-widget__mark {
    width: 18px;
    height: 18px;
    object-fit: contain;
    opacity: .95;
}

/* The delta: an up-tick in mint, drawn rather than written. */
.ap-widget__delta {
    width: 0;
    height: 0;
    border-inline: 4.5px solid transparent;
    border-bottom: 7px solid #3DD68C;
    filter: drop-shadow(0 0 5px rgba(61, 214, 140, .7));
}

.ap-widget__spark {
    width: 100%;
    height: 42%;
    margin-top: auto;
    overflow: visible;
}

.ap-widget__area { fill: rgba(94, 210, 236, .2); }

.ap-widget__line {
    fill: none;
    stroke: #62CFE6;
    stroke-width: 1.8;
    stroke-linecap: round;
    stroke-linejoin: round;
}

/* --- dock ----------------------------------------------------------------- */
.ap-screen__dots {
    display: flex;
    justify-content: center;
    gap: 6px;
    margin: auto auto 12px;
}

.ap-screen__dots i {
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: rgba(226, 240, 255, .28);
}

.ap-screen__dots i.is-on { background: rgba(226, 240, 255, .85); }

.ap-screen__dock {
    position: relative;
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 9px;
    padding: 9px;
    border-radius: 28px;
    background: rgba(180, 215, 255, .12);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1);
    backdrop-filter: blur(8px);
}

.ap-screen__dock .ap-slot__tile {
    background: linear-gradient(160deg, rgba(160, 205, 255, .2), rgba(120, 170, 235, .09));
}

.ap-screen__dock .ap-slot__tile::before {
    content: "";
    width: 42%;
    height: 42%;
    border-radius: 50%;
    background: rgba(233, 244, 255, .18);
}

.ap-screen__dock .ap-slot__tile:nth-child(2)::before { border-radius: 22%; rotate: 45deg; }
.ap-screen__dock .ap-slot__tile:nth-child(3)::before { width: 44%; height: 12%; border-radius: 999px; box-shadow: 0 7px 0 rgba(233, 244, 255, .18); }
.ap-screen__dock .ap-slot__tile:nth-child(4)::before { border-radius: 50% 50% 50% 4px; }

.ap-phone__home {
    position: relative;
    width: 108px;
    height: 4px;
    margin: 9px auto 0;
    border-radius: 999px;
    background: rgba(233, 244, 255, .5);
}

/* =============================================================================
   4. Motion
   -----------------------------------------------------------------------------
   One idea, once: the icon lands on the home screen. Everything else is still.
   ========================================================================== */

@media (prefers-reduced-motion: no-preference) {
    .ap-slot--ours {
        animation: ap-land .7s cubic-bezier(.22, 1.4, .4, 1) .35s both;
    }

    .ap-slot--ours .ap-slot__tile::after {
        content: "";
        position: absolute;
        inset: 0;
        background: inherit;
        opacity: .5;
        animation: ap-pulse 2.8s ease-out 1.2s infinite;
    }

    .ap-slot--ours .ap-slot__tile { position: relative; }
}

@keyframes ap-land {
    from { opacity: 0; translate: 0 -22px; scale: .82; }
    to   { opacity: 1; translate: 0 0; scale: 1; }
}

@keyframes ap-pulse {
    0%   { opacity: .45; scale: 1; }
    70%  { opacity: 0; scale: 1.5; }
    100% { opacity: 0; scale: 1.5; }
}

/* =============================================================================
   5. Wider viewports
   ========================================================================== */

@media (min-width: 992px) {
    .ap-layout {
        /* Explicit columns and a centred track, so the pair reads as one
           composition rather than as two things pushed to opposite edges. */
        grid-template-columns: minmax(0, 540px) auto;
        justify-content: center;
        gap: 80px;
        justify-items: start;
        text-align: start;
    }

    .ap-title { font-size: 34px; }
    .ap-plat { justify-content: flex-start; }

    .ap-phone { width: 288px; }
    .ap-phone__screen { height: 452px; }

    .ap-stage__halo { width: 340px; height: 380px; }
}

@media (max-width: 991.98px) {
    .ap-app { margin-top: 64px; }

    /* The device leads on a narrow screen: it is the fastest way to say what
       the section is about, and the copy reads under it. */
    .ap-stage { order: -1; }
}

@media (prefers-reduced-motion: reduce) {
    .ap-app * { transition: none !important; }
}
