* {
  box-sizing: border-box;
}

@font-face {
  font-family: "Inter Composition";
  src: url("components/Install Button Asset/assets/InterVariable.woff2") format("woff2");
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
}

:root {
  --canvas-width: 1920;
  --canvas-height: 1080;
  --neutral-900: #0d0d0d;
  --border-media: color-mix(in srgb, var(--neutral-900) 5%, transparent);
  --card: #f5f5f5;
  --card-line: var(--border-media);

  /* Chip motion. One duration and one curve is the whole point: selecting a
     chip morphs its width and padding, reveals the leading icon, resizes the
     surface behind it and re-orders the row — four things that have to look
     like one movement. They were on the same duration but the reorder is
     driven from script.js, so the pair is defined here and read from both.
     300ms on a decelerating curve is the standard chip-sized shape change;
     the press is much shorter, since that wants to feel immediate. */
  --chip-duration: 300ms;
  --chip-ease: cubic-bezier(0.2, 0, 0, 1);
  --chip-press: 110ms;
  --touch-cursor: url("data:image/svg+xml;utf8,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='32'%20height='32'%3E%3Ccircle%20cx='16'%20cy='16'%20r='13.25'%20fill='black'%20fill-opacity='.14'%20stroke='black'%20stroke-opacity='.3'%20stroke-width='1.5'/%3E%3C/svg%3E") 16 16, default;
}

html,
body {
  width: 100%;
  min-width: 100%;
  min-height: 100%;
  margin: 0;
}

/* No ground of its own — the composition is transparent between its cards so
   whatever the host page is painted with shows through. Three layers had to give
   for that: this body, the frame below, and a full-canvas white <rect> that was
   baked into reference.svg as its first element (removed there, not here — CSS
   cannot reach inside the image). The cards themselves keep their own fills, so
   only the space around and between them is now open. */
body {
  display: grid;
  min-height: 100vh;
  overflow-x: hidden;
  place-items: center;
  background: transparent;
}

.composition-frame {
  position: relative;
  width: min(100vw, 1920px);
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background: transparent;
  container-type: inline-size;
}

/* The touch cursor is a claim that something can be operated, so it is spent
   only on the things that can: the draggable phone screen and its rails, the
   filter chips, the radios. It used to be forced onto `.composition-frame *`,
   which put it over the empty margins, the static artwork and every masked
   panel as well — the pointer changed the moment you entered the block and then
   promised interactivity almost nowhere it existed.

   This is the whole cursor policy for the outer frame; the rules below
   deliberately do not set one. Components living in iframes are handled in
   script.js instead, because a frame's cursor is decided by its own document
   rather than by this one. */
.phone__scroll,
.phone__rail,
.native-chip,
.radio-control {
  cursor: var(--touch-cursor);
}

.composition-canvas {
  position: absolute;
  top: 0;
  left: 0;
  width: 1920px;
  height: 1080px;
  overflow: hidden;
  transform: scale(var(--canvas-scale, 1));
  transform-origin: left top;

  /* Card outlines should read as the same hairline the host page draws around
     its images. This canvas is transform-scaled to fit, so a plain 1px border
     arrives on screen at whatever that scale is — 0.58px at the current size,
     against the page's full 1px. Dividing by the scale cancels that out.

     It gets within a hair rather than exactly: border-width is snapped to whole
     device pixels BEFORE the transform, so at 2x the only reachable widths here
     are 1.5px (0.87 on screen) and 2px (1.16). This asks for 1.72 and the
     browser takes 1.5, the nearer of the two. The card outlines drawn inside
     reference.svg are not snapped and sit exactly on 1.000.

     Declared here rather than on :root on purpose: --canvas-scale is set on
     this element by script.js, and a custom property's var() resolves at the
     element that declares it — on :root it would silently take the fallback of
     1 and do nothing. */
  --card-hairline: calc(1px / var(--canvas-scale, 1));
}

/* ── Loading state ────────────────────────────────────────────────────────
   Each card resolves out of its own blur instead of the whole block fading in
   as one piece. The stagger runs left to right so the composition assembles in
   reading order rather than arriving all at once.

   This is `filter` on the cards themselves, NOT backdrop-filter — nothing here
   is frosted or glassy. A card is simply out of focus, then in focus.

   The base image goes first because it carries every card's fill and outline:
   the shapes settle, then the live components inside them sharpen. Opacity is
   quick and the blur is slow, which is what makes it read as focusing rather
   than as a fade. */
.composition-canvas :is(
    .reference-base,
    .hero-panel,
    .controls-panel,
    .alert-panel,
    .app-item-panel,
    .snackbar-panel,
    .utility-panel,
    .tags-panel,
    .rating-panel
  ) {
  opacity: 0;
  filter: blur(24px);
  transition:
    opacity 200ms linear,
    filter 320ms cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* The phone card owns a transition already, for the hover grow. Restating it
   here is deliberate: this selector outranks the one below, so leaving it out
   would silently kill that motion. The delay list is per-property for the same
   reason — a bare transition-delay would postpone the hover by the stagger. */
.composition-canvas .phone-card {
  opacity: 0;
  filter: blur(24px);
  transition:
    opacity 200ms linear,
    filter 320ms cubic-bezier(0.22, 0.61, 0.36, 1),
    top 680ms cubic-bezier(0.22, 1, 0.36, 1),
    height 680ms cubic-bezier(0.22, 1, 0.36, 1);
}

.composition-canvas.is-ready :is(
    .reference-base,
    .phone-card,
    .hero-panel,
    .controls-panel,
    .alert-panel,
    .app-item-panel,
    .snackbar-panel,
    .utility-panel,
    .tags-panel,
    .rating-panel
  ) {
  opacity: 1;
  filter: blur(0);
}


.reference-base {
  position: absolute;
  z-index: 0;
  inset: 0;
  display: block;
  width: 1920px;
  height: 1080px;
  pointer-events: none;
  user-select: none;
}

.phone-card {
  position: absolute;
  z-index: 2;
  top: 84px;
  left: 680.667px;
  width: 558.667px;
  height: 912px;
  overflow: hidden;
  border: var(--card-hairline) solid var(--card-line);
  border-radius: 48px;
  background: var(--card);
  will-change: top, height;
  transition:
    top 680ms cubic-bezier(0.22, 1, 0.36, 1),
    height 680ms cubic-bezier(0.22, 1, 0.36, 1);
}

.phone-card:hover,
.phone-card:focus-within {
  z-index: 6;
  top: 47.52px;
  height: 984.96px;
}

.phone-mock-wrap {
  position: absolute;
  top: 29px;
  left: 50%;
  width: 500.667px;
  height: 1010.35px;
  transform: translateX(-50%);
  will-change: transform;
  transition: transform 680ms cubic-bezier(0.22, 1, 0.36, 1);
}

.phone-mock-wrap:hover,
.phone-mock-wrap:focus-within {
  transform: translate(-50%, -96px);
}

.phone {
  --phone-scale: 1.41033;
  position: absolute;
  top: 0;
  left: 0;
  width: 355px;
  height: 716.106px;
  transform: scale(var(--phone-scale));
  transform-origin: left top;
}

.phone__shadow {
  position: absolute;
  inset: 0.17% 1% 0.33%;
  border-radius: 65.418px;
  background: #000000;
}

.phone__screen {
  position: absolute;
  top: 18.315px;
  right: 5.9%;
  left: 5.65%;
  height: 696.916px;
  overflow: hidden;
  border-radius: 38px;
  background: #ffffff;
  user-select: none;
  -webkit-user-select: none;
}

.phone__scroll {
  position: absolute;
  top: 102.68px;
  right: 0;
  bottom: 73.23px;
  left: 0;
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.phone__scroll.is-dragging,
.phone__scroll.is-dragging .phone__rail {
  scroll-behavior: auto;
}

.phone__rail {
  display: flex;
  gap: 10.4667px;
  padding: 13.956px;
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-x: contain;
}

.phone__band {
  padding-block: 13.956px;
}

.phone__tint {
  background: var(--phone-tint);
}

.phone__scroll,
.phone__rail {
  scrollbar-width: none;
  -ms-overflow-style: none;
}

.phone__scroll::-webkit-scrollbar,
.phone__rail::-webkit-scrollbar {
  display: none;
}

.phone img,
.phone video {
  display: block;
  border: 0;
  border-radius: 0;
  background: none;
  user-select: none;
}

.phone__scroll img,
.phone__scroll video,
.phone__rail img {
  flex: 0 0 auto;
}

.phone__statusbar,
.phone__searchbar,
.phone__bottomnav {
  position: absolute;
  left: 0;
  width: 314px;
}

.phone__statusbar {
  top: 0.39px;
}

.phone__searchbar {
  top: 46.74px;
}

.phone__bottomnav {
  bottom: 18.24px;
}

.phone__frame {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  border: 0;
  border-radius: 0;
  object-fit: cover;
  pointer-events: none;
}

.component-panel,
.scaled-asset {
  position: absolute;
}

.component-panel {
  z-index: 3;
  overflow: hidden;
}

.component-frame {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
  background: transparent;
}

.scaled-asset {
  transform-origin: left top;
}

/* Left upper card */
.alert-panel {
  top: 113px;
  left: 113px;
  width: 500.667px;
  height: 156.424px;
  padding: 12px 11.667px 11.424px 12px;
  border-radius: 16px;
  background: #fbfbfb;
}

.alert-panel .component-frame {
  width: 477px;
  height: 133px;
}

.app-item-panel {
  top: 319.425px;
  left: 113px;
  width: 500.667px;
  height: 115.988px;
  display: grid;
  padding: 0;
  place-items: center;
  border-radius: 16px;
  background: rgb(255 255 255 / 80%);
}

.app-item-panel .component-frame {
  width: 477px;
  height: 92px;
}

.snackbar-panel {
  top: 474.426px;
  left: 85.529px;
  width: 555.608px;
  height: 131.894px;
  background: var(--card);
}

.snackbar-scale {
  top: 0;
  left: 0;
  width: 404.521px;
  height: 96px;
  transform: scale(1.37349);
}

.snackbar-scale .component-frame {
  width: 404.521px;
  height: 96px;
}

.utility-panel {
  top: 603px;
  left: 103px;
  width: 520px;
  height: 88px;
  overflow: visible;
  background: transparent;
}

.chip-surface {
  position: absolute;
  top: 9.367px;
  left: 10px;
  display: inline-flex;
  width: max-content;
  height: auto;
  padding: 12px;
  overflow: visible;
  border-radius: 16px;
  /* Pure white, not the #FBFBFB this carried — over the card's #F5F5F5 that
     read as a slightly greyed panel rather than a white one. */
  background: #ffffff;
  z-index: 2;
  transition: width var(--chip-duration) var(--chip-ease);
}

.native-chip-group {
  display: flex;
  width: max-content;
  height: 40.72px;
  align-items: center;
  gap: 12px;
}

.native-chip {
  position: relative;
  display: inline-flex;
  height: 40.72px;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  padding: 0 12px;
  border: 1.34px solid #e0e0e3;
  border-radius: 10.72px;
  /* Opaque white too. Left transparent, an unselected chip picked up whatever
     was behind it, which is what made these look washed out. */
  background: #ffffff;
  color: #52525c;
  font-family: "Inter Composition", Inter, sans-serif;
  font-size: 19.3px;
  font-variation-settings: "wght" 500;
  font-weight: 500;
  line-height: 1;
  white-space: nowrap;
  outline: none;
  -webkit-tap-highlight-color: transparent;
  transition:
    width var(--chip-duration) var(--chip-ease),
    padding var(--chip-duration) var(--chip-ease),
    border-color var(--chip-duration) var(--chip-ease),
    background-color var(--chip-duration) var(--chip-ease),
    color var(--chip-duration) var(--chip-ease),
    transform var(--chip-press) var(--chip-ease);
}

.native-chip:hover,
.native-chip:focus-visible,
.native-chip:active {
  background: rgb(82 82 92 / 10%);
}

.native-chip:active {
  transform: scale(0.985);
}

.native-chip.is-selected {
  padding-right: 12.4px;
  padding-left: 14.7px;
  border-color: #05a55d;
  background: #f5fff3;
  color: #05a55d;
}

.native-chip.is-selected:is(:hover, :focus-visible, :active) {
  background: color-mix(in srgb, #05a55d 10%, #f5fff3);
}

.native-chip-close {
  display: inline-grid;
  width: 0;
  margin-right: 0;
  place-items: center;
  overflow: visible;
  opacity: 0;
  /* A scale-and-fade, not a spin. The rotate this used to carry is not a chip
     pattern — a leading icon grows into the space the container opens for it. */
  transform: scale(0.8);
  transition:
    width var(--chip-duration) var(--chip-ease),
    margin-right var(--chip-duration) var(--chip-ease),
    opacity 130ms linear,
    transform var(--chip-duration) var(--chip-ease);
}

.native-chip-close svg {
  display: block;
  fill: currentColor;
}

/* On the way in the icon waits ~a third of the morph before fading up, so it
   arrives into space that already exists rather than fighting for it. On the
   way out the base rule above has no delay, so it clears first and the chip
   closes behind it — the conventional order for a chip's leading icon. */
.native-chip.is-selected .native-chip-close {
  width: 16px;
  margin-right: 10.2px;
  opacity: 1;
  transform: scale(1);
  transition-delay: 0ms, 0ms, 100ms, 0ms;
}

.native-chip[data-chip-id="top-rated"] { width: 113.64px; }
.native-chip[data-chip-id="kids"],
.native-chip[data-chip-id="new"] { width: 62.44px; }
.native-chip[data-chip-id="top-rated"].is-selected { width: 142.92px; }
.native-chip[data-chip-id="kids"].is-selected,
.native-chip[data-chip-id="new"].is-selected { width: 91.34px; }

.native-chip-group.is-measuring .native-chip,
.native-chip-group.is-measuring .native-chip-close {
  transition: none;
}

.badge-mask {
  position: absolute;
  top: 16px;
  left: 348px;
  width: 142px;
  height: 52px;
  background: var(--card);
}

.badge-scale {
  top: 0;
  left: 0;
  width: 520px;
  height: 88px;
  z-index: 1;
  pointer-events: none;
}

.badge-scale .component-frame {
  width: 520px;
  height: 88px;
}

/* Left lower card */
.controls-panel {
  top: 746.889px;
  left: 84px;
  width: 558.667px;
  height: 249.112px;
  overflow: hidden;
  border: 0;
  border-radius: 48px;
  background: transparent;
}

/* Figma (1340:90022) puts the nav at 500.667 × 82.6175 inside the card. The
   asset is a fixed 356 × 63 SVG, whose aspect does not match that box — so the
   old scale(1.40637, 1.31139) squashed it, stretching every icon and label 7.3%
   wider than tall. The scale is uniform now, taken from the width: 500.667/356.
   Width is the axis that has to govern, because it puts the four tab centres
   exactly on the ones the base SVG draws underneath (34.5 + n·89, scaled, lands
   on Figma's 49.473 + n·125.167). Scaling by height instead would size the icons
   to spec but walk each tab progressively out of register.

   That leaves the asset 88.6 tall against the design's 82.6175, so the wrapper
   crops the surplus off the bottom: 82.6175 / 1.406368 = 58.746 before scaling.
   The nav's ink ends at y 49.25 of the 63, well clear of the cut, so this only
   trims empty white — and it lands the white band exactly on the one in the
   base SVG. */
.navigation-scale {
  top: 29px;
  left: 29px;
  width: 356px;
  height: 58.746px;
  overflow: hidden;
  transform: scale(1.406368);
}

.navigation-scale .component-frame {
  width: 356px;
  height: 63px;
}

.checkbox-mask {
  position: absolute;
  top: 139px;
  left: 20px;
  width: 112px;
  height: 82px;
  background: var(--card);
}

.checkbox-scale {
  top: 139.617px;
  left: 29px;
  width: 48px;
  height: 48px;
  transform: scale(1.67696);
}

.checkbox-scale .component-frame {
  width: 48px;
  height: 48px;
}

/* 160.98 × 80.49, per Figma 1340:90057 (was 161.49 × 81). */
.radio-group {
  position: absolute;
  z-index: 2;
  top: 139.617px;
  left: 195.49px;
  width: 160.98px;
  height: 80.49px;
  background: var(--card);
}

.radio-control {
  position: absolute;
  inset: 0 auto auto 0;
  display: grid;
  width: 80.49px;
  height: 80.49px;
  padding: 0;
  place-items: center;
  border: 0;
  border-radius: 50%;
  background: transparent;
  outline: none;
  -webkit-tap-highlight-color: transparent;
  transition: background-color 160ms ease-in-out;
}

.radio-control::before {
  position: absolute;
  width: 67.075px;
  height: 67.075px;
  border-radius: 50%;
  background: rgb(82 82 92 / 8%);
  content: "";
  opacity: 0;
  transition:
    background-color 160ms ease-in-out,
    opacity 160ms ease-in-out;
}

.radio-control-second {
  left: 80.49px;
}

.radio-control:is(:hover, :active, :focus-visible) {
  background: transparent;
}

.radio-control:is(:hover, :active, :focus-visible)::before {
  opacity: 1;
}

.radio-control.is-selected::before {
  background: rgb(5 165 93 / 8%);
}

.radio-visual {
  position: relative;
  display: grid;
  width: 33.54px;
  height: 33.54px;
  place-items: center;
  border: 2.58px solid #52525c;
  border-radius: 50%;
  z-index: 1;
  transition:
    border-color 220ms cubic-bezier(0.2, 0, 0, 1),
    transform 180ms cubic-bezier(0.2, 0, 0, 1);
}

.radio-dot {
  width: 20.64px;
  height: 20.64px;
  border-radius: 50%;
  background: #05a55d;
  opacity: 0;
  transform: scale(0.35);
  transition:
    opacity 160ms ease-in-out,
    transform 240ms cubic-bezier(0.22, 1.18, 0.36, 1);
}

.radio-control.is-selected .radio-visual {
  border-color: #05a55d;
}

.radio-control.is-selected .radio-dot {
  opacity: 1;
  transform: scale(1);
}

.radio-control:active .radio-visual {
  transform: scale(0.94);
}

.switch-mask {
  position: absolute;
  top: 142px;
  left: 410px;
  width: 126px;
  height: 69px;
  background: var(--card);
}

.switch-scale {
  top: 153.033px;
  left: 442.465px;
  width: 52px;
  height: 32px;
  transform: scale(1.67696);
}

.switch-scale .component-frame {
  width: 52px;
  height: 32px;
}

/* Right upper hero card */
.hero-panel {
  top: 84px;
  left: 1277.33px;
  width: 525.193px;
  height: 718.634px;
  padding: 29px;
  border: var(--card-hairline) solid var(--card-line);
  border-radius: 48px;
  background: var(--card);
}

.hero-scale {
  top: 29px;
  left: 29px;
  width: 328px;
  height: 483.667px;
  transform: scale(1.42378);
}

.hero-scale .component-frame {
  width: 328px;
  height: 483.667px;
}

/* Right lower card */
/* Both panels in this card sit 11.16px lower than they used to, which centres
   their contents on the card now that it reaches the same baseline as the left
   column. Horizontal centring was already right to within 0.6px and is
   untouched.

   The rating cannot simply move: reference.svg draws the five static stars at
   y 893, and this panel's card-coloured background is what hides them. Moving
   it down would uncover their tips. So the panel grows upward by the same
   11.16 instead — staying anchored at 884.24 so it still covers the artwork —
   and the frame is pinned to its bottom, which puts the visible rating in the
   new position at its own unscaled size. */
.rating-panel {
  top: 884.24px;
  left: 1515.15px;
  width: 245.4px;
  height: 60.24px;
  overflow: visible;
  background: var(--card);
}

.rating-panel .component-frame {
  position: absolute;
  bottom: 0;
  left: 0;
  width: 245.4px;
  height: 49.08px;
}

/* Moved down the same 11.16px. This one can move outright — its mask still
   covers the tag artwork the SVG draws at y 870.48 to 946.48. */
.tags-panel {
  top: 865.16px;
  left: 1302px;
  width: 176px;
  height: 106px;
  display: grid;
  place-items: center;
  background: var(--card);
}

/* Two rows that each pack left on their own, per Figma 1340:90080 — NOT a
   two-column grid. A grid gives both rows a shared second column, which pushed
   Orange out to a 14px gap behind Red while Blue → Green kept its 8px. Wrapping
   flex keeps each row independent, so every gap is the 8px the design asks for.

   The width is row 2 (50 + 8 + 81), the wider of the two. It has to be exact:
   any wider and Red would pull up onto row 1. That is also why the tags below
   carry a fixed `width` rather than the old `min-width` — a fallback font
   measuring a fraction wider would overflow the row and drop Orange onto a
   third line. */
.color-tags {
  display: flex;
  flex-wrap: wrap;
  width: 139px;
  gap: 8px;
  align-items: center;
  justify-content: flex-start;
}

/* 32 tall on a 6px radius, and 8px of side padding around the label — Figma
   1340:90081-90088. The 19px type is already right: it measures 39.02 / 53.45 /
   34.41 / 65.30, against Figma's 39 / 53 / 34 / 65. It was the boxes that were
   ~16% oversized (37 tall, and min-widths of 64/80/58/94). */
.color-tag {
  display: inline-grid;
  height: 32px;
  padding: 0 8px;
  place-items: center;
  border-radius: 6px;
  color: #ffffff;
  font-family: Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-size: 19px;
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
}

.color-tag-blue {
  width: 55px;
  background: #2b7fff;
}
/* Labelled Black, because the swatch is #1E1E1F — it was reading "Green" over a
   near-black fill. 65px is the label at 19px plus the 8px side padding, the same
   way every other tag here is measured. */
.color-tag-black {
  width: 65px;
  background: #1e1e1f;
}
.color-tag-red {
  width: 50px;
  background: #dc3736;
}
.color-tag-orange {
  width: 81px;
  background: #ffa239;
  color: #441306;
}

@media (max-aspect-ratio: 16 / 9) {
  body {
    align-items: start;
  }
}

@media (prefers-reduced-motion: reduce) {
  .composition-canvas {
    transform-origin: left top;
  }

  /* Still hidden until ready — a half-drawn composition is worse than a wait —
     but it arrives without the blur, the stagger or the slow resolve. */
  .composition-canvas :is(
      .reference-base, .phone-card, .hero-panel, .controls-panel, .alert-panel,
      .app-item-panel, .snackbar-panel, .utility-panel, .tags-panel, .rating-panel
    ) {
    filter: none;
    transition: opacity 1ms;
  }

  .composition-canvas.is-ready :is(
      .reference-base, .phone-card, .hero-panel, .controls-panel, .alert-panel,
      .app-item-panel, .snackbar-panel, .utility-panel, .tags-panel, .rating-panel
    ) {
    transition-delay: 0ms;
  }
}
