/* Phone and small-tablet layer.
   ------------------------------------------------------------------
   The marketing pages are composed in `vw` against a 1440–1536px board,
   which is right for a fixed cinematic composition and wrong for a phone:
   at 375px one vw is 3.75px, so a 1.04vw label lands at 3.9px. Nothing
   overflowed — it just shrank until it could not be read.

   So this file does not "shrink the desktop". It restates each surface at
   phone scale: one column, thumb-sized targets, type on a real px ramp,
   and the desktop-only chrome (the glass dashboard mock, the mirrored
   trail, the pinned glass break) retired where it cannot be read.

   Loaded last, so it wins ties without needing !important.

   Breakpoints
     1024px — tablet: multi-column grids halve, sidebars stay
      860px — phone: single column, drawer navigation, px type ramp
      520px — small phone: tighter gutters, 2-up becomes 1-up
   ================================================================== */

:root {
  /* One gutter value for every mobile surface, so nothing sits on its own
     margin. Grows slightly on larger phones. */
  --m-pad: 20px;
  --m-gap: 14px;
  --m-radius: 16px;
  /* Notch / home-indicator awareness. Falls back to 0 everywhere else. */
  --m-safe-t: env(safe-area-inset-top, 0px);
  --m-safe-b: env(safe-area-inset-bottom, 0px);
}

/* Mobile-only chrome. Present in the markup at every width so the shells
   stay one template; it only becomes visible where it is needed. */
.navburger,
.navscrim,
.topsheet,
.tabbar {
  display: none;
}

/* NB: `.histrow__watch` is NOT hidden here anymore — the owner asked for
   Play/View beside Download on the My Assets rows at every width
   (2026-07-25). Desktop columns live in propai.css; the phone block below
   only repositions it. */

/* NB: `.vidcard__acts` is NOT hidden here anymore — the owner asked for
   Play + Download on the My Videos cards at every width. Desktop styling
   lives in app-pages.css; the phone override below only resizes it. */

/* ==================================================================
   1. TABLET — 1024px and down
   Halve the widest grids so cards keep a readable measure. The sidebars
   and the vw composition still hold at this size.
   ================================================================== */

@media (max-width: 1024px) {
  .tools4,
  .grid10,
  .trust,
  .footer__cols,
  .steps,
  .plp__proof,
  .dstudio,
  .dfeat,
  .toolgrid,
  .vidgrid,
  .recents,
  .workrow,
  .packgrid,
  .pget5,
  .pchoice5,
  .psteps4,
  .rooms4,
  .order4 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .tmpls,
  .create3,
  .stats3,
  .hs-topics,
  .pfeats3,
  .plp__tools,
  .plp__steps,
  .plp__packs {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .app {
    grid-template-columns: 190px minmax(0, 1fr);
  }

  .pai {
    grid-template-columns: 200px minmax(0, 1fr);
  }

  .main {
    padding: 20px 24px 36px;
  }
}

/* ==================================================================
   2. PHONE — 860px and down
   ================================================================== */

@media (max-width: 860px) {
  /* iOS bumps font sizes in landscape unless told not to; the ramp below
     is deliberate and should survive rotation. */
  html {
    -webkit-text-size-adjust: 100%;
  }

  /* Locked while a nav drawer is open, so the page behind cannot be
     rubber-banded out from under it. */
  html.nav-open,
  html.nav-open body {
    overflow: hidden;
  }

  /* iOS Safari zooms the viewport when a focused field's text is under
     16px, and never zooms back out — the rest of the page is then off
     screen. 16px is the floor for anything typed into.

     The `:is(:enabled, :disabled)` tail is there for specificity: it adds a
     pseudo-class so this outranks the class rules that set 13–14px, without
     having to name every field in the product. */
  input:is(:enabled, :disabled),
  textarea:is(:enabled, :disabled),
  select:is(:enabled, :disabled) {
    font-size: max(16px, 1em);
  }

  /* ---- 2.1 Shared mobile chrome ---------------------------------- */

  /* Hamburger. One component, used by both the dark app and PropAI —
     it inherits its colour from the shell it sits in. */
  .navburger {
    display: grid;
    place-items: center;
    width: 40px;
    height: 40px;
    padding: 0;
    border: 1px solid currentColor;
    border-radius: 11px;
    background: transparent;
    color: inherit;
    cursor: pointer;
    flex: none;
  }

  .navburger span {
    position: relative;
    display: block;
    width: 17px;
    height: 1.5px;
    border-radius: 2px;
    background: currentColor;
    transition: transform 220ms var(--ease), background-color 220ms var(--ease);
  }

  .navburger span::before,
  .navburger span::after {
    content: '';
    position: absolute;
    left: 0;
    width: 17px;
    height: 1.5px;
    border-radius: 2px;
    background: currentColor;
    transition: transform 220ms var(--ease);
  }

  .navburger span::before {
    top: -5.5px;
  }
  .navburger span::after {
    top: 5.5px;
  }

  /* Becomes a close cross while its drawer is open. */
  .navburger[aria-expanded='true'] span {
    background: transparent;
  }
  .navburger[aria-expanded='true'] span::before {
    transform: translateY(5.5px) rotate(45deg);
  }
  .navburger[aria-expanded='true'] span::after {
    transform: translateY(-5.5px) rotate(-45deg);
  }

  /* Backdrop behind an open drawer. Tap to dismiss. */
  .navscrim {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 190;
    background: rgba(4, 3, 2, 0.62);
    backdrop-filter: blur(2px);
    opacity: 0;
    pointer-events: none;
    transition: opacity 240ms var(--ease);
    border: 0;
    padding: 0;
  }

  .navscrim.is-open {
    opacity: 1;
    pointer-events: auto;
  }

  /* ---- 2.1b Bottom tab bar ---------------------------------------- */

  /* Primary navigation lives at the thumb, like a native app — not behind
     a burger in the far corner. The burger stays only on the marketing
     site (a website, not an app); inside the products the Menu/Tools tab
     opens the same drawer. */
  .tabbar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 120;
    display: flex;
    align-items: stretch;
    height: calc(58px + var(--m-safe-b));
    padding: 0 8px var(--m-safe-b);
    border-top: 1px solid rgba(255, 255, 255, 0.08);
    background: rgba(9, 7, 5, 0.94);
    -webkit-backdrop-filter: blur(18px) saturate(1.15);
    backdrop-filter: blur(18px) saturate(1.15);
  }

  .tabbar__item {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    min-width: 0;
    padding: 0;
    border: none;
    background: none;
    font-family: var(--font-ui);
    font-size: 10px;
    font-weight: 500;
    letter-spacing: 0.02em;
    color: rgba(255, 255, 255, 0.52);
    text-decoration: none;
    cursor: pointer;
    transition: color 180ms var(--ease);
  }

  .tabbar__item .icon {
    width: 20px;
    height: 20px;
  }

  .tabbar__item.is-on {
    color: var(--gold-bright);
  }

  .tabbar__item:active {
    color: rgba(255, 255, 255, 0.85);
  }

  /* Raised centre action — the one thing the product wants you to do. */
  .tabbar__fab {
    flex: 0 0 auto;
    align-self: center;
    display: grid;
    place-items: center;
    width: 46px;
    height: 46px;
    margin: 0 10px;
    border-radius: 50%;
    background: linear-gradient(150deg, var(--gold-bright), var(--gold));
    color: #1a1206;
    text-decoration: none;
    transform: translateY(calc(-10px - var(--m-safe-b) / 2));
    box-shadow:
      0 10px 22px -6px rgba(201, 160, 99, 0.55),
      0 0 0 5px #0a0806;
  }

  .tabbar__fab .icon {
    width: 19px;
  }

  .tabbar__fab:active {
    transform: translateY(calc(-10px - var(--m-safe-b) / 2)) scale(0.94);
  }

  /* Menu glyph — three short lines, drawn rather than borrowed from an
     icon that means something else. */
  .tabbar__lines {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 4px;
    width: 20px;
    height: 20px;
  }

  .tabbar__lines i {
    display: block;
    height: 1.6px;
    border-radius: 2px;
    background: currentColor;
  }

  .tabbar__lines i:nth-child(2) {
    width: 74%;
  }

  /* Light theme for the PropAI workspace. */
  .tabbar--pai {
    border-top: 1px solid var(--line, #ececee);
    background: rgba(255, 255, 255, 0.94);
  }

  .tabbar--pai .tabbar__item {
    color: #9a9ea6;
  }

  .tabbar--pai .tabbar__item.is-on {
    color: var(--gold);
  }

  .tabbar--pai .tabbar__item:active {
    color: #3a3d42;
  }

  /* Content must clear the bar. */
  .app .main {
    padding-bottom: calc(92px + var(--m-safe-b));
  }

  .pai .pmain {
    padding-bottom: calc(92px + var(--m-safe-b));
  }

  /* With the tab bar in place the header burgers are redundant chrome —
     one navigation model per screen. */
  .app .topbar .navburger,
  .pai .ptop .navburger {
    display: none;
  }

  /* ---- 2.2 Marketing header -------------------------------------- */

  .topnav {
    height: 58px;
    padding: 0 var(--m-pad);
    padding-top: var(--m-safe-t);
    gap: 10px;
  }

  .topnav__logo {
    width: 104px;
  }

  /* The desktop link row and the twin CTAs cannot both fit; the links move
     into the sheet and only the primary action stays in the bar. */
  .topnav__links,
  .topnav__login {
    display: none;
  }

  .topnav__actions {
    gap: 10px;
    margin-left: auto;
  }

  .topnav__cta {
    height: 38px;
    padding: 0 16px;
    font-size: 13px;
    border-radius: 999px;
  }

  .topnav .navburger {
    color: rgba(255, 255, 255, 0.62);
  }

  /* Full-width sheet dropping from under the header. */
  .topsheet {
    position: fixed;
    top: calc(58px + var(--m-safe-t));
    left: 0;
    right: 0;
    z-index: 195;
    display: flex;
    flex-direction: column;
    padding: 8px var(--m-pad) 18px;
    border-bottom: 1px solid var(--gold-edge);
    background: rgba(10, 8, 6, 0.94);
    backdrop-filter: blur(18px) saturate(1.2);
    transform: translateY(-8px);
    opacity: 0;
    pointer-events: none;
    transition: opacity 220ms var(--ease), transform 220ms var(--ease);
  }

  .topsheet.is-open {
    transform: translateY(0);
    opacity: 1;
    pointer-events: auto;
  }

  .topsheet a {
    display: flex;
    align-items: center;
    height: 50px;
    font-family: var(--font-ui);
    font-size: 15.5px;
    font-weight: 400;
    color: rgba(255, 255, 255, 0.82);
    text-decoration: none;
  }

  .topsheet a + a {
    border-top: 1px solid rgba(255, 255, 255, 0.07);
  }

  .topsheet a.is-active {
    color: var(--gold-bright);
  }

  /* ---- 2.3 Starting page ----------------------------------------- */

  /* Already close to right — it is a centred hero over full-bleed video.
     Only the fixed logo needed rescuing from the left edge. */
  .starting__logo {
    left: var(--m-pad);
    top: calc(20px + var(--m-safe-t));
  }

  .starting__wordmark {
    font-size: clamp(44px, 15vw, 64px);
  }

  .starting__welcome {
    font-size: 10.5px;
    letter-spacing: 0.3em;
  }

  .starting__tagline {
    padding: 0 var(--m-pad);
    font-size: 14px;
    line-height: 1.6;
  }

  .starting__scroll {
    font-size: 9.5px;
    letter-spacing: 0.28em;
  }

  /* The travelling logo lands on the header's smaller mobile mark.
     Its transform carries a fixed -25.5px at the end of the journey (it was
     tuned against a 72px desktop header), so `top` has to be that much
     lower than the 29px centre line of the 58px mobile bar. */
  .morphlogo {
    left: var(--m-pad);
    top: calc(54.5px + var(--m-safe-t));
  }

  .morphlogo__img {
    width: 132px;
  }

  /* ---- 2.4 Landing hero ------------------------------------------ */

  /* The glass dashboard mock is a 1440px composition — nine nested panels
     of 0.8vw type. At phone width it is a grey smudge, so it steps aside
     and the photograph becomes the backdrop it was always meant to be. */
  .landing-panel,
  .landing-glass,
  .ltrail__row--echo,
  .hero__skip {
    display: none !important;
  }

  /* Cover the frame rather than holding the desktop crop and offset.

     Softened on purpose. Sharp, it is a picture of an interface whose
     labels are 4px tall — present enough to try to read, too small to
     succeed, and it fights the headline sitting on top of it. Blurred and
     dimmed it becomes what it should be at this size: warm depth behind
     the words. Scaled past the frame so the blur has no visible edge. */
  .landing-dash {
    /* The desktop rule now sizes this to the 16:9 frame at left: 50% (with
       the centring -50% inside the transform, which the override below
       kills) — restore the full-bleed box the phone backdrop needs. */
    inset: 0;
    width: 100%;
    height: 100%;
    transform: scale(1.06) !important;
    object-fit: cover;
    /* Framed so the dashboard's card thumbnails land in the band between
       the copy and the feature strip — that gap is the product shot, not
       leftover space. */
    object-position: 58% 38%;
    /* No live filter: the blur(2px)/saturate/brightness grade is BAKED into
       landing-dashboard-phone.jpg (LandingPage.ts serves it on phones).
       A full-screen runtime blur was one of the compositor's biggest costs
       during the curtain scrub. */
  }

  /* A stronger scrim than the desktop one — the copy now sits directly on
     the picture instead of beside a lit panel.

     z-index 5 is the point of this rule: the desktop scrim is painted
     underneath .landing-dash (z 4), which is correct when the artwork is a
     lit panel in the middle of the frame and wrong when it is the
     full-bleed background. The hero and the trail are lifted above it.

     The ramp opens deliberately between 58% and 78%: that is the band
     under the copy and above the feature strip, and letting the photograph
     read there is what turns it from leftover black into the product shot
     the hero is selling. Dark again top and bottom, where type sits. */
  .landing::after {
    z-index: 5;
    inset: 0;
    background: linear-gradient(
      180deg,
      rgba(6, 5, 4, 0.92) 0%,
      rgba(6, 5, 4, 0.82) 20%,
      rgba(6, 5, 4, 0.74) 46%,
      rgba(6, 5, 4, 0.44) 62%,
      rgba(6, 5, 4, 0.5) 78%,
      rgba(6, 5, 4, 0.86) 100%
    );
    /* The `background` shorthand replaces the desktop photo, but the
       desktop rule's blur filter and composited masks were still APPLYING
       to this plain gradient — an invisible full-screen blur pass the
       phone GPU paid for on every frame of the curtain. */
    filter: none;
    -webkit-mask-image: none;
    mask-image: none;
  }

  /* Same trade as .landing-dash: the desktop ::before live-blurs the 2.3MB
     house PNG (blur 3px over a 124%-of-viewport layer). The phone swaps in
     landing-house-phone.jpg — 46KB with the whole grade baked — and drops
     the runtime filter. Opacity and the vignette mask stay, so the
     composite under the screen-blended backdrop is unchanged. */
  .landing::before {
    background-image: url('/landing-house-phone.jpg');
    filter: none;
  }

  .hero,
  .ltrail__row {
    z-index: 6;
  }

  /* Top-anchored, not bottom-anchored. Hanging the block off the bottom
     left 303px of dead black between the header and the first word — the
     single largest empty area on the phone. It now starts one comfortable
     gap below the bar, and the space it used to waste sits between the
     copy and the feature strip, where the product shot fills it. */
  .hero {
    top: 132px;
    bottom: auto;
    left: var(--m-pad);
    right: var(--m-pad);
    width: auto;
  }

  .hero__label {
    gap: 7px;
    font-size: 10px;
    letter-spacing: 0.2em;
  }

  .icon--sparkle {
    width: 13px;
  }

  /* Reference mock: the headline is the hero — two confident serif lines
     with "Potential." italic gold on its own line. */
  .hero__headline {
    margin: 14px 0 0;
    font-size: clamp(33px, 9.4vw, 37px);
    line-height: 1.16;
  }

  /* The desktop line break falls in the wrong place at this measure. */
  .hero__headline br,
  .hero__sub br {
    display: none;
  }

  .hero__sub {
    margin: 14px 0 0;
    max-width: 30ch;
    font-size: 15px;
    line-height: 1.65;
  }

  .hero__actions {
    gap: 12px;
    margin-top: 24px;
  }

  /* Side by side rather than stacked: two 44px rows cost less height than
     two full-width buttons, and the hero has little to spare. */
  /* Rounded rectangles per the mock, not pills — taller, calmer, easier
     to hit. The ghost picks up the gold voice instead of neutral white. */
  .btn {
    flex: 1 1 0;
    gap: 8px;
    height: 52px;
    border-radius: 14px;
    font-size: 14.5px;
  }

  .btn--gold,
  .btn--ghost {
    width: auto;
  }

  .btn--ghost {
    border-color: rgba(201, 160, 99, 0.45);
    color: var(--gold-bright);
  }

  .icon--arrow {
    width: 15px;
  }

  .proof {
    gap: 14px;
    margin-top: 24px;
  }

  .proof__face {
    width: 38px;
    height: 38px;
  }

  .proof__text {
    font-size: 14px;
    line-height: 1.5;
  }

  /* The feature trail becomes a 2x2 plate pinned to the bottom of the
     hero — same four claims, at a size a thumb and an eye can both use. */
  /* Grouped directly beneath the hero, not pinned to the floor.

     Pinned to the bottom it left a tall band of unlit dashboard between the
     copy and the cards — two disconnected clusters with a void between. A
     fixed top just below the hero's own bottom keeps hero and cards reading
     as one block; the space that frees up falls to the bottom of the frame,
     where the lit villa fills it. Very short screens (which cannot fit both)
     drop the row entirely in the short-viewport block below. */
  .ltrail__row {
    /* Just below the hero's proof row (hero ends ≈438 at the mock's type
       scale, stable across phone widths since the headline is a fixed two
       lines). */
    top: 466px;
    bottom: auto;
    left: var(--m-pad);
    right: var(--m-pad);
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
  }

  /* Full cards per the mock, not chips: outlined icon tile on top, title
     with a gold arrow, description underneath. The desktop row is a
     divider-separated strip; this restacks each item as a column. */
  .ltrail__item,
  .ltrail__item:first-child {
    flex-direction: column;
    align-items: stretch;
    gap: 12px;
    padding: 16px 14px 18px;
    border: 1px solid rgba(201, 160, 99, 0.15);
    border-left: 1px solid rgba(201, 160, 99, 0.15);
    border-radius: 16px;
    background: rgba(13, 10, 8, 0.62);
    backdrop-filter: blur(6px);
  }

  .ltrail__item + .ltrail__item {
    border-left-color: rgba(201, 160, 99, 0.15);
  }

  /* Outlined tile, gold glyph — the mock's icon treatment. */
  .ltrail__icon {
    width: 40px;
    height: 40px;
    border-radius: 12px;
    border: 1px solid rgba(201, 160, 99, 0.4);
    background: rgba(201, 160, 99, 0.05);
  }

  .ltrail__icon svg {
    width: 18px;
  }

  .ltrail__text {
    gap: 6px;
  }

  .ltrail__title {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    font-size: 15px;
    line-height: 1.3;
  }

  /* The go-arrow beside each title. Drawn, not markup — the desktop strip
     has no arrows and must not grow one. */
  .ltrail__title::after {
    content: '→';
    flex: none;
    font-weight: 400;
    color: var(--gold);
  }

  .ltrail__sub {
    font-size: 12px;
    line-height: 1.5;
    white-space: normal;
  }

  /* ---- 2.5 Suite section (.second) ------------------------------- */

  /* The mock's hero layout fills the frame (cards end ≈780 of 812), so
     the big pull-up that closed the old empty band is gone — it would
     cover the cards now. A small tuck keeps the handoff snug. */
  .second {
    margin-top: -16px;
    padding: 60px var(--m-pad) 44px;
  }

  /* Decorative corner flourishes are drawn for a 1536px board; at phone
     width they read as stray marks across the headline. */
  .flourish {
    display: none;
  }

  .second__badge {
    height: 26px;
    padding: 0 12px;
    font-size: 10px;
    letter-spacing: 0.16em;
  }

  .second__headline {
    font-size: clamp(23px, 6.6vw, 27px);
    line-height: 1.2;
  }

  .second__headline br {
    display: none;
  }

  .second__sub {
    font-size: 13.5px;
    line-height: 1.65;
    color: rgba(255, 255, 255, 0.55);
  }

  .studios {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--m-gap);
  }

  .studio {
    padding: 16px;
    border-radius: var(--m-radius);
  }

  .studio__head {
    gap: 12px;
  }

  .studio__tile {
    width: 42px;
    height: 42px;
    border-radius: 12px;
  }

  .studio__tile .icon {
    width: 20px;
  }

  .studio__title {
    font-size: 16px;
  }

  .studio__desc {
    font-size: 12.5px;
    line-height: 1.5;
  }

  .studio__go {
    width: 38px;
    height: 38px;
  }

  .studio__go .icon {
    width: 14px;
  }

  /* Feature list above, media below — side by side leaves neither enough
     room to be worth showing. */
  .studio__body {
    grid-template-columns: minmax(0, 1fr);
    gap: 14px;
    height: auto;
  }

  .media {
    height: 146px;
    border-radius: 12px;
  }

  .media__play {
    width: 44px;
    height: 44px;
  }

  .media__play .icon {
    width: 16px;
  }

  .media__wave {
    height: 22px;
  }

  .media__chip {
    width: 32px;
    height: 32px;
  }

  .media__chip .icon {
    width: 13px;
  }

  .feats {
    gap: 12px;
  }

  .feat {
    gap: 10px;
  }

  .feat__tile {
    width: 28px;
    height: 28px;
    border-radius: 8px;
  }

  .feat__tile .icon {
    width: 13px;
  }

  .feat__title {
    font-size: 13.5px;
  }

  .feat__sub {
    font-size: 11.5px;
    line-height: 1.45;
  }

  .studio__strip {
    gap: 11px;
    padding: 12px 14px;
  }

  .strip__spark .icon {
    width: 17px;
  }

  .strip__title {
    font-size: 13px;
  }

  .strip__sub {
    font-size: 11.5px;
    line-height: 1.45;
  }

  /* ---- 2.6 Tool cards -------------------------------------------- */

  .tools4 {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--m-gap);
  }

  .tool {
    gap: 11px;
    padding: 16px;
    border-radius: var(--m-radius);
  }

  .tool__title {
    font-size: 15.5px;
  }

  .tool__desc {
    max-width: none;
    font-size: 12.5px;
    line-height: 1.55;
  }

  .tool__go {
    width: 34px;
    height: 34px;
  }

  .tool__go .icon {
    width: 13px;
  }

  .tool__panel {
    padding: 12px;
    border-radius: 12px;
  }

  /* The embedded product mocks are the part that suffers most — every one
     of them is a miniature dashboard. Restated at legible sizes. */
  .adshot {
    height: 100px;
  }

  .adshot__generate {
    right: 8px;
    padding: 5px 11px;
    font-size: 11px;
  }

  .adchip {
    gap: 7px;
    font-size: 12px;
  }

  .fbdot {
    width: 20px;
    height: 20px;
    font-size: 11px;
  }

  .adstats {
    gap: 8px;
  }

  .adstat {
    gap: 3px;
    padding: 10px;
  }

  .adstat i,
  .adstat em {
    font-size: 10.5px;
  }

  .adstat b {
    font-size: 15px;
  }

  .adstat em .icon {
    width: 9px;
  }

  .mkt__label,
  .mkt__cap {
    font-size: 11px;
  }

  .mkt__price {
    font-size: 17px;
  }

  .mkt__line {
    width: 78px;
    height: 30px;
  }

  .mkt__delta {
    font-size: 11px;
  }

  .mkt__delta .icon {
    width: 9px;
  }

  .locs {
    gap: 9px;
  }

  .loc {
    gap: 8px;
  }

  .loc__dot {
    width: 14px;
    height: 14px;
  }

  .loc__name,
  .loc__price {
    font-size: 12px;
  }

  .loc__meter {
    width: 44px;
    height: 4px;
  }

  .mba {
    gap: 8px;
  }

  .mba__shot {
    height: 84px;
  }

  .mba__tag {
    top: 6px;
    left: 6px;
    gap: 4px;
    padding: 3px 7px;
    font-size: 9.5px;
  }

  .mba__tag .icon {
    width: 8px;
  }

  .tracks {
    gap: 7px;
  }

  .tracks__ruler {
    gap: 6px;
    height: 14px;
  }

  .tracks__ruler i {
    height: 6px;
  }

  .tracks__ruler .icon {
    width: 9px;
  }

  .tracks__playhead {
    top: 18px;
  }

  /* Motion Edit — four named tracks. The label column was sized in `em`
     against a 0.65vw font, so it collapsed along with the type. */
  .track4 {
    grid-template-columns: auto 5.2em minmax(0, 1fr);
    gap: 7px;
  }

  .track4__ico {
    width: 10px;
    height: 10px;
  }

  .track4__name {
    font-size: 11px;
  }

  .track4__lane {
    height: 12px;
    border-radius: 3px;
  }

  .track4__bar {
    border-radius: 3px;
  }

  /* Video Insights — link bar, analysis ticks, generated prompt. */
  .vlink {
    gap: 7px;
    margin-top: 8px;
    font-size: 11.5px;
  }

  .vflow .icon {
    width: 12px;
  }

  .vgrid {
    gap: 8px;
  }

  .vpanel {
    gap: 6px;
  }

  .vcheck {
    gap: 5px;
    font-size: 11px;
  }

  .vcheck .icon {
    width: 10px;
  }

  .vprompt {
    font-size: 11px;
    line-height: 1.5;
  }

  /* ---- 2.7 Built-for chips --------------------------------------- */

  .builtfor {
    margin-top: 34px;
  }

  .builtfor__label {
    gap: 8px;
    font-size: 10px;
    letter-spacing: 0.16em;
  }

  .builtfor__label i {
    width: 3px;
    height: 3px;
  }

  /* Wraps to as many rows as it needs rather than compressing five chips
     into one line of 4px type. */
  .builtfor__row {
    flex-wrap: wrap;
    justify-content: center;
    gap: 9px;
  }

  .chip {
    gap: 7px;
    height: 38px;
    padding: 0 14px;
    font-size: 12.5px;
  }

  .chip .icon {
    width: 14px;
  }

  /* ---- 2.8 Vision cards ------------------------------------------ */

  /* The desktop plate is one tall card beside two stacked ones. On a phone
     that becomes three equal cards in a column — the L-shape carries no
     meaning once it is only 375px wide. */
  .vision3 {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto;
    gap: var(--m-gap);
    height: auto;
    min-height: 0;
    margin-top: 26px;
  }

  .vcard {
    border-radius: var(--m-radius);
    min-height: 178px;
  }

  .vcard--land {
    grid-row: auto;
    min-height: 224px;
  }

  /* Land Vision is a full-bleed photograph with its copy laid on top. The
     desktop card is tall and narrow, so the title fell on the dark barren
     half of the plate; at phone proportions the same copy lands on the lit
     villa. It gets the scrim the interior card already has. */
  .vcard--land::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 1;
    background: linear-gradient(
      180deg,
      rgba(7, 5, 4, 0.88) 0%,
      rgba(7, 5, 4, 0.5) 32%,
      rgba(7, 5, 4, 0.12) 55%,
      rgba(7, 5, 4, 0.55) 88%,
      rgba(7, 5, 4, 0.78) 100%
    );
    pointer-events: none;
  }

  /* Land only — the other two lay their copy out in flow, and lifting them
     out of it drops the text on top of their own artwork. */
  .vcard--land .vcard__copy {
    position: absolute;
    z-index: 2;
    top: 16px;
    left: 16px;
    right: 60px;
  }

  /* Interior stacks copy over the full-bleed shot; its 56% cap was cut for a
     wide card and leaves a two-word column here. */
  .vcard--interior .vcard__copy {
    position: relative;
    max-width: none;
    height: 100%;
    gap: 8px;
    padding: 18px;
  }

  /* Agent keeps copy beside a strip of three presenters on desktop. Below
     the fold of a phone that strip is 120px wide; copy above, faces below. */
  .vcard--agent {
    grid-template-columns: minmax(0, 1fr);
    gap: 12px;
    padding: 16px;
  }

  .vcard--agent .vcard__copy {
    position: relative;
    gap: 6px;
  }

  /* The presenter strip is the second grid row. With the card held at a
     min-height the row was allotted whatever was left — 23px — and four
     full-body plates were clipped to a band of shoulders. Give the row a
     real height and let the card grow to it. */
  .vcard--agent {
    min-height: 0;
    grid-template-rows: auto 172px;
  }

  .vcard__faces {
    gap: 7px;
  }

  .vcard__faces i {
    border-radius: 8px;
  }

  .vcard__title,
  .vcard--interior .vcard__title,
  .vcard--agent .vcard__title {
    font-size: 18px;
  }

  .vcard__desc {
    margin-top: 6px;
    font-size: 12.5px;
    line-height: 1.5;
  }

  .vcard__go {
    top: 14px;
    right: 14px;
    width: 34px;
    height: 34px;
  }

  .vcard__go .icon {
    width: 13px;
  }

  .vcard__play {
    width: 42px;
    height: 42px;
  }

  .vcard__play .icon {
    width: 14px;
  }

  .explore,
  .vcard--land > .explore {
    left: 16px;
    bottom: 16px;
    gap: 7px;
    height: 38px;
    padding: 0 16px;
    font-size: 12.5px;
  }

  .explore .icon {
    width: 13px;
  }

  /* ---- 2.9 How it works / trust / pricing (.fourth) --------------- */

  /* Was locked to 100vh, which is why the pricing panel rendered as a tall
     empty gold box with a paragraph in the corner. It is a content page;
     it should be as tall as its content. */
  .fourth {
    height: auto;
    min-height: 0;
    padding: 56px var(--m-pad) 48px;
    gap: 40px;
  }

  .eyebrow {
    gap: 7px;
    font-size: 10px;
    letter-spacing: 0.16em;
  }

  .eyebrow i {
    width: 3px;
    height: 3px;
  }

  .fourth__headline,
  .fourth__headline--sm {
    font-size: clamp(22px, 6.4vw, 26px);
    line-height: 1.2;
  }

  .fourth__headline br {
    display: none;
  }

  .fourth__sub {
    font-size: 14px;
    line-height: 1.65;
  }

  .hiw {
    grid-template-columns: minmax(0, 1fr);
    gap: 26px;
  }

  .steps {
    grid-template-columns: minmax(0, 1fr);
    gap: 12px;
  }

  .step {
    padding: 15px 14px;
    border-radius: 14px;
  }

  /* The connecting hairlines run between columns; in a stack they point at
     nothing. */
  .step__link {
    display: none;
  }

  .step__tile {
    width: 40px;
    height: 40px;
    border-radius: 12px;
  }

  .step__tile .icon {
    width: 18px;
  }

  .step__n {
    top: 16px;
    right: 16px;
    font-size: 18px;
  }

  .step__title {
    font-size: 15px;
  }

  .step__desc {
    font-size: 12.5px;
    line-height: 1.55;
  }

  /* The block carries its own border, so the columns need inner padding —
     on desktop the four columns get it from their own `padding: 0 2.3vw`. */
  .trust {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 22px 18px;
    padding: 24px 18px;
  }

  .trust__col {
    padding: 0;
  }

  /* The vertical rules divided four columns; with two they land in the
     middle of the row and read as noise. */
  .trust__col + .trust__col {
    border-left: 0;
  }

  .trust__icon .icon {
    width: 19px;
  }

  .trust__title {
    font-size: 14px;
  }

  .trust__desc {
    font-size: 12px;
    line-height: 1.5;
  }

  .pricing {
    grid-template-columns: minmax(0, 1fr);
    gap: 24px;
  }

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

  .perk {
    gap: 8px;
  }

  .perk + .perk {
    border-left: 0;
    padding-left: 0;
  }

  .perk__icon .icon {
    width: 16px;
  }

  .perk__label {
    font-size: 12px;
  }

  .bonus {
    height: auto;
    padding: 20px 18px 22px;
    border-radius: var(--m-radius);
    text-align: left;
  }

  /* A 55%-wide, 140%-tall glow anchored off the right edge — on a narrow
     card it covers the CTA. */
  .bonus::after {
    display: none;
  }

  .bonus__pill {
    height: 26px;
    padding: 0 12px;
    font-size: 10px;
  }

  .bonus__title {
    font-size: 19px;
    line-height: 1.3;
  }

  .bonus__title br {
    display: none;
  }

  /* Quieter CTA — ~30% smaller by area than the 40px version (32×~170 vs
     40×~200). 32px is the floor for a touch target; going shorter starts
     costing taps. */
  .bonus__cta {
    gap: 7px;
    height: 32px;
    /* fourth.css floors this at 36px/13px for narrow desktop windows —
       lift both floors or the 32px height silently loses. */
    min-height: 32px;
    padding: 0 14px;
    font-size: 11.5px;
  }

  .bonus__cta .icon {
    width: 11px;
    min-width: 11px;
  }

  /* Two clauses joined by a dot; one line of it is wider than the card,
     and the desktop nowrap clips it instead of wrapping. Fine print is
     allowed to look like fine print. */
  .bonus__note {
    flex-wrap: wrap;
    white-space: normal;
    font-size: 10px;
    line-height: 1.55;
    letter-spacing: 0.02em;
    color: rgba(255, 255, 255, 0.42);
  }

  .bonus__note .icon {
    width: 12px;
  }

  .bonus__dot {
    width: 3px;
    height: 3px;
  }

  /* The floating gem is positioned against the desktop pricing split. */
  .fourth .gem {
    display: none;
  }

  /* ---- 2.10 Footer ------------------------------------------------ */

  .footer {
    padding: 40px var(--m-pad) calc(26px + var(--m-safe-b));
  }

  .footer__top {
    grid-template-columns: minmax(0, 1fr);
    gap: 28px;
  }

  /* The footer brand becomes the same wordmark artwork the header uses —
     the gold "L" tile + typed LUMIQ read as a different logo, and the tile
     was outsized next to phone-scale text. Drawn with ::before so the
     desktop markup (badge + word) stays untouched. */
  .footer__badge,
  .footer__word {
    display: none;
  }

  .footer__mark::before {
    content: '';
    display: block;
    width: 104px;
    aspect-ratio: 1138 / 229;
    background-image: url('/lumiq-logo.png');
    background-size: contain;
    background-position: left center;
    background-repeat: no-repeat;
  }

  .footer__line {
    font-size: 13px;
  }

  .footer__note {
    font-size: 11.5px;
    line-height: 1.55;
  }

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

  .footer__colTitle {
    font-size: 10px;
    letter-spacing: 0.16em;
  }

  .footer__link {
    font-size: 13px;
    /* A link in a list needs a tap target, not just a line of text. */
    padding: 5px 0;
  }

  .footer__base {
    flex-direction: column;
    align-items: flex-start;
    gap: 12px;
  }

  .footer__copy,
  .footer__top-link {
    font-size: 11.5px;
  }

  .footer__top-link .icon {
    width: 12px;
  }

  /* Clear of the home indicator, and out from under the footer link. */
  .to-top {
    right: 16px;
    bottom: calc(16px + var(--m-safe-b));
    width: 44px;
    height: 44px;
  }

  /* ---- 2.11 Signed-in app (dark) --------------------------------- */

  /* The sidebar was a 220px grid column. At 375px that column plus the
     content column meant the content began off-screen. It becomes an
     off-canvas drawer instead. */
  .app {
    grid-template-columns: minmax(0, 1fr);
  }

  .side {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 200;
    width: min(292px, 84vw);
    height: 100dvh;
    padding: calc(20px + var(--m-safe-t)) 16px calc(18px + var(--m-safe-b));
    overflow-y: auto;
    overscroll-behavior: contain;
    border-right: 1px solid var(--gold-edge);
    box-shadow: 24px 0 60px -30px rgba(0, 0, 0, 0.9);
    transform: translateX(-101%);
    transition: transform 280ms var(--ease);
    visibility: hidden;
  }

  .side.is-open {
    transform: translateX(0);
    visibility: visible;
  }

  /* Full-height rows are easier to hit than 40px ones on glass. */
  .snav {
    height: 46px;
    font-size: 14.5px;
  }

  .main {
    padding: 0 var(--m-pad) 40px;
  }

  /* Burger | actions on the first row, page title spanning the second.
     Sticky, because the credit balance and notifications are the two
     things you reach for mid-scroll.

     Scoped to `.app` to outrank app-popovers.css's `.app .topbar`, which
     pins this to `position: relative`.

     The frost is deliberately dropped. `backdrop-filter` makes an element a
     containing block for its fixed-position descendants, and the popovers
     below need to escape this bar to become full-width sheets. An opaque
     bar behaves identically here — nothing shows through a 92%-black blur
     that would not show through solid black — and it is cheaper to
     composite while scrolling. */
  .app .topbar {
    position: sticky;
    top: 0;
    z-index: 80;
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    gap: 14px 12px;
    margin: 0 calc(var(--m-pad) * -1) 20px;
    padding: calc(10px + var(--m-safe-t)) var(--m-pad) 14px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.07);
    background: #0b0907;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }

  .topbar .navburger {
    grid-column: 1;
    grid-row: 1;
    color: rgba(255, 255, 255, 0.5);
  }

  .topbar__right {
    grid-column: 2;
    grid-row: 1;
    justify-content: flex-end;
    gap: 9px;
  }

  .topbar > div:not(.topbar__right) {
    grid-column: 1 / -1;
    grid-row: 2;
  }

  /* Header actions that belong to a page (Upload, New project…) would push
     the row past the viewport; they live in the page body on mobile. */
  .topbar__right > .btn-gold,
  .topbar__right > .btn-ghost {
    display: none;
  }

  .topbar__eyebrow {
    font-size: 10px;
    letter-spacing: 0.18em;
  }

  /* A page title is a label, not a poster — 21px reads instantly and
     gives the screen back to its content. */
  .topbar__title {
    font-size: 21px;
  }

  .topbar__title--sans {
    font-size: 18px;
  }

  .topbar__sub {
    margin-top: 4px;
    font-size: 12.5px;
    line-height: 1.5;
    color: rgba(255, 255, 255, 0.48);
  }

  /* Number and gem only — "Credits" is legible from the context. */
  .creditpill {
    height: 34px;
    padding: 0 11px;
    gap: 6px;
    font-size: 0;
  }

  .creditpill b {
    font-size: 12.5px;
  }

  .creditpill .plus {
    font-size: 15px;
  }

  .who__name {
    display: none;
  }

  .who .icon {
    display: none;
  }

  .sechead {
    margin: 24px 0 12px;
  }

  .sechead h2 {
    font-size: 15px;
  }

  .seclink {
    font-size: 12.5px;
  }

  /* Every multi-column app grid collapses. Listed explicitly rather than
     with a wildcard so a future two-up stays two-up if it should. */
  .tmpls,
  .recents,
  .workrow,
  .vidgrid,
  .toolgrid,
  .create3,
  .stats3,
  .drops,
  .credtop,
  .dash-split,
  .setgrid,
  .fifagen__cols,
  .fifagen__fmt,
  .hs-topics,
  .hs-grid,
  .lgn__wrap,
  .perkbar {
    grid-template-columns: minmax(0, 1fr);
  }

  .packgrid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
    margin-top: 24px;
  }

  /* My Videos — finished cards show Play + Download in the open. The
     kebab stays for the rest of the menu. */
  .vidcard__acts {
    display: flex;
    gap: 7px;
    /* Clear air between the READY badge line and the buttons. */
    padding: 12px 12px 3px;
  }

  .vidcard__act {
    flex: 1 1 0;
    height: 30px;
    gap: 5px;
    padding: 0;
    font-size: 11px;
    font-weight: 500;
  }

  .vidcard__act .icon {
    width: 11px;
  }

  /* Wizard rail. Three steps with labels and captions need ~500px; only
     the step you are on keeps its words, the rest keep their number. */
  .app .steps {
    gap: 9px;
    padding: 13px 15px;
    overflow: hidden;
  }

  .app .step {
    gap: 9px;
    min-width: 0;
  }

  .app .step__n {
    width: 27px;
    height: 27px;
    font-size: 12.5px;
  }

  .app .step:not(.is-on) .step__x {
    display: none;
  }

  .app .step__x b {
    font-size: 13px;
  }

  .app .step__x i {
    display: none;
  }

  .app .step__line {
    min-width: 12px;
  }

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

  .perkbar {
    gap: 16px;
    padding: 20px;
  }

  /* Filter tabs. A scrolling strip beats wrapping here — the row keeps its
     shape and the overflow is a familiar swipe. */
  .tabs {
    overflow-x: auto;
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }

  .tabs::-webkit-scrollbar {
    display: none;
  }

  .tab {
    flex: none;
    padding: 9px 14px;
    font-size: 13px;
    white-space: nowrap;
  }

  /* Reassurance row under the generator — three icon+label pairs at a 60px
     gap. Stacks rather than scrolls; it is read, not chosen from. */
  .trustrow {
    flex-direction: column;
    align-items: flex-start;
    gap: 12px;
  }

  /* Settings rows: avatar, name/email, and a trailing action. The action
     wraps to its own line rather than squeezing the name it belongs to.

     `.billrow` is the same shape and needed it most — the Delete Account
     warning was rendering in an 89px column, seven lines tall. */
  .profrow,
  .setrow,
  .billrow {
    flex-wrap: wrap;
    gap: 12px 14px;
  }

  .profrow__x,
  .setrow__x {
    flex: 1 1 60%;
  }

  /* The danger block's copy is a full sentence — it takes the row to
     itself and the button sits under it. */
  .danger .billrow .setrow__x {
    flex: 1 1 100%;
  }

  /* Ready / generating bar: thumbnail, title + progress, percentage. The
     title column was 105px because the 152px still does not shrink. The
     still moves to its own line above the copy. */
  .readybar {
    flex-wrap: wrap;
    gap: 12px 14px;
  }

  .readybar__shot {
    width: 100%;
    height: 150px;
  }

  .readybar__x {
    flex: 1 1 60%;
  }

  /* Promo modal — full-height sheet rather than a centred dialog. */
  .promo__card {
    max-height: 92dvh;
    overflow-y: auto;
    overscroll-behavior: contain;
  }

  /* ---- 2.12 PropAI workspace (light) ----------------------------- */

  .pai {
    grid-template-columns: minmax(0, 1fr);
  }

  .pside {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 200;
    width: min(288px, 84vw);
    height: 100dvh;
    padding: calc(20px + var(--m-safe-t)) 14px calc(16px + var(--m-safe-b));
    overflow-y: auto;
    overscroll-behavior: contain;
    box-shadow: 24px 0 60px -34px rgba(23, 24, 26, 0.5);
    transform: translateX(-101%);
    transition: transform 280ms var(--ease);
    visibility: hidden;
  }

  .pside.is-open {
    transform: translateX(0);
    visibility: visible;
  }

  .pnav {
    height: 46px;
    font-size: 14.5px;
  }

  /* Scoped to `.pai` to outrank propai-notif.css's `.pai .ptop`, which
     pins this to `position: relative`. Frost dropped for the same reason
     as the dark app's topbar: `backdrop-filter` would make this the
     containing block for the notification sheet below, which needs the
     viewport. */
  .pai .ptop {
    position: sticky;
    top: 0;
    z-index: 60;
    gap: 10px;
    height: auto;
    min-height: 58px;
    padding: calc(8px + var(--m-safe-t)) var(--m-pad) 8px;
    background: #fff;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }

  .ptop .navburger {
    color: #8b8f96;
  }

  .ptop__right {
    gap: 8px;
    margin-left: auto;
  }

  .ptop__crumb {
    font-size: 12px;
    /* One line, ellipsed — a wrapped breadcrumb doubles the bar's height. */
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    min-width: 0;
  }

  .pdash__back span {
    display: none;
  }

  /* Burger, back, bell, EN/中文, credits and avatar came to ~440px in a
     375px bar. Each control keeps its function and loses its padding; the
     word "credits" goes, since the pill is unmistakable without it. */
  .plang b {
    padding: 5px 9px;
    font-size: 12px;
    white-space: nowrap;
  }

  .pcredits {
    gap: 6px;
    height: 32px;
    padding: 0 10px;
    font-size: 0;
    white-space: nowrap;
  }

  .pcredits [data-creditbal] {
    font-size: 12.5px;
  }

  .pdash__av,
  .pav {
    width: 30px;
    height: 30px;
  }

  /* The chevron after the avatar opens nothing on touch. */
  .ptop__right > .icon {
    display: none;
  }

  /* .pnote is a flex row whose children are bare text nodes around a <b>.
     Flex wraps each run in its own anonymous item, so at a wide measure it
     reads as one sentence and at 375px it splits into three columns
     ("New to this? Open the" / "Sample" / "tab to see…"). Block layout puts
     the run back together and the icon back on the baseline. */
  .pnote {
    display: block;
    padding: 12px 14px;
  }

  .pnote .icon {
    display: inline;
    vertical-align: -2px;
    margin-right: 7px;
  }

  .phead {
    flex-direction: column;
    align-items: flex-start;
    gap: 10px;
    padding: 18px var(--m-pad) 14px;
  }

  .phead__title {
    font-size: 20px;
  }

  .phead__sub {
    font-size: 12.5px;
    line-height: 1.55;
  }

  .pmain {
    min-width: 0;
  }

  .pgrid--rail,
  .pgrid--wide,
  /* `minmax(0, 1fr) 300px` — the fixed 300px rail ate the whole row and
     collapsed the main column to 0, which is why Smart Edit 2's dropzone
     was 42px wide and its label ran one word per line. */
  .pgrid--se2,
  .pgrid2,
  .pcol2,
  .pfields2,
  .pchoice2,
  .voicedemo,
  .pfeats3,
  .psteps4,
  .rooms4,
  .order4,
  .pget5,
  .pchoice4,
  .pchoice5,
  .hostdemo,
  .dstudio,
  .dfeat {
    grid-template-columns: minmax(0, 1fr);
  }

  /* Back up to two-up: these are picture tiles and short chips, which read
     fine at half width. `.pget5` and `.psteps4` deliberately stay in one
     column — they carry a sentence each, and at 124px that sentence broke
     to four lines. */
  .pchoice4,
  .pchoice5,
  .rooms4,
  .order4,
  .dstudio,
  .dfeat {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  /* Full-width rail sections carry a 30px desktop gutter. */
  .pgrid--se2 {
    margin-left: var(--m-pad);
    margin-right: var(--m-pad);
  }

  /* Agent Studio results. Five strips flexed into a 343px row are ~48px
     each; with the desktop's `contain` fit every full-body portrait shrank
     to a thumbnail floating mid-pill over its gradient. On phone it is a
     swipe carousel of real portrait cards — ~2.8 in view, faces kept in
     frame, chevrons retired in favour of the thumb. */
  .heads {
    gap: 8px;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
  }

  .heads::-webkit-scrollbar {
    display: none;
  }

  .heads__nav {
    display: none;
  }

  .heads__shot {
    flex: 0 0 32%;
    height: 154px;
    border-radius: 12px;
    background-size: cover;
    background-position: center 12%;
  }

  /* The step list's active underline is drawn for the desktop 4-across
     row; stacked into one column it reads as a stray rule between steps
     1 and 2. The gold numbered circle already marks the active step. */
  .psteps4 .pstep:first-child {
    border-bottom: 0;
    padding-bottom: 0;
    margin-bottom: 0;
  }

  /* Interior Vision room cards. At 375px the header row (icon, room
     select, photo count, delete) ran out of width — "0 photos" broke onto
     two lines against the bin icon. Every piece slims one notch and the
     pill is forbidden from wrapping. */
  .room2__head {
    gap: 6px;
    padding: 10px 10px;
  }

  .room2__ico {
    width: 26px;
    height: 26px;
  }

  .room2__ico .icon {
    width: 14px;
  }

  /* flex:1 hands the row's spare width to the select so "Living Room"
     never truncates. Its font stays at the global 16px — shrinking it
     re-triggers the iOS focus zoom, which is worse than a bigger label —
     so the rest of the row slims down instead. */
  .room2__type {
    flex: 1 1 auto;
    min-width: 0;
    padding: 5px 22px 5px 8px;
    background-position: right 7px center;
  }

  .room2__count {
    white-space: nowrap;
    padding: 3px 7px;
    font-size: 10px;
  }

  .room2__rm {
    width: 26px;
    height: 26px;
  }

  /* Empty rooms: the lone square "Add photos" cell sat at ~40% width with
     dead space beside it. Empty state becomes one full-width, shorter bar;
     rooms with photos keep the square thumbnail grid. */
  .room2.is-empty .room2__photos {
    grid-template-columns: 1fr;
  }

  .room2.is-empty .room2__add {
    flex-direction: row;
    gap: 8px;
    aspect-ratio: auto;
    height: 76px;
  }

  .room2__photos {
    grid-template-columns: repeat(auto-fill, minmax(76px, 1fr));
    gap: 8px;
  }

  /* Motion Edit's cost + enhance row. A desktop side-by-side (cost left,
     button right) that cannot fit 335px — the button ran off the frame and
     the note clipped. Stacks: cost, full-width button, note. */
  .penh {
    flex-direction: column;
    align-items: stretch;
    gap: 14px;
  }

  .penh__right {
    align-items: stretch;
    gap: 10px;
  }

  .penh .pgen {
    padding: 0;
    width: 100%;
  }

  .pcost {
    gap: 10px;
  }

  .pcost > span:first-child {
    width: 34px;
    height: 34px;
  }

  .pcost b {
    font-size: 16px;
  }

  /* Open Canvas "Preview Example" card — a grey placeholder plate with a
     dead play button. On the phone it is a screen of nothing between the
     tips and the footer, so it goes (user call, 2026-07-24). Desktop keeps
     it. .vsample only exists in this one card, so :has() is exact. */
  .pai .pcard:has(> .vsample) {
    display: none;
  }

  /* Ratio / option chips (Square 1:1, Portrait 3:4 …). The desktop chip
     wraps icon and label freely, so narrow 2-up cells broke labels onto
     second lines and every card was a different height. One line, one
     height. */
  .pchoice4 .pchip,
  .pchoice5 .pchip {
    flex-wrap: nowrap;
    white-space: nowrap;
    gap: 7px;
    min-width: 0;
    padding: 11px 10px;
    font-size: 12px;
  }

  .pchoice4 .pchip .icon,
  .pchoice5 .pchip .icon {
    width: 15px;
    flex: none;
  }

  /* …but chips that CARRY a description (Motion Edit's video styles:
     "Dynamic — fast cuts, high energy") need the wrap back — the one-line
     rule above crammed title and description into a clipped strip. Icon +
     title on the first line, description on its own line below. */
  .pchoice4 .pchip:has(i),
  .pchoice5 .pchip:has(i) {
    flex-wrap: wrap;
    white-space: normal;
    gap: 6px 7px;
  }

  .pchoice4 .pchip i,
  .pchoice5 .pchip i {
    font-size: 10.5px;
    line-height: 1.45;
  }

  /* Before / after and three-up comparisons: the connector columns become
     rows, so the arrow keeps pointing the right way. */
  .ba,
  .frames2,
  .demo3 {
    grid-template-columns: minmax(0, 1fr);
  }

  .ba .icon,
  .frames2 .icon,
  .demo3 .icon {
    transform: rotate(90deg);
    justify-self: center;
  }

  .report__kpis {
    grid-template-columns: repeat(2, 1fr);
  }

  /* Four "how it works" steps in a row, each flexed to 1fr with an arrow
     between. Below 860px they stack and the arrows turn to point down. */
  .phow {
    margin: 0 var(--m-pad) 18px;
  }

  .phow4 {
    flex-direction: column;
    gap: 14px;
  }

  .phow__arrow {
    padding-top: 0;
    justify-self: center;
    transform: rotate(90deg);
  }

  .phow__i {
    width: 40px;
    height: 40px;
  }

  /* Platform picker — wraps instead of running off the edge. */
  .plats {
    flex-wrap: wrap;
    gap: 8px;
  }

  .plat {
    height: 42px;
    padding: 0 14px;
    font-size: 13px;
  }

  /* Asset history. Five desktop columns cannot fit, so each row becomes a
     small card grid: thumbnail beside title+meta, status and date sharing
     one line, actions on their own row — Play (videos only, phone-only
     markup) at the left, Download at the right. */
  .pai .histrow {
    grid-template-columns: 66px minmax(0, 1fr);
    gap: 7px 11px;
    align-items: start;
    padding: 14px 2px;
  }

  .pai .histrow__thumb {
    grid-row: 1 / span 2;
    align-self: stretch;
  }

  /* Titles may take a second line instead of ellipsizing mid-word. */
  .pai .histrow__x b {
    font-size: 13.5px;
    white-space: normal;
    line-height: 1.35;
  }

  .pai .histrow__x i {
    margin-top: 3px;
    font-size: 11.5px;
  }

  /* Badge left, date right — one quiet line instead of two stacked rows. */
  /* Sized so the widest pairing ("Completed" + "Yesterday · 6:48 PM")
     clears the ~215px cell with room to spare — they share the cell as
     start/end-anchored items, so their widths must never sum past it. */
  .pai .histrow__badge {
    grid-column: 2;
    grid-row: 2;
    justify-self: start;
    align-self: center;
    padding: 2px 7px;
    font-size: 9.5px;
  }

  /* The pill's colour already says "done" — the check glyph inside it was
     14px the shared cell cannot spare. */
  .pai .histrow__badge .icon {
    display: none;
  }

  .pai .histrow__date {
    grid-column: 2;
    grid-row: 2;
    justify-self: end;
    align-self: center;
    font-size: 10px;
  }

  .pai .histrow__act {
    grid-column: 2;
    grid-row: 3;
    justify-self: end;
    height: 32px;
    padding: 0 13px;
    gap: 6px;
    font-size: 12px;
  }

  .pai .histrow__act .icon {
    width: 12px;
  }

  /* Same three classes as the base hide, later in the file, so the phone
     reveal wins the tie. */
  .pai .histrow__act.histrow__watch {
    display: inline-flex;
    justify-self: start;
  }

  /* PropAI dashboard hero. A 33:14 band is 159px tall at this width, so the
     copy cannot sit inside it — the band becomes a picture with the words
     beneath it, on paper, where they are legible. */
  .dhero {
    display: block;
    aspect-ratio: auto;
    min-height: 0;
    margin: 8px var(--m-pad) 0;
  }

  .dhero__media {
    position: relative;
    height: 138px;
    border-radius: 14px 14px 0 0;
  }

  .dhero__copy {
    max-width: none;
    padding: 20px 18px 22px;
  }

  .dhero__welcome {
    font-size: 15px;
  }

  .dhero__title {
    font-size: 26px;
  }

  .dhero__lede {
    margin-top: 12px;
    font-size: 15px;
  }

  .dhero__sub {
    font-size: 13px;
    line-height: 1.6;
  }

  .dhero__sub br {
    display: none;
  }

  /* `.pgen` is written for <button> and never sets `text-decoration`, so
     wherever it is used as an <a> — the dashboard hero, the empty states —
     the UA default draws a line across the gold pill. Fixed here, inside
     the phone breakpoint only: the desktop design is frozen, so this rule
     deliberately does NOT go in propai.css where it belongs. */
  .pai .pgen {
    text-decoration: none;
    /* Desktop's 16px/54px wraps long labels onto two lines. 12.5px nowrap
       keeps even the longest ("Generate House Tour Video — 50 Credits",
       ~250px) on one line inside a 261px card. */
    height: 48px;
    font-size: 12.5px;
    white-space: nowrap;
  }

  .pai .pgen .icon {
    width: 15px;
  }

  .pgen__cap {
    font-size: 11.5px;
  }

  .pgen--hero {
    display: flex;
    width: 100%;
    height: 48px;
    margin-top: 18px;
    padding: 0 20px;
  }

  .dsec {
    margin: 26px var(--m-pad) 0;
  }

  /* Empty state. As a row it is icon | copy | button, and the button does
     not shrink — at 343px that left the copy column 53px wide and set
     "You haven't created any projects yet." one word per line. Centred
     stack instead: the standard shape for an empty state on a phone, and
     the copy gets the full measure. */
  .dempty {
    flex-direction: column;
    align-items: center;
    gap: 12px;
    padding: 26px 20px 22px;
    text-align: center;
  }

  .dempty__x {
    flex: none;
    align-items: center;
    gap: 5px;
  }

  .dempty__cta {
    width: 100%;
    margin-top: 4px;
  }

  .dsec__t {
    font-size: 16px;
  }

  .dsec__s {
    font-size: 13px;
    line-height: 1.55;
  }

  /* ---- 2.13 PropAI marketing landing ----------------------------- */

  .plp__nav {
    height: 58px;
    padding: 0 var(--m-pad);
    padding-top: var(--m-safe-t);
    gap: 10px;
  }

  /* The "PropAI" suite chip goes; both actions stay. Signing in is the only
     way back to an existing account, so it does not get dropped — it just
     loses its border and becomes a text link. */
  .plp__sub {
    display: none;
  }

  .plp__navcta {
    margin-left: auto;
    gap: 4px;
  }

  .plp__nav .plp__ghost {
    height: 38px;
    padding: 0 10px;
    border-color: transparent;
    background: none;
    font-size: 13.5px;
    white-space: nowrap;
  }

  .plp__gold {
    height: 38px;
    padding: 0 15px;
    font-size: 13px;
    white-space: nowrap;
  }

  .plp__word {
    font-size: 17px;
  }

  .plp__hero {
    padding: 48px var(--m-pad) 0;
  }

  .plp__h1 {
    margin-top: 16px;
    font-size: clamp(28px, 7.8vw, 33px);
    line-height: 1.14;
  }

  .plp__h1--sm {
    font-size: clamp(24px, 6.6vw, 28px);
  }

  .plp__lede {
    margin-top: 16px;
    font-size: 15px;
    line-height: 1.6;
  }

  .plp__pill {
    height: 32px;
    padding: 0 14px;
    font-size: 12px;
  }

  .plp__cta {
    flex-direction: column;
    gap: 10px;
    margin-top: 24px;
  }

  .plp__gold--lg,
  .plp__ghost--lg {
    width: 100%;
    height: 50px;
    font-size: 14.5px;
  }

  .plp__shot {
    margin-top: 34px;
    border-radius: 14px;
  }

  /* The mock's own sidebar is chrome inside a picture of chrome. */
  .plp__shotbody {
    grid-template-columns: minmax(0, 1fr);
  }

  .plp__shotside {
    display: none;
  }

  .plp__shotgrid {
    grid-template-columns: minmax(0, 1fr);
    gap: 10px;
  }

  .plp__shotgrid .pshot {
    height: 116px;
  }

  .plp__arrow {
    transform: rotate(90deg);
  }

  .plp__proof {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 18px 12px;
    padding: 26px var(--m-pad);
  }

  .plp__proof b {
    font-size: 22px;
  }

  .plp__proof i {
    font-size: 12px;
  }

  .plp__sec {
    padding: 44px var(--m-pad);
  }

  .plp__h2 {
    font-size: clamp(21px, 6vw, 25px);
    line-height: 1.25;
  }

  .plp__sub2 {
    font-size: 14.5px;
    line-height: 1.6;
  }

  .plp__tools,
  .plp__steps,
  .plp__packs {
    grid-template-columns: minmax(0, 1fr);
    gap: 12px;
    margin-top: 28px;
  }

  .plp__tool,
  .plp__step,
  .plp__pack {
    padding: 20px;
  }

  .plp__toolGo {
    /* No hover on touch — reveal it permanently instead of never. */
    opacity: 1;
    transform: none;
    top: 20px;
    right: 20px;
  }

  .plp__pack b {
    font-size: 30px;
  }

  .plp__foot {
    padding: 34px var(--m-pad) calc(24px + var(--m-safe-b));
  }

  .plp__footTop {
    grid-template-columns: minmax(0, 1fr);
    gap: 26px;
  }

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

  /* ---- 2.14 Public pricing --------------------------------------- */

  .pub__nav {
    gap: 12px;
    padding-left: var(--m-pad);
    padding-right: var(--m-pad);
  }

  .pub__brand .topnav__logo {
    width: 104px;
  }

  .pub__actions {
    margin-left: auto;
    gap: 12px;
  }

  .pub__main {
    padding-left: var(--m-pad);
    padding-right: var(--m-pad);
  }

  .pub__hero {
    margin-bottom: 28px;
  }

  /* 62px is a desktop display size; at 375px it costs three lines before a
     single price is visible. */
  .buytitle {
    font-size: clamp(30px, 8.6vw, 38px);
    line-height: 1.12;
  }

  .buysub {
    font-size: 14.5px;
    line-height: 1.6;
  }

  /* Same anonymous-flex-item split as .pnote — three text runs around a
     <b> became three columns. */
  .pub__free {
    display: block;
    margin-top: 18px;
    padding: 11px 16px;
    border-radius: 14px;
    font-size: 13px;
    line-height: 1.55;
    text-align: left;
  }

  .pub__free .icon {
    display: inline;
    vertical-align: -2px;
    margin-right: 7px;
  }

  /* ---- 2.15 Icon and tile scale ---------------------------------- */

  /* One scale for every rounded icon tile on the phone.

     These are all sized for a 1440px board, where a 54px tile is a small
     detail. At 375px the same tile is 14% of the screen width and the page
     reads as a row of buttons with captions. Three sizes, used everywhere:

       40px  page-level dropzones — the one thing you are meant to tap
       34px  card and list tiles
       30px  inline row markers

     The inner glyph stays at roughly 45% of its tile, so the ring of space
     around it is constant and the set reads as one family. */

  /* -- 40: dropzones -- */
  .pdrop__i {
    width: 40px;
    height: 40px;
    margin-bottom: 11px;
  }

  .pdrop__i .icon {
    width: 18px;
  }

  /* -- 34: cards, empty states, section tiles -- */
  .toolcard__i,
  .statcard__i,
  .invcard__i,
  .hs-topic__i,
  .hs-contact__i,
  .dcard__i,
  .dempty__i,
  .pcan__i,
  .phow__i,
  .studio__tile,
  .step__tile {
    width: 34px;
    height: 34px;
    border-radius: 10px;
  }

  .toolcard__i .icon,
  .statcard__i .icon,
  .invcard__i .icon,
  .hs-topic__i .icon,
  .hs-contact__i .icon,
  .dcard__i .icon,
  .dempty__i .icon,
  .pcan__i .icon,
  .phow__i .icon,
  .studio__tile .icon,
  .step__tile .icon {
    width: 16px;
  }

  /* -- 30: list rows and inline markers.
        `.feat__tile` (28) and `.ltrail__icon` (26) are deliberately absent —
        they are already below this size and the point is to come down, not
        to make anything grow. -- */
  .setrow__i,
  .histrow__i,
  .drop__i,
  .pget__i {
    width: 30px;
    height: 30px;
    border-radius: 9px;
  }

  .setrow__i .icon,
  .histrow__i .icon,
  .drop__i .icon,
  .pget__i .icon {
    width: 14px;
  }

  .pget__i {
    margin-bottom: 10px;
  }

  /* -- Circular controls. Go-arrows are secondary and come down to 30;
        play buttons stay a touch larger because they are the affordance
        the whole panel exists for. -- */
  .studio__go,
  .tool__go,
  .vcard__go {
    width: 30px;
    height: 30px;
  }

  .studio__go .icon,
  .tool__go .icon,
  .vcard__go .icon {
    width: 13px;
  }

  .media__play,
  .vcard__play {
    width: 36px;
    height: 36px;
  }

  .media__play .icon,
  .vcard__play .icon {
    width: 14px;
  }

  /* -- Circular tiles: same 34 scale, but keep the round shape -- */
  .paudio__i,
  .perkcol__i {
    width: 34px;
    height: 34px;
  }

  .paudio__i .icon,
  .perkcol__i .icon {
    width: 16px;
  }

  /* -- Avatars. The profile avatar stays a little larger than the icon
        tiles — it is a person, and the settings page leads with it. -- */
  .who__av--lg {
    width: 44px;
    height: 44px;
    font-size: 17px;
  }

  /* -- Loose glyphs that carry no tile -- */
  .trust__icon .icon,
  .perk__icon .icon,
  .strip__spark .icon {
    width: 16px;
  }

  /* ---- 2.16 Popovers --------------------------------------------- */

  /* Anchored dropdowns become bottom sheets.

     These MUST carry their shell prefix. `.app .notif` and `.app .acct`
     set `position: absolute; right: 0` at (0,2,0) and a bare `.notif` at
     (0,1,0) loses to them however late it is loaded — which is what put
     the 385px notification panel at x 268→608, a third of it past the
     right edge of a 375px screen, and the account menu with it. */
  .app .notif,
  .app .acct,
  .pai .pnotif {
    position: fixed;
    top: auto;
    left: 8px;
    right: 8px;
    bottom: calc(8px + var(--m-safe-b));
    width: auto;
    max-height: 74dvh;
    overscroll-behavior: contain;
    /* Above the topbar's own stacking context. */
    z-index: 210;
    /* popIn slides down from above — right for a dropdown, backwards for
       a sheet that arrives from the bottom edge. */
    animation-name: sheetIn;
  }

  /* The two notification sheets keep their title bar and their footer link
     in place and scroll only the list between them, the way the desktop
     dropdown does. The panel is the flex column; the list is the only part
     that may overflow, so its own 390/400px cap has to go — otherwise it
     stops short and leaves dead space at the bottom of a taller sheet. */
  .app .notif,
  .pai .pnotif {
    display: flex;
    flex-direction: column;
    overflow: hidden;
  }

  /* Any `display` rule on a [hidden]-toggled element has to restore
     `display: none` itself, at matching-or-higher specificity.

     `.pnotif[hidden] { display: none }` in propai-notif.css is (0,2,0) —
     one class plus one attribute — which TIES with `.pai .pnotif` above.
     A tie goes to the later stylesheet, and this one loads last, so the
     PropAI notification panel rendered open on page load and could not be
     dismissed: `hidden` was being set correctly and doing nothing. The
     dark app escaped it only because app-popovers.css writes its guard as
     `.app .notif[hidden]`, which is (0,3,0) and already outranks this. */
  .app .notif[hidden],
  .app .acct[hidden],
  .pai .pnotif[hidden] {
    display: none;
  }

  .app .notif__scroll,
  .pai .pnotif__scroll {
    flex: 1;
    min-height: 0;
    max-height: none;
  }

  .app .notif__head,
  .app .notif__all,
  .pai .pnotif__head,
  .pai .pnotif__all {
    flex: none;
  }

  /* The account menu is a short list — it scrolls as one piece. */
  .app .acct {
    overflow-y: auto;
  }

  /* Native sheet dressing: a soft 20px radius and the grabber pill every
     bottom sheet on the platform carries. Decorative, but it is the cue
     that says "this floats above the page and can be dismissed". */
  .app .notif,
  .app .acct,
  .pai .pnotif {
    border-radius: 20px;
  }

  .app .notif::before,
  .app .acct::before,
  .pai .pnotif::before {
    content: '';
    display: block;
    flex: none;
    width: 36px;
    height: 4px;
    margin: 8px auto 2px;
    border-radius: 999px;
    background: rgba(128, 128, 128, 0.35);
  }

  /* The drawers get a rounded leading edge for the same reason. */
  .side,
  .pside {
    border-radius: 0 20px 20px 0;
  }

  /* propai-notif.css narrows this to 330px at 640px; the sheet takes its
     width from left/right instead. */
  .pai .pnotif {
    width: auto;
  }
}

@keyframes sheetIn {
  from {
    opacity: 0;
    transform: translateY(14px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* ==================================================================
   3. SMALL PHONE — 520px and down
   ================================================================== */

@media (max-width: 520px) {
  :root {
    --m-pad: 16px;
  }

  /* PropAI's top bar carries six controls. At 375px they fit at these
     paddings; at 320px they only fit at these. Nothing is dropped —
     language, credits and notifications all stay reachable. */
  .ptop {
    padding-left: 12px;
    padding-right: 12px;
  }

  .ptop__right {
    gap: 6px;
  }

  .plang b {
    padding: 5px 7px;
    font-size: 11.5px;
  }

  .pcredits {
    gap: 5px;
    padding: 0 9px;
  }

  .pdash__back {
    padding: 0 8px;
  }
}

/* ==================================================================
   3b. NARROW PHONE — 400px and down
   The PropAI bar carries six controls; at 320px they need one more turn
   of the screw. Everything stays reachable — this is spacing, not
   removal.
   ================================================================== */

@media (max-width: 400px) {
  .ptop {
    gap: 8px;
    padding-left: 10px;
    padding-right: 10px;
  }

  .ptop .navburger {
    width: 36px;
    height: 36px;
  }

  .ptop__right {
    gap: 5px;
  }

  .plang b {
    padding: 5px 6px;
    font-size: 11px;
  }

  .pcredits {
    padding: 0 8px;
  }

  .pdash__av,
  .pav {
    width: 28px;
    height: 28px;
  }

  /* Two-up plates that still crowd at 360–390px. `.pget5` and `.psteps4`
     are deliberately absent — they stay one-up at every phone width. */
  .trust,
  .perks,
  .packgrid,
  .plp__proof,
  .footer__cols,
  .plp__footCols,
  .dstudio,
  .dfeat,
  .rooms4,
  .order4,
  .pchoice4,
  .pchoice5 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  /* No hero/button overrides here: this width block covers EVERY phone
     (375 ≤ 520), and the reference-mock scale in the main phone block is
     already designed for 375. Shrinking it again here is what quietly
     undid the mock. Height-based tiers below handle small screens. */
  .ltrail__title {
    font-size: 14px;
  }

  .topbar__title {
    font-size: 19px;
  }
}

/* ==================================================================
   3c. MID-HEIGHT PHONES — 621–750px tall
   The mock's full hero (big serif, 52px buttons, card descriptions) needs
   ~780px of stage; the stage is 100vh and clips. These screens keep the
   same composition at a tighter scale.
   ================================================================== */

@media (max-width: 860px) and (min-height: 621px) and (max-height: 750px) {
  .hero {
    top: 104px;
  }

  .hero__headline {
    font-size: clamp(27px, 7.8vw, 30px);
  }

  .hero__sub {
    margin-top: 10px;
    font-size: 13.5px;
  }

  .hero__actions {
    margin-top: 16px;
  }

  .btn {
    height: 46px;
    font-size: 13.5px;
  }

  .proof {
    margin-top: 16px;
  }

  .proof__face {
    width: 32px;
    height: 32px;
  }

  .proof__text {
    font-size: 12.5px;
  }

  .ltrail__row {
    top: 384px;
    gap: 8px;
  }

  .ltrail__item,
  .ltrail__item:first-child {
    gap: 9px;
    padding: 12px 12px 13px;
  }

  .ltrail__icon {
    width: 32px;
    height: 32px;
    border-radius: 10px;
  }

  .ltrail__icon svg {
    width: 15px;
  }

  .ltrail__title {
    font-size: 13.5px;
  }

  .ltrail__sub {
    display: none;
  }
}

/* ==================================================================
   4. SHORT VIEWPORTS
   Any phone under ~620px tall — a landscape handset, or a small portrait
   one — cannot fit the top-anchored hero AND the feature cards beneath it.
   Rather than clip the cards, they stand down and the hero recentres, so
   the short screen still reads as one clean, centred block.
   ================================================================== */

@media (max-width: 900px) and (max-height: 620px) {
  .ltrail__row {
    display: none;
  }

  .hero {
    top: 50%;
    bottom: auto;
    transform: translateY(-50%);
  }

  .hero__headline {
    font-size: clamp(24px, 6vw, 30px);
  }

  .starting__wordmark {
    font-size: clamp(34px, 9vw, 46px);
  }
}

/* ==================================================================
   5. TOUCH
   Hover lifts and reveal-on-hover affordances have no counterpart on a
   touch screen — the transform sticks after a tap and the revealed
   control is never seen at all.
   ================================================================== */

@media (hover: none) {
  .btn-gold:hover,
  .side__btn:hover,
  .plp__gold:hover,
  .plp__tool:hover,
  .topnav__cta:hover,
  .bonus__cta:hover {
    transform: none;
  }

  /* Active state does the work instead — immediate, and it releases. */
  .btn:active,
  .btn-gold:active,
  .plp__gold:active,
  .topnav__cta:active,
  .bonus__cta:active,
  .side__btn:active {
    transform: scale(0.98);
  }
}
