/*
  core.css — shared layout, components & responsive rules
  ------------------------------------------------------------
  Everything here is used on 2+ pages (or is part of the base
  layout: nav, footer, floating CTA). No colors or fonts are
  hardcoded — everything reads from the tokens in theme.css and
  font.css. Load both of those before this file.

  Page-only rules (things that appear on exactly one page) live
  in pages.css instead, so this file stays reusable if a section
  gets moved or reused elsewhere.
*/

/* ---- Reset & base ------------------------------------------- */

* {
  box-sizing: border-box
}

html {
  scroll-behavior: smooth
}

body {
  margin: 0;
  font-family: var(--font-child);
  color: var(--color-text);
  background: var(--color-bg);
  line-height: 1.55
}

/* Every page has exactly one h1 (its main headline) — gets the Parent
   display font. .heading h2 below covers the same role for section
   headings and the 3 pages whose visual "page title" is an h2. */
h1 {
  font-family: var(--font-parent)
}

/* ---- Icon system --------------------------------------------- */
/* Inline SVG line-icons from the {% icon %} shortcode (see .eleventy.js).
   currentColor means most icons need zero color CSS of their own — they
   just inherit whatever text color surrounds them. .i-brand/.i-soft are
   for the handful of spots that need a specific tint regardless of the
   surrounding text color (e.g. a check icon inside dark muted list text). */

.i {
  display: inline-block;
  vertical-align: -3px;
  flex-shrink: 0
}

.i-brand {
  color: var(--color-brand-light)
}

.i-soft {
  color: var(--color-text-muted)
}

a {
  color: inherit;
  text-decoration: none
}

button,
input,
select,
textarea {
  font: inherit
}

button {
  cursor: pointer
}

/* ---- Layout primitives --------------------------------------- */

.wrap {
  max-width: 1120px;
  margin: auto;
  padding: 0 20px
}

.center {
  text-align: center
}

.section {
  padding: 80px 0
}

.alt {
  background: var(--color-bg-alt);
  border-block: 1px solid var(--color-border)
}

/* Shared page-header background — same hero-accent.svg illustration AND
   the same radial-gradient glow wash used behind Home's hero (.hero in
   pages.css), reused here so every interior page (Services, Pricing,
   Contact, About, Portfolio) opens with that same premium tinted
   backdrop instead of a bare section. Low-opacity source art means it
   stays out of the way of on-page illustrations already used in the
   About/Portfolio two-column heroes. */
.page-hero {
  position: relative;
  overflow: hidden;
  background: radial-gradient(circle at 60% 10%, var(--tint-primary-glow), transparent 35%), var(--color-bg)
}

.page-hero-bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top;
  pointer-events: none;
  z-index: 0;
  /* Dissolves into the page background over the illustration's last
     30% instead of stopping in a hard line at the section's bottom
     edge — that hard cutoff (visible where the tinted hero background
     meets the plain next section, especially on Contact/FAQ/Portfolio/
     Services/Where We Work/Terms/Privacy/Refund, all of which sit their
     next section right up against the hero) was reading as a rendering
     glitch rather than a deliberate section break. */
  mask-image: linear-gradient(to bottom, #000 0%, #000 70%, transparent 100%);
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 70%, transparent 100%)
}

.page-hero>.wrap {
  position: relative;
  z-index: 1
}

/* One-time fade-up entrance for every interior page's H1 — same motion
   language as Home's hero headline (see pages.css .hero h1) so the site
   doesn't visually "go static" the moment you leave Home, but deliberately
   NOT the homepage's typing effect: that's a first-impression flourish
   tied to Home's specific copy, and repeating it on every single page a
   visitor clicks through would read as slow/gimmicky rather than
   consistent. Defined here (not pages.css) since core.css is the file
   shared across pages — pages.css is meant to be safely deletable
   per-page, so it shouldn't be the thing other pages depend on. */
.page-hero h1 {
  animation: pageHeroTitleIn .7s cubic-bezier(.16, .84, .44, 1) both
}

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

@media (prefers-reduced-motion: reduce) {
  .page-hero h1 {
    animation: none
  }
}

.heading {
  text-align: center;
  max-width: 780px;
  margin: 0 auto 42px
}

.heading h1,
.heading h2 {
  font-family: var(--font-parent);
  font-size: clamp(28px, 4vw, 40px);
  line-height: 1.15;
  letter-spacing: -1px;
  margin: 14px 0
}

/* ---- Breadcrumb -------------------------------------------------- */

.breadcrumb {
  font-size: 11px;
  color: var(--color-text-muted);
  margin: 0 0 14px
}

.breadcrumb a {
  color: var(--color-text-muted)
}

.breadcrumb a:hover {
  color: var(--color-brand)
}

.heading p {
  color: var(--color-text-muted);
  font-size: 16px
}

.two {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 45px
}

.two>div>p {
  color: var(--color-text-muted);
  font-size: 14px
}

.narrow {
  max-width: 820px
}

.grid3 {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 22px
}

/* ---- Top bar & navigation -------------------------------------- */

/* .site-header wraps .topbar + #nav and is the thing that's actually
   sticky — not #nav alone. That way both bars scroll together and lock
   to the viewport as one unit. Sticking the wrapper also means nothing
   needs to know either bar's exact height — no JS, no manual top-offset
   math, same behavior at every width. .topbar already carries its own
   solid background, so it needs no separate "scrolled" treatment.

   .topbar itself is announcement-only: header.njk only renders it when
   site.announcement.enabled is true (see src/_data/site.js), so with
   no active offer there's no topbar in the page at all — not hidden,
   not collapsed, just absent — and .site-header shrinks to #nav alone. */
.site-header {
  position: sticky;
  top: 0;
  z-index: 30
}

/* Solid highlight amber, not --color-dark-bg — an offer bar needs to
   read as "look here", not as one more dark strip matching the
   scrolled nav / footer. --color-action stays green on the link pill
   below so it still reads as the site's one consistent "click here"
   color, same as every other CTA. */
.topbar {
  background: var(--color-dark-bg);
  color: var(--color-white);
  font-family: var(--font-subchild);
  font-weight: 500;
  font-size: 13.5px;
  line-height: 1.4;
  padding: 7px 20px;
  min-height: 38px;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  text-align: center;
}

.topbar-link {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 4px 11px;
  border-radius: 5px;
  background: var(--color-action);
  color: var(--color-white);
  font-weight: 600;
  line-height: 1.3;
  white-space: nowrap;
  text-decoration: none;
  transition: background-color 0.2s ease, transform 0.2s ease;
}

.topbar-link:hover {
  background: var(--color-action-light);
}

.topbar-link:focus-visible {
  outline: 2px solid var(--color-white);
  outline-offset: 2px;
}

.nav-inner {
  max-width: 1120px;
  margin: auto;
  padding: 13px 20px;
  display: flex;
  align-items: center;
  justify-content: space-between
}

/* Translucent header once the page is scrolled — background/blur toggled by
   app.js adding .scrolled to #nav, kept out of the JS itself so it's driven
   by the same theme tokens as everything else. #nav doesn't need to be
   sticky itself — it's sticky as part of .site-header above — but it
   does need `position: relative` so .navlinks (position:absolute,
   mobile dropdown) anchors to #nav's own box via top:100%, not to
   .site-header's, whatever height .topbar ends up adding above it. */
#nav {
  position: relative;
  background: transparent
}

#nav.scrolled {
  background: var(--tint-nav-scroll-bg);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px)
}

.brand {
  font-size: 19px;
  font-weight: 800;
  display: flex;
  align-items: center;
  gap: 9px
}

/* Real logo mark (assets/images/logo/citytask-logo-svg.svg), replacing
   the old CSS-only "CT" badge. Colors are baked into the SVG itself
   (recolored to match --gradient-brand) rather than read from a var —
   image assets can't reference CSS custom properties, so if the brand
   gradient ever changes, the logo file needs regenerating to match. */
.brand-mark {
  display: block;
  flex-shrink: 0
}

/* .wordmark wraps "City" + "task" as ONE flex item so the "task" part
   can be colored differently while the two stay glued together as one
   word. Splitting them into two separate flex items (e.g. bare "City"
   text + a sibling <span>task</span>, both direct children of .brand)
   used to insert .brand's own gap:9px between them — "City" and "task"
   rendered with a visible space, i.e. "City task" instead of
   "Citytask". Wrapping keeps that gap where it belongs: between the
   logo icon and the wordmark, not inside the wordmark itself. */
.wordmark b {
  color: var(--color-brand-light);
  font-weight: inherit
}

.navlinks {
  display: flex;
  gap: 20px;
  align-items: center;
  font-size: 12px;
  font-weight: 650
}

.navlinks a:hover {
  color: var(--color-brand)
}

/* Current-page nav link — header.njk sets aria-current="page" on the
   matching item, this just gives it a visible color so it's clear which
   page you're on (also lifts the {% icon %} next to "Home" via
   currentColor, no separate rule needed for that). */
.navlinks a[aria-current="page"] {
  color: var(--color-brand);
  font-weight: 800
}

.navcta {
  background: var(--color-action);
  color: var(--color-white) !important;
  padding: 9px 14px;
  border-radius: 10px
}

.menu {
  display: none;
  align-items: center;
  justify-content: center;
  background: none;
  border: 0;
  color: var(--color-text);
  padding: 4px
}

/* ---- Buttons ---------------------------------------------------- */

.btn {
  display: inline-flex;
  justify-content: center;
  align-items: center;
  gap: 7px;
  border: 0;
  border-radius: 11px;
  padding: 12px 17px;
  font-size: 13px;
  font-weight: 750;
  transition: .2s
}

.btn:hover {
  transform: translateY(-1px)
}

.primary {
  background: var(--color-action);
  color: var(--color-white);
  box-shadow: 0 8px 25px var(--tint-action-shadow)
}

.light {
  background: var(--color-white);
  border: 1px solid var(--color-border-strong);
  color: var(--color-slate-700)
}

.dark {
  background: var(--color-dark-bg);
  color: var(--color-white)
}

/* .btn.dark only needs to stretch full-width when it's the last element
   inside a card (Services' "Enquire", Portfolio's "See Real Examples") —
   there it matches the card's own width on purpose. Everywhere else (a
   centered section CTA, a .faq-cta banner row) it should size to its own
   text like every other button; .dark used to force width:100% globally,
   which is why "See All Services", "More About Us" and the faq-cta
   buttons were stretching edge-to-edge instead of fitting their label. */
.card .btn.dark {
  width: 100%
}

.textbtn {
  font-size: 13px;
  color: var(--color-text-soft);
  padding: 10px
}

.full {
  width: 100%;
  margin-top: 14px
}

/* ---- Text helpers ------------------------------------------------ */

.micro,
.muted {
  font-size: 11px;
  color: var(--color-text-muted)
}

.lead {
  font-size: 17px;
  color: var(--color-text-soft);
  max-width: 700px
}

.lead b {
  color: var(--color-brand)
}

.tag,
.pill,
.badge {
  display: inline-block;
  font-family: var(--font-subchild);
  border-radius: 999px;
  font-size: 11px;
  font-weight: 750
}

.tag {
  padding: 6px 11px;
  background: var(--color-brand-soft);
  color: var(--color-brand-strong);
  text-transform: uppercase;
  letter-spacing: .08em
}

/* ---- Card family (shared "surface" look) -------------------------- */
/* Individual card types (.price-card, .contact-box, .portfolio, .tech,
   .coverage) get their sizing/padding in pages.css — this just gives
   every one of them the same white-surface-with-border base look.
   Shadow lifts them off the site's green-tinted background instead of
   relying on the 1px border alone. .price-card overrides this with its
   own larger floating shadow further down in pages.css. */

.price-card,
.card,
.contact-box,
.portfolio,
.tech,
.faq,
.coverage {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: 18px;
  box-shadow: 0 4px 16px var(--tint-card-shadow)
}

.card {
  padding: 23px
}

.service {
  display: flex;
  flex-direction: column
}

.icon {
  width: 48px;
  height: 48px;
  border-radius: 14px;
  background: var(--color-brand-soft);
  color: var(--color-brand);
  display: grid;
  place-items: center;
  font-weight: 900;
  margin-bottom: 12px
}

/* The icon shortcode hard-codes width/height/stroke-width on each <svg> at
   the call site (usually 22/1.6) — CSS here overrides those so every
   card-icon badge site-wide gets a slightly larger, slightly bolder glyph
   that actually fills the badge instead of looking small and thin next to
   the bold heading it sits above. */
.icon svg {
  width: 24px;
  height: 24px;
  stroke-width: 2
}

.badge {
  padding: 5px 9px;
  background: var(--color-bg-alt);
  color: var(--color-text-soft);
  border: 1px solid var(--color-border);
  align-self: flex-start
}

/* Small "visit/view" link at the bottom of a .card — used on About's
   GitHub credibility badge and each real client card on /portfolio/. */
.card-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 10px;
  font-size: 11px;
  font-weight: 700;
  color: var(--color-brand-strong)
}

.card-link:hover {
  text-decoration: underline
}

.card h3,
.tour h3,
.portfolio h3,
.tech h3 {
  font-size: 17px;
  margin: 8px 0 5px
}

/* Card header row — icon sits inline beside its title instead of stacked
   above it, so the two read as one matched unit rather than two separately-
   aligned elements. Used by every standard "icon badge + heading" card
   (Home's two grids, Services, About's adv cards, Where We Work's "Also
   Serving" grid) — the About timeline (icon + date tag + heading) and
   Where We Work's area-info (icon + count badge + heading) keep their own
   stacked layout since they carry an extra badge between icon and title. */
.card-head {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 10px
}

.card-head .icon {
  margin-bottom: 0;
  flex-shrink: 0
}

.card-head h3 {
  margin: 0
}

.card p,
.tour p {
  font-size: 12px;
  color: var(--color-text-muted)
}

.card ul,
.tour ul {
  padding: 0;
  list-style: none;
  font-size: 12px;
  color: var(--color-slate-700);
  line-height: 1.8
}

.ideal {
  margin-top: auto;
  background: var(--color-bg);
  padding: 10px;
  border-radius: 10px;
  font-size: 11px;
  color: var(--color-text-muted);
  margin-bottom: 14px
}

/* Generic "big price" display — used standalone on /pricing/ and
   inside the home hero's .price-card (page-specific wrapper) */
.price {
  font-family: var(--font-subchild);
  font-size: 28px;
  font-weight: 900;
  text-align: right
}

.price small {
  font-size: 10px;
  color: var(--color-text-muted);
  font-weight: 500
}

.mini {
  padding: 12px;
  margin-top: 12px;
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: 12px;
  box-shadow: 0 4px 16px var(--tint-card-shadow)
}

.mini b {
  font-size: 12px
}

.mini p {
  font-size: 11px;
  color: var(--color-text-muted);
  margin: 3px 0 0
}

/* Dark variant — opt-in via an extra "dark" class alongside .mini (used on
   Contact's Call/Email/Coverage row). Reuses the same dark surface as
   .dark-banner / .final-cta so it stays visually consistent with the rest
   of the site's dark sections rather than introducing a new dark tone. */
.mini.dark {
  background: var(--gradient-dark);
  border-color: var(--color-slate-700);
  color: var(--color-white)
}

.mini.dark p {
  color: var(--color-slate-300)
}

/* Dark promo banner — used on Home (tourism block) and Services (tech) */
.dark-banner {
  max-width: 1120px;
  margin: 0 auto 38px;
  background: var(--gradient-dark);
  color: var(--color-white);
  border: 1px solid var(--color-slate-700);
  border-radius: 18px;
  padding: 26px;
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 25px;
  align-items: center
}

.dark-banner small {
  color: var(--color-brand-lighter);
  font-weight: 800
}

.dark-banner h3 {
  font-family: var(--font-parent);
  font-size: 22px;
  margin: 8px 0
}

.dark-banner p {
  color: var(--color-slate-300);
  font-size: 13px;
  margin: 0;
  max-width: 720px
}

/* ---- FAQ accordion (shared between Home's preview and the full /faq/ list) - */

.faq-list {
  display: grid;
  gap: 9px
}

.faq {
  overflow: hidden
}

.faq-q {
  width: 100%;
  padding: 17px;
  text-align: left;
  border: 0;
  background: var(--color-white);
  font-weight: 750;
  font-size: 13px;
  display: flex;
  align-items: center;
  justify-content: space-between
}

.faq-a {
  display: none;
  padding: 0 17px 17px;
  color: var(--color-text-muted);
  font-size: 12px;
  border-top: 1px solid var(--color-bg-alt)
}

.faq.open .faq-a {
  display: block
}

.faq.open .faq-q .faq-chevron {
  transform: rotate(180deg);
  color: var(--color-brand)
}

/* Optional leading icon badge on a .faq-q button (used where a question
   list benefits from a quick visual scan, e.g. Home's "realtalk" section)
   — text and chevron alone (the FAQ page default) don't need this wrapper
   at all, so it only appears where a template actually adds it. */
.faq-q-label {
  display: flex;
  align-items: center;
  gap: 12px
}

.faq-q-icon {
  flex-shrink: 0;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--color-brand-soft);
  color: var(--color-brand);
  display: grid;
  place-items: center;
  font-weight: 800;
  font-size: 13px
}

/* "Still have a question?" banner — the full accordion's own CTA on /faq/,
   and re-used on /contact/ as a compact pointer to that page. */
.faq-cta {
  margin-top: 30px;
  background: var(--color-brand-soft);
  border: 1px solid var(--color-brand-border);
  border-radius: 15px;
  padding: 20px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 20px;
  box-shadow: 0 4px 16px var(--tint-card-shadow)
}

.faq-cta p {
  font-size: 11px;
  color: var(--color-text-muted);
  margin: 3px 0
}

/* ---- Final CTA band (Home / Services / About) ------------------------ */

.final-cta {
  background: var(--gradient-dark);
  color: var(--color-white);
  padding: 64px 20px;
  text-align: center
}

.final-cta h2 {
  font-family: var(--font-parent);
  font-size: clamp(24px, 3.5vw, 34px);
  margin: 0 0 10px;
  letter-spacing: -.5px
}

.final-cta p {
  color: var(--color-slate-300);
  font-size: 14px;
  margin: 0 auto 22px;
  max-width: 520px
}

/* ---- Footer (every page, via base layout) ----------------------------- */

.footer-cta {
  background: var(--gradient-footer-cta);
  color: var(--color-white);
  padding: 30px max(20px, calc((100% - 1120px)/2));
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 20px
}

.footer-cta h3,
.footer-cta h2,
.footer-cta-title {
  margin: 0;
  font-size: 19px
}

.footer-cta p {
  font-size: 11px;
  color: var(--color-slate-300);
  margin: 4px 0
}

.footer-main {
  background: var(--color-darkest);
  color: var(--color-slate-400);
  padding: 50px max(20px, calc((100% - 1120px)/2));
  display: grid;
  grid-template-columns: 2fr 1fr 1fr;
  gap: 50px
}

.inverse {
  color: var(--color-white)
}

.footer-main p,
.footer-main a,
.footer-main span {
  display: block;
  font-size: 11px;
  line-height: 1.8
}

/* .footer-main a/span above (meant for the Services/Contact link lists)
   also matches the brand logo link and its ".Studio" span, since both
   sit inside .footer-main too — same specificity, so whichever rule is
   declared last just wins outright, stomping .brand's flex layout and
   font-size. Re-declared here with 2 classes' worth of specificity so
   the brand mark stays a single row (logo + wordmark) instead of
   stacking into 3 lines. */
.footer-main .brand {
  display: flex;
  font-size: 19px
}

/* Tagline sits right under the wordmark, above the descriptive
   paragraph — its own line rather than fused into the name (that's
   what ".Studio" used to do, and it wasn't actually part of the
   brand). .footer-main p above already sets font-size/line-height;
   this just adds color + spacing + weight on top. */
.tagline {
  color: var(--color-brand-lighter);
  font-weight: 700;
  letter-spacing: .02em;
  margin: 6px 0 10px
}

.footer-main h4 {
  font-size: 11px;
  text-transform: uppercase;
  color: var(--color-white)
}

.footer-main a:hover {
  color: var(--color-brand-lighter)
}

/* Facebook / Trustpilot / Google brand marks under the footer description —
   real logos rather than text links so they read instantly as credibility
   signals. Icons inherit .footer-main's slate-400 -> brand-lighter hover. */
.social-icons {
  display: flex;
  gap: 14px;
  margin-top: 14px
}

.social-icons a {
  display: flex
}

.copyright {
  background: var(--color-darkest);
  border-top: 1px solid var(--color-dark-bg-2);
  color: var(--color-text-muted);
  text-align: center;
  padding: 14px;
  font-size: 10px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px
}

.footer-legal a {
  color: var(--color-text-muted)
}

.footer-legal a:hover {
  color: var(--color-white)
}

.footer-legal span {
  margin: 0 6px;
  opacity: .5
}

/* ---- Floating WhatsApp CTA (every page, via base layout) -------------- */

.sticky {
  display: none;
  position: fixed;
  right: 18px;
  bottom: 18px;
  background: var(--color-dark-bg);
  color: var(--color-white);
  border: 1px solid var(--color-slate-700);
  padding: 9px 10px 9px 14px;
  border-radius: 15px;
  align-items: center;
  gap: 10px;
  box-shadow: 0 15px 35px var(--tint-sticky-shadow);
  font-size: 11px;
  z-index: 20
}

.sticky a {
  padding: 9px;
  border-radius: 50%;
  background: var(--color-dark-bg-2)
}

.sticky .wa {
  border-radius: 999px;
  background: var(--color-action);
  font-weight: 800
}

.sticky button {
  position: absolute;
  right: -10px;
  top: -10px;
  border: 0;
  border-radius: 50%;
  background: var(--color-slate-700);
  color: var(--color-white);
  width: 25px;
  height: 25px
}

.sticky.show {
  display: flex
}

/* ---- App-style bottom tab bar (mobile only, see responsive.css) ------
   Two jobs: quick navigation, and looking/feeling enough like a native
   app that it prompts "can my site do that?" from a visitor — see
   app-nav.njk's header comment. Hidden here (desktop default); shown
   below 900px in responsive.css, replacing the .sticky bubble there. */

.app-nav {
  display: none;
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 30;
  background: var(--color-surface);
  border-top: 1px solid var(--color-border);
  box-shadow: 0 -8px 24px var(--tint-card-shadow);
  padding: 6px 4px calc(6px + env(safe-area-inset-bottom, 0px));
}

.app-nav-item {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  padding: 6px 2px;
  color: var(--color-text-muted);
  font-size: 10px;
  font-weight: 700;
  text-align: center
}

.app-nav-item[aria-current="page"] {
  color: var(--color-brand)
}

.app-nav-cta {
  color: var(--color-action)
}

.app-nav-cta-bubble {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  margin-top: -20px;
  border-radius: 50%;
  background: var(--color-action);
  color: var(--color-white);
  box-shadow: 0 8px 18px var(--tint-action-shadow);
  border: 3px solid var(--color-surface)
}

/* Soft expanding ring behind the WhatsApp bubble — the "flicker" meant
   to catch a first-time visitor's eye, not an urgent/alarming blink.
   Respects prefers-reduced-motion below. */
.app-nav-ping {
  position: absolute;
  inset: -3px;
  border-radius: 50%;
  background: var(--color-action);
  animation: appNavPing 2.4s cubic-bezier(0, 0, .2, 1) infinite
}

@keyframes appNavPing {
  0% { opacity: .55; transform: scale(1) }
  75%, 100% { opacity: 0; transform: scale(1.7) }
}

@media (prefers-reduced-motion: reduce) {
  .app-nav-ping {
    animation: none;
    display: none
  }
}

/* Responsive breakpoints used to live here. Moved to responsive.css,
   which @imports LAST from style.css — see that file's header comment
   for why (a real bug this caused on the Home hero). Add new
   breakpoint rules there, not here. */
