/* ============================================================
   MOBILE-WEB INSTALL BANNER  —  web-app-install-banner-checklist Phase A
   ------------------------------------------------------------
   The slim treatment (D2 "A"): one line, 46px, a text button. Reads as
   chrome rather than as an ad, which is the whole reason it is allowed
   to sit on top of the feed at all.

   Every colour is a token, so both themes come free and community mode's
   overrides reach it like anything else.

   Placement (D14): the rail becomes a fixed 52px bottom bar at z-index
   100 below 640px (home.css). This sits ON TOP of it at z-index 90 —
   under the nav, and under every popup, sheet and viewer in the app.
   ============================================================ */

.apb {
  /* The banner publishes its own height so .hm_pne can reserve room for it
     (D15). One number, set here, read there — a second hard-coded value
     would drift the first time this changes. */
  --apb-h: 46px;

  position: fixed;
  z-index: 90;
  left: 10px;
  right: 10px;
  bottom: calc(52px + 8px + env(safe-area-inset-bottom, 0px));

  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 9px 7px 10px;
  min-height: var(--apb-h);
  box-sizing: border-box;

  background: var(--container);
  border: 1px solid var(--border-color);
  border-radius: 14px;
  box-shadow: 0 10px 28px var(--shadow-color);

  /* Entrance. The banner starts off-screen and is revealed by the script;
     `hidden` keeps it out of the layout and the a11y tree until then. */
  transform: translateY(calc(100% + 70px));
  opacity: 0;
  transition: transform .34s cubic-bezier(.22, .85, .3, 1), opacity .26s ease;
}

.apb[hidden] { display: none; }

/* Set by the script one frame after unhiding, so the transition has a
   from-state to animate out of. */
.apb.apb_in {
  transform: none;
  opacity: 1;
}

/* Dismissal runs the entrance backwards, then the script hides it. */
.apb.apb_out {
  transform: translateY(calc(100% + 70px));
  opacity: 0;
}

@media (prefers-reduced-motion: reduce) {
  .apb { transition: none; }
}

/* Above the phone breakpoint there is no bottom bar to sit on — and no
   banner either, because GetTemplateData renders nothing. This is belt and
   braces for a desktop UA on a narrow window, where the fixed bar is absent
   and the 52px offset would leave it floating. */
@media screen and (min-width: 640px) {
  .apb { display: none; }
}

.apb_mark {
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  border-radius: 7px;
  background: var(--blue);
  display: grid;
  place-items: center;
}

.apb_mark svg {
  width: 15px;
  height: 13px;
}

/* The mark sits on a saturated fill in both themes, so it takes the
   inverted text colour rather than a literal white that would vanish on
   the light palette's paler blue. */
.apb_mark svg path { fill: var(--text-primary-inverted); }

.apb_txt {
  flex: 1;
  min-width: 0;
  font-size: 13px;
  font-weight: 500;
  line-height: 1.3;
  color: var(--text-primary);
  /* One line. A long translation truncates rather than pushing the button
     off the row — the button is the point of the banner. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.apb_cta {
  flex: 0 0 auto;
  /* 44px minimum target (D-a11y): the visible pill is smaller, so the
     padding does the work rather than the text box. */
  display: inline-flex;
  align-items: center;
  min-height: 36px;
  padding: 7px 12px;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-blue);
  text-decoration: none;
  white-space: nowrap;
}

.apb_cta:hover,
.apb_cta:focus-visible { background: var(--surface); }

.apb_x {
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--text-tertiary);
  display: grid;
  place-items: center;
  cursor: pointer;
  font-size: 15px;
  line-height: 1;
}

.apb_x:hover,
.apb_x:focus-visible {
  background: var(--surface);
  color: var(--text-primary);
}

.apb_cta:focus-visible,
.apb_x:focus-visible {
  outline: 2px solid var(--blue);
  outline-offset: 2px;
}

/* ------------------------------------------------------------
   CONTENT CLEARANCE (D15)
   .hm_pne already reserves 72px at the phone breakpoint for the bottom
   bar. While the banner is up the feed's last row would sit under it, so
   the page reserves the banner's height on top — published by the script
   as --app-banner-h on <body>, and 0px whenever the banner is down.
   ------------------------------------------------------------ */
@media screen and (max-width: 639px) {
  .hm_pne { padding-bottom: calc(72px + var(--app-banner-h, 0px)); }
}

/* ============================================================
   CONTEXT CARD  —  treatment "C" (checklist Phase C)
   ------------------------------------------------------------
   Shown where the page IS one thing and has said so in its
   OpenGraph: a post, an event, a community page. Names the thing
   and shows its own og:image, so the card carries the same
   picture the link unfurls with.

   Everything below is scoped to .apb_context. The slim bar's rules
   are untouched, so the two treatments cannot drift into each
   other through a shared selector.
   ============================================================ */

.apb_context {
  --apb-h: 62px;
  align-items: center;
  gap: 10px;
  padding: 9px 10px;
}

.apb_thumb {
  flex: 0 0 auto;
  width: 40px;
  height: 40px;
  border-radius: 10px;
  overflow: hidden;
  background: var(--surface);
  display: grid;
  place-items: center;
}

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

/* No og:image on this page — the app mark stands in rather than leaving a
   hole where a picture was promised. */
.apb_thumb_mark {
  width: 20px;
  height: 18px;
}
.apb_thumb_mark path { fill: var(--icon-shade); }

.apb_body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  /* min-width:0 on the flex child is what actually lets the two lines
     truncate; without it the longest word sets the width and pushes the
     CTA off the row. */
}

.apb_title {
  font-size: 13px;
  font-weight: 600;
  line-height: 1.3;
  color: var(--text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.apb_sub {
  font-size: 11.5px;
  line-height: 1.35;
  color: var(--text-secondary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The card earns a filled button: it has already said something specific,
   so the action is worth more than it is on the slim bar. */
.apb_context .apb_cta {
  background: var(--blue);
  color: var(--text-primary-inverted);
  padding: 8px 14px;
}

.apb_context .apb_cta:hover,
.apb_context .apb_cta:focus-visible {
  background: var(--blue);
  filter: brightness(1.08);
}
