:root {
  --bg: #f2f5f2;
  --card: #fff;
  --border: #dae3dc;
  --accent: #0f231e;
  --band: #e3ebe5;
  --muted: #6c7671;
  --faint: #98a29c;
  --done: #dcebe2;
  --todo: #e1e9e3;
  --soft: #e6efe9;
  --warn-bg: #f7e9e3;
  --warn-tx: #b3452e;
  --warn-tx-lite: #efbdb3;
  --gift-bg: #fffaf0;
  --gift-bar: #fdefd2;
  --gift-line: #f0dcb4;
  --radius: 14px;
  --radius-sm: 12px;
  /* tokens.css ships these warm; override to the cool-green neutral family
     (they are used directly, unlike --ph/--code-*/--bonus-* which aren't) */
  --line: #dfe8e1;
  --sub: #7c8779;
  /* muted brown-gold for the "invited, not active yet" friend node; --gold read
     against white is too bright for a state that isn't actionable yet */
  --gold-muted: #ad8a4e;
}

* {
  box-sizing: border-box;
}

/* focus ring: accent-colored, keyboard-only (mouse clicks don't show it) */
a:focus,
button:focus,
input:focus,
select:focus,
textarea:focus,
.cell:focus,
[tabindex]:focus {
  outline: none;
}

a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
.cell:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

html {
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--accent);
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  line-height: 1.5;
}

.container {
  width: 100%;
  max-width: 1100px;
  margin: 0 auto;
  padding: 0 16px;
}

/* ---- page transitions ---- */
@media (prefers-reduced-motion: no-preference) {
  @view-transition { navigation: auto; }
}

/* ---- header / footer ---- */
/* the header card lines up with the profile dashboard, not the 1100px
   .container column — one width for both, so they never drift apart.
   .container pages (public status, 404) keep their narrower column centred
   under the same header. */
.hdr-wrap,
.profile {
  width: 100%;
  max-width: min(1500px, calc(100vw - 48px));
  margin: 0 auto;
}

.hdr {
  display: flex;
  align-items: center;
  gap: 14px;
  height: 58px;
  padding: 0 18px;
  margin: 14px 0 16px;
  background: var(--card);
  border-radius: var(--r-card);
  box-shadow: var(--sh-card);
}

.hdr .sp {
  margin-left: auto;
}

/* subscription status next to the logo, behind a hairline rule (the 20px on
   its left is 6px here + the .hdr gap). Profile page only — every other page
   leaves it out of the markup. */
.hdr-sub {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: 6px;
  padding-left: 20px;
  padding-right: 20px;
  border-left: 1px solid var(--line);
  font-size: 13px;
  color: var(--sub);
  white-space: nowrap;
}

.hdr-sub b {
  color: var(--ink);
  font-weight: 600;
}

.hdr-dot {
  flex: none;
  width: 7px;
  height: 7px;
  border-radius: var(--r-pill);
  background: var(--ok);
}

.hdr-dot.bad {
  background: var(--bad);
}

/* no room for the status next to the links on a phone — logo + nav only */
@media (max-width: 560px) {
  .hdr-sub {
    display: none;
  }
}

.logo {
  display: flex;
  align-items: center;
  align-self: stretch;
  font-weight: 800;
  font-size: 18px;
  letter-spacing: -0.02em;
  color: var(--accent);
  text-decoration: none;
}

.navlink {
  color: var(--accent);
  text-decoration: none;
  font-size: 14px;
}

/* 12px keeps the link's box at the 44px minimum touch size */
:is(.hdr, .hero-hdr) .navlink {
  padding: 12px;
  border-radius: 10px;
  font-size: 14px;
}

.hdr .navlink.on {
  background: var(--sel-bg);
}

.hdr .navlink.linkbtn {
  color: var(--sub);
}

.hdr .navlink.linkbtn:hover,
.hdr .navlink.linkbtn:focus-visible {
  color: var(--accent);
}

/* ---- shared bits ---- */
.card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px;
}

.card.center {
  text-align: center;
  display: flex;
  flex-direction: column;
  gap: 12px;
  align-items: center;
}

.page-title {
  margin: 24px 0 14px;
  font-size: 24px;
  letter-spacing: -0.02em;
}

.muted {
  color: var(--muted);
}

.btn {
  border: 0;
  border-radius: 13px;
  padding: 16px 24px;
  font: inherit;
  font-weight: 700;
  text-align: center;
  background: var(--accent);
  color: var(--bg);
  text-decoration: none;
  display: block;
  cursor: pointer;
  transition: filter 120ms ease, transform 60ms ease, box-shadow 120ms ease;
}

.btn-w {
  background: var(--card);
  color: var(--accent);
  border: 1px solid #cbd6ce;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
}

.btn:hover {
  filter: brightness(1.12);
}
.btn:active {
  transform: translateY(1px);
}
.btn-w:hover {
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}

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

.num {
  display: inline-grid;
  place-items: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--bg);
  font-size: 11px;
  font-weight: 750;
  flex: none;
}

.pill {
  font-size: 11px;
  font-weight: 750;
  padding: 2px 10px;
  border-radius: 999px;
  letter-spacing: 0.02em;
}

.pill.soft {
  background: var(--soft);
  color: var(--accent);
}

.pill.warn {
  background: var(--warn-bg);
  color: var(--warn-tx);
}

/* ---- landing: three full-height screens (hero, prices, arguments) ---- */
.screen {
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}

.dark {
  background: linear-gradient(180deg, var(--accent), var(--accent-end));
  color: #fff;
}

/* the page scrollbar is hidden and one wheel click equals one screen; snapping
   is off on short windows and on touch, where the page scrolls as usual */
html:has(.screen) {
  scroll-behavior: smooth;
  scrollbar-width: none;
}

html:has(.screen)::-webkit-scrollbar {
  display: none;
}

@media (min-height: 720px) and (pointer: fine) {
  html:has(.screen) {
    scroll-snap-type: y mandatory;
  }
  .screen {
    scroll-snap-align: start;
    scroll-snap-stop: always;
  }
}

@media (prefers-reduced-motion: reduce) {
  html:has(.screen) {
    scroll-behavior: auto;
  }
}

/* same plate as .hdr, but glass: translucent white over the hero gradient, so
   the gradient stays the ground of the first screen */
.hero-hdr {
  display: flex;
  align-items: center;
  gap: 14px;
  height: 58px;
  padding: 0 18px;
  margin: 14px auto 0;
}

/* the glass surface itself, shared with the base .hdr on the green pages
   (profile, public status) — there the white plate would read as a hole */
:is(.hero-hdr, body:has(.profile) .hdr, body:has(.public) .hdr, body:has(.notfound) .hdr) {
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: var(--r-card);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  box-shadow: none;
}

.hero-hdr .sp {
  margin-left: auto;
}

:is(.hero-hdr, body:has(.profile) .hdr, body:has(.public) .hdr, body:has(.notfound) .hdr) .logo,
:is(.hero-hdr, body:has(.profile) .hdr, body:has(.public) .hdr, body:has(.notfound) .hdr) .navlink {
  color: #fff;
}

:is(.hero-hdr, body:has(.profile) .hdr, body:has(.public) .hdr, body:has(.notfound) .hdr) .navlink.on {
  background: rgba(255, 255, 255, 0.2);
}

:is(.hero-hdr, body:has(.profile) .hdr, body:has(.public) .hdr, body:has(.notfound) .hdr) .navlink.linkbtn {
  opacity: 0.75;
}

/* the white plate's hover (dark --accent) disappears on glass — brighten
   instead of recolouring */
:is(body:has(.profile) .hdr, body:has(.public) .hdr, body:has(.notfound) .hdr) .navlink.linkbtn:hover,
:is(body:has(.profile) .hdr, body:has(.public) .hdr, body:has(.notfound) .hdr) .navlink.linkbtn:focus-visible {
  color: #fff;
  opacity: 1;
}

/* subscription status on glass: --sub/--ink/--line are page values */
body:has(.profile) .hdr .hdr-sub {
  color: rgba(255, 255, 255, 0.72);
  border-left-color: rgba(255, 255, 255, 0.22);
}

body:has(.profile) .hdr .hdr-sub b {
  color: #fff;
}

body:has(.profile) .hdr .hdr-dot {
  background: #7fd6ab;
}

body:has(.profile) .hdr .hdr-dot.bad {
  background: #eda893;
}

.hero-inner {
  flex: 1;
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
  align-items: center;
  gap: 56px;
  padding: 40px 16px 56px;
}

.hero-left h1 {
  margin: 0;
  font-size: clamp(40px, 4.6vw + 18px, 76px);
  line-height: 0.98;
  font-weight: 700;
  letter-spacing: -0.04em;
}

.hero-left .tagline {
  margin: 16px 0 0;
  color: rgba(255, 255, 255, 0.84);
  font-size: clamp(17px, 0.5vw + 15px, 20px);
  line-height: 1.45;
  max-width: 420px;
}

.hero-left .giftbanner {
  margin-left: 0;
}

.cta {
  display: inline-block;
  border: 0;
  background: #fff;
  color: var(--accent);
  font: inherit;
  font-size: 18px;
  font-weight: 650;
  padding: 16px 32px;
  border-radius: var(--r-pill);
  cursor: pointer;
  box-shadow: var(--sh-button);
}

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

.hero-left .cta {
  margin-top: 30px;
}

/* burnt orange: the complement of the dark green, white text on top */
.cta.accent {
  background: #c85f2c;
  color: #fff;
  box-shadow: 0 8px 20px rgba(200, 95, 44, 0.34);
}

.rainbow {
  font-weight: 800;
  background: linear-gradient(90deg,
    #ffe14d 0%, #ffffff 12%, #7fe3ff 25%, #ffffff 37%,
    #9dff9d 50%, #ffffff 62%, #ffb0e6 75%, #ffffff 87%, #ffe14d 100%);
  background-size: 400% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

@media (prefers-reduced-motion: no-preference) {
  .rainbow {
    animation: rainbow 8s linear infinite;
  }
}

@keyframes rainbow {
  to {
    background-position: -400% 0;
  }
}

.hero-alt {
  margin: 7px 0 0;
  font-size: 15px;
  display: flex;
  flex-wrap: wrap;
  gap: 6px 20px;
}

.hero-alt a {
  padding: 11px 0;
  color: rgba(255, 255, 255, 0.82);
  text-underline-offset: 4px;
}

.brief {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
  align-content: center;
}

.brief-item {
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: var(--r-card);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  padding: 18px 18px 20px;
  transition: transform 0.18s ease, background 0.18s ease;
}

@media (prefers-reduced-motion: no-preference) {
  .brief-item:hover {
    transform: translateY(-4px);
    background: rgba(255, 255, 255, 0.1);
  }
}

.brief-item .eyebrow {
  display: block;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.5);
  margin-bottom: 7px;
}

.brief-item h2 {
  margin: 0 0 6px;
  font-size: 18px;
  font-weight: 650;
  letter-spacing: -0.015em;
  text-wrap: balance;
}

.brief-item p {
  margin: 0;
  color: rgba(255, 255, 255, 0.78);
  font-size: 14px;
  line-height: 1.5;
}

/* one row: on a narrow screen it scrolls sideways instead of wrapping */
.chips {
  display: flex;
  flex-wrap: nowrap;
  gap: 6px;
  margin-top: 18px;
  overflow-x: auto;
  scrollbar-width: none;
  padding-bottom: 2px;
}

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

.chips span {
  flex: 0 0 auto;
  font-size: 12px;
  padding: 4px 10px;
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.12);
  white-space: nowrap;
}

/* the sign that screens follow below; same glass as .hero-hdr */
.scroll-cue {
  position: relative;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  margin: 0 auto 22px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.06);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  color: rgba(255, 255, 255, 0.8);
}

.scroll-cue::after {
  content: '';
  position: absolute;
  inset: -5px;
}

.scroll-cue:hover {
  color: #fff;
}

@media (prefers-reduced-motion: no-preference) {
  .scroll-cue {
    animation: cue 1.8s ease-in-out infinite;
  }
}

/* its own keyframes: the popup button's nudge drags translateX */
@keyframes cue {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(4px);
  }
}

/* ---- landing screen 2: Unlimited prices ---- */
.prices {
  justify-content: center;
  padding: 56px 0 60px;
}

.sec-head {
  text-align: center;
  margin: 0 auto 30px;
  max-width: 640px;
}

.sec-head h2 {
  margin: 0 0 10px;
  font-size: clamp(26px, 2vw + 16px, 38px);
  line-height: 1.15;
  font-weight: 650;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

.sec-head p {
  margin: 0;
  color: var(--sub);
  font-size: 17px;
}

.prices .sec-head {
  max-width: 940px;
}

@media (min-width: 900px) {
  .prices .sec-head h2 {
    white-space: nowrap;
  }
}

.prices .refdead {
  margin: 8px 0 0;
  color: var(--warn-tx);
  font-size: 15px;
}

/* the price cards, scoped under .prices: landing-only */
.prices .plans {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 14px;
}

.prices .plan {
  cursor: pointer;
  transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-sheet);
  padding: 24px 22px 20px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  box-shadow: var(--sh-card);
}

.prices .plan.best {
  border-color: var(--accent-end);
  box-shadow: 0 10px 26px rgba(24, 49, 45, 0.12);
}

@media (prefers-reduced-motion: no-preference) {
  .prices .plan.best {
    transform: translateY(-6px);
  }
  .prices .plan:not(.best):hover {
    transform: translateY(-3px);
  }
}

.plan-top {
  display: flex;
  align-items: center;
  gap: 10px;
}

.plan-len {
  font-size: 20px;
  font-weight: 650;
  letter-spacing: -0.01em;
}

.save {
  background: #ffd45e;
  color: #4a3506;
  font-size: 12px;
  font-weight: 700;
  padding: 3px 9px;
  border-radius: var(--r-pill);
}

.price {
  display: flex;
  align-items: baseline;
  gap: 7px;
  margin-top: auto;
}

.price b {
  font-size: clamp(32px, 2.4vw + 18px, 44px);
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.price span {
  color: var(--sub);
  font-size: 15px;
}

.plan-buy {
  border: 1px solid var(--accent);
  background: var(--card);
  color: var(--accent);
  font: inherit;
  font-size: 15px;
  font-weight: 600;
  padding: 12px 16px;
  border-radius: var(--r-card);
  cursor: pointer;
}

/* display:contents — the funnel form must not become the card's flex item */
.prices .plan form {
  display: contents;
}

.prices .plan.best .plan-buy {
  background: var(--accent);
  color: #fff;
}

.plan-buy:hover {
  opacity: 0.9;
}

.plan-note {
  margin: 0;
  color: var(--sub);
  font-size: 13px;
}

.or {
  display: flex;
  align-items: center;
  gap: 16px;
  margin: 26px 0 18px;
  color: var(--sub);
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-weight: 700;
}

.or::before,
.or::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--line);
}

.freeband {
  background: var(--accent);
  color: #fff;
  border-radius: var(--r-sheet);
  padding: 24px 26px;
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 20px;
}

.freeband h3 {
  margin: 0 0 6px;
  font-size: clamp(20px, 1.3vw + 15px, 26px);
  font-weight: 650;
  letter-spacing: -0.015em;
}

.freeband p {
  margin: 0;
  font-size: 15px;
  color: rgba(255, 255, 255, 0.88);
  max-width: 560px;
}

.freeband .cta {
  box-shadow: none;
  background: #c85f2c;
  color: #fff;
  white-space: nowrap;
}

.freeband .cta:hover {
  background: #d86c37;
}

.promo-line {
  margin: 16px 0 0;
  text-align: center;
  color: var(--sub);
  font-size: 15px;
}

/* the promo trigger is a button (the popup opens with no navigation), the shared
   .linkbtn shrunk to look like the link it reads as */
.promo-line .linkbtn {
  font-size: inherit;
  padding: 0;
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* ---- landing screen 3: arguments ---- */
.why {
  justify-content: center;
  padding: 52px 0 56px;
}

.why .sec-head {
  margin-bottom: 26px;
}

.why .sec-head h2 {
  color: #fff;
}

.why .sec-head p {
  color: rgba(255, 255, 255, 0.72);
}

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

/* seven arguments: the first one spans two cells so the rows stay even */
.args .arg:first-child {
  grid-column: span 2;
}

.arg {
  position: relative;
  overflow: hidden;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: var(--r-card);
  padding: 18px 16px;
  transition: transform 0.18s ease, background 0.18s ease;
}

.arg::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 4px;
  background: var(--arg-hue, #ffd45e);
}

.arg:nth-child(1) { --arg-hue: #ffd45e; }
.arg:nth-child(2) { --arg-hue: #7fe3ff; }
.arg:nth-child(3) { --arg-hue: #9dff9d; }
.arg:nth-child(4) { --arg-hue: #de7a45; }
.arg:nth-child(5) { --arg-hue: #ffb0e6; }
.arg:nth-child(6) { --arg-hue: #b9a3ff; }
.arg:nth-child(7) { --arg-hue: #ffe14d; }

@media (prefers-reduced-motion: no-preference) {
  .arg:hover {
    transform: translateY(-4px);
    background: rgba(255, 255, 255, 0.1);
  }
}

.arg h3 {
  margin: 0 0 6px;
  font-size: 16px;
  font-weight: 650;
  letter-spacing: -0.015em;
  text-wrap: balance;
}

.arg p {
  margin: 0;
  color: rgba(255, 255, 255, 0.76);
  font-size: 14px;
  line-height: 1.5;
}

/* minmax(0, …) everywhere a track collapses to one column: a bare 1fr floors at
   the item's min-content, and the sideways-scrolling .chips row is 429px wide —
   that floor widened the whole document at every phone width. */
@media (max-width: 900px) {
  .hero-inner {
    grid-template-columns: minmax(0, 1fr);
    gap: 30px;
    align-content: center;
  }
  .hero-left .tagline {
    max-width: none;
  }
  .brief {
    grid-template-columns: minmax(0, 1fr);
  }
  .freeband {
    grid-template-columns: minmax(0, 1fr);
  }
  .args {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 560px) {
  .screen {
    min-height: 0;
  }
  .hero-inner {
    padding: 28px 16px 40px;
  }
  .cta {
    width: 100%;
    padding: 16px 20px;
  }
  .prices,
  .why {
    padding: 44px 0 48px;
  }
  .args {
    grid-template-columns: minmax(0, 1fr);
  }
  .args .arg:first-child {
    grid-column: auto;
  }
  .freeband {
    padding: 20px 18px;
  }
  .promo-line .linkbtn {
    padding: 11px 0;
  }
}

/* landing gift-invite button (sn_ref cookie present): the manual entry into the
   gift branch, so it has to look and feel pressable */
.giftbanner {
  display: block;
  width: fit-content;
  background: var(--friend);
  color: #fff;
  font-family: inherit;
  font-size: 12px;
  font-weight: 700;
  border: 0;
  border-radius: var(--r-pill);
  padding: 6px 14px;
  margin: 0 auto 14px;
  text-align: center;
  cursor: pointer;
  transition: filter 0.15s ease, transform 0.15s ease;
}

.giftbanner:hover {
  filter: brightness(1.08);
  transform: translateY(-1px);
}

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

/* ---- popup shell ---- */
.scrim {
  position: fixed;
  inset: 0;
  background: rgba(23, 21, 18, 0.45);
  z-index: 40;
}

.popup {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: grid;
  /* minmax(0,1fr) — a bare implicit auto track sizes to the card's
     max-content (.popup-card's max-width: 560px) and overflows a phone
     viewport, widening the whole document. Same fix as .profile-grid. */
  grid-template-columns: minmax(0, 1fr);
  place-items: center;
  height: 100dvh;
  padding: 16px;
  overflow: auto;
  overscroll-behavior: contain;
}

/* the card scrolls itself, so .pop-more can sit on its bottom edge */
.popup-wrap {
  position: relative;
  width: 100%;
  max-width: 640px;
}

.popup-card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 18px;
  width: 100%;
  max-width: 640px;
  max-height: calc(100dvh - 32px);
  overflow-y: auto;
  scrollbar-width: none;
  box-shadow: 0 12px 32px rgba(23, 21, 18, 0.22);
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.popup-card::-webkit-scrollbar {
  display: none;
}

/* the card is a height-capped flex column, so a child with a zero automatic
   minimum size (.ladder, .zone-connect, .zone-ref — all overflow: hidden) gets
   squeezed to nothing and clips its own rows instead of scrolling the card. */
.popup-card > * {
  flex-shrink: 0;
}

/* scroll hint: shown by popup.js only while content is left below the fold */
.pop-more {
  position: absolute;
  left: 50%;
  bottom: 14px;
  transform: translateX(-50%);
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--accent);
  color: var(--bg);
  box-shadow: 0 4px 12px rgba(23, 21, 18, 0.2);
  cursor: pointer;
}

.pop-more::after {
  content: '';
  position: absolute;
  inset: -7px 0;
}

.pop-more[hidden] {
  display: none;
}

@media (prefers-reduced-motion: no-preference) {
  .pop-more {
    animation: nudge 1.8s ease-in-out infinite;
  }
}

@keyframes nudge {
  0%,
  100% {
    transform: translateX(-50%) translateY(0);
  }
  50% {
    transform: translateX(-50%) translateY(4px);
  }
}

/* popup open animation: popup.js adds .popup-enter once, at creation, to the
   scrim and card — swap() (screen-to-screen transitions inside an already
   open popup) never re-adds it, so it plays only when the popup itself
   appears. Reduced motion drops both keyframes to a no-op (instant show). */
@media (prefers-reduced-motion: no-preference) {
  .popup-card.popup-enter {
    animation: popup-card-in 0.2s cubic-bezier(0.34, 1.56, 0.5, 1);
  }

  .scrim.popup-enter {
    animation: scrim-in 0.2s cubic-bezier(0.34, 1.56, 0.5, 1);
  }
}

@keyframes popup-card-in {
  from {
    opacity: 0;
    transform: scale(0.9);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}

@keyframes scrim-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

.popup-title {
  margin: 0;
  font-size: 18px;
  text-align: center;
  letter-spacing: -0.02em;
}

.popup-note {
  margin: 0;
  text-align: center;
  color: var(--muted);
  font-size: 13px;
}

.popup-note.justify {
  text-align: justify;
  hyphens: auto;
}

/* native <dialog> reusing the .popup-card look (e.g. account-delete confirm) */
dialog.popup-card:not([open]) {
  display: none;
}

dialog.popup-card::backdrop {
  background: rgba(23, 21, 18, 0.45);
}

@media (prefers-reduced-motion: no-preference) {
  dialog.popup-card {
    opacity: 1;
    transform: scale(1);
    transition: opacity 0.18s ease-out, transform 0.18s ease-out, display 0.18s allow-discrete, overlay 0.18s allow-discrete;
  }

  dialog.popup-card:not([open]) {
    opacity: 0;
    transform: scale(0.96);
  }

  @starting-style {
    dialog.popup-card[open] {
      opacity: 0;
      transform: scale(0.96);
    }
  }

  dialog.popup-card::backdrop {
    transition: background 0.18s ease-out, display 0.18s allow-discrete, overlay 0.18s allow-discrete;
  }

  @starting-style {
    dialog.popup-card[open]::backdrop {
      background: rgba(23, 21, 18, 0);
    }
  }
}

/* section headings inside a multi-paragraph nested screen (e.g. Friends "О программе") */
.popup-subtitle {
  margin: 4px 0 0;
  font-size: 14px;
  font-weight: 700;
}

/* powerline stage tracker */
.powerline {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
  justify-content: center;
  font-size: 10px;
  font-weight: 750;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

/* header login (and linkEmail) render with no steps — an empty tracker div
   should not still eat the .popup-card gap above the title. */
.powerline:empty {
  display: none;
}

.powerline .seg {
  padding: 5px 18px 5px 19px;
  margin-left: -8px;
  clip-path: polygon(0 0, calc(100% - 8px) 0, 100% 50%, calc(100% - 8px) 100%, 0 100%, 8px 50%);
}

.powerline .seg:first-child {
  margin-left: 0;
  padding-left: 14px;
  clip-path: polygon(0 0, calc(100% - 8px) 0, 100% 50%, calc(100% - 8px) 100%, 0 100%);
}

.powerline .done {
  background: var(--done);
  color: var(--accent);
}

.powerline .cur {
  background: var(--accent);
  color: var(--bg);
}

.powerline .todo {
  background: var(--todo);
  color: var(--faint);
}

/* ---- public status ---- */
/* dark green page ("Лес" variant): body itself carries the fill so it covers
   the full viewport height, not just the .container column. */
body:has(.public) {
  min-height: 100vh;
  background: var(--accent);
}

/* here the content is the 1100px .container, not the wide dashboard — the
   header follows it instead of the shared .hdr-wrap width. Same for
   notfound, also a .container page. */
body:has(.public) .hdr-wrap,
body:has(.notfound) .hdr-wrap {
  max-width: 1100px;
  padding: 0 16px;
}

.public {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin-bottom: 20px;
  padding-bottom: 20px;
}

.public .page-title,
.public .grp {
  color: #eef4ee;
}

.public .card {
  background: #fbfdfa;
  border-color: transparent;
}

.row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  padding: 8px 0;
  border-bottom: 1px solid var(--band);
  font-size: 14px;
}

.card .row:last-child {
  border-bottom: 0;
}

.row.col {
  flex-direction: column;
  align-items: stretch;
  gap: 0;
}

.row.col .line {
  display: flex;
  justify-content: space-between;
  gap: 10px;
}

.bar {
  height: 7px;
  border-radius: 999px;
  background: var(--border);
  overflow: hidden;
  margin-top: 8px;
}

.bar i {
  display: block;
  height: 100%;
  background: var(--accent);
  border-radius: 999px;
}

.grp {
  font-size: 16px;
  margin: 4px 0 0;
}

.key {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  border: 1px solid var(--border);
  background: var(--bg);
  border-radius: 12px;
  padding: 9px 12px;
  margin-top: 6px;
  font: inherit;
  text-align: left;
}

/* copy affordance only where a copy button is actually present (self, as in
   the popup's done-step button, or a descendant, as in profile's key rows);
   public.html's key field has neither and stays default cursor. */
.key[data-copy],
.key:has([data-copy]) {
  cursor: pointer;
}

.key code {
  flex: 1;
  min-width: 0;
  font: 12px ui-monospace, Menlo, monospace;
  color: var(--accent);
  overflow-wrap: anywhere;
  word-break: break-all;
}

/* ---- funnel steps (branch A) ---- */
.funnel {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* same cascade issue as `.done-col[hidden]` above: author display:flex beats UA [hidden]. */
.funnel[hidden] {
  display: none;
}

.popup-note.small {
  font-size: 11px;
}

.errtx {
  font-size: 11px;
  color: var(--warn-tx);
}

.center {
  text-align: center;
}

/* login screen: Telegram / Почта as two labelled zones instead of a column
   of buttons (variant C of the login mockups). */
.zone {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  background: var(--card);
}

.zone-alt {
  background: var(--bg);
}

.zone-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
}

.zone-hint {
  font-size: 11px;
  color: var(--faint);
}

.divider {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--faint);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  font-weight: 700;
}

.divider::before,
.divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--border);
}

.btn-tg {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}

.tg-icon {
  flex: none;
}

/* merge screen: one card per colliding account + the honest loss list */
.merge-cards {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.merge-card {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 4px 12px 8px;
}

.merge-card-title {
  display: block;
  padding: 8px 0 2px;
  font-size: 13px;
}

.merge-card .row:last-child {
  border-bottom: 0;
}

.merge-losses {
  margin: 0;
  padding-left: 18px;
  font-size: 12px;
  color: var(--muted);
  line-height: 1.5;
}

form.center .btn {
  width: 100%;
}

.popup-card form > .btn {
  width: 100%;
}

/* the friend ladder: friends, the Unlimited days they give, what that leaves
   per month. The last rung (Unlimited навсегда) is the one worth pointing at. */
.ladder {
  list-style: none;
  margin: 0;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
}

.ladder li {
  display: flex;
  gap: 12px;
  align-items: baseline;
  padding: 9px 12px;
  font-size: 13px;
  border-top: 1px solid var(--border);
}

.ladder li:first-child {
  border-top: 0;
  background: var(--bg);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

.ladder li b {
  flex: 0 0 84px;
  font-weight: 650;
}

.ladder li i {
  flex: 0 0 130px;
  font-style: normal;
  font-weight: 650;
  color: var(--accent);
}

.ladder li span {
  flex: 1;
  color: var(--muted);
}

.ladder li:last-child {
  background: var(--soft);
}

.ladder li:last-child span {
  color: var(--accent);
  font-weight: 650;
}

.ladder li:first-child b,
.ladder li:first-child i {
  font-weight: 700;
  color: var(--muted);
}

/* email field */
.fld {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.lab {
  font-size: 10.5px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--faint);
}

.inp {
  border: 1px solid var(--border);
  background: var(--card);
  color: var(--accent);
  border-radius: var(--radius-sm);
  padding: 11px 13px;
  font: inherit;
  font-size: 13px;
}

.inp.err {
  border-color: var(--warn-tx);
}

/* the ladder's three fixed columns need 214px before the reward column starts;
   a phone row has ~240px in total, so there the reward takes its own line.
   16px on the field is what keeps iOS Safari from zooming the page on focus. */
@media (max-width: 560px) {
  .ladder li {
    flex-wrap: wrap;
  }
  .ladder li b {
    flex: 0 0 auto;
  }
  .ladder li i {
    flex: 1 1 auto;
  }
  .ladder li span {
    flex: 1 0 100%;
  }
  .inp {
    font-size: 16px;
  }
}

/* promo coupon capsule (branch C): dashed "tear-off" row, input + button in one
   field, solid accent border on focus. */
.coupon-row {
  display: flex;
  /* warm paper-ticket look (reuses the site's existing --gift-* warm tokens,
     the cool --band/--faint pair is for the rest of the UI) */
  border: 2px dashed var(--gold);
  border-radius: var(--radius);
  background: var(--gift-bg);
  overflow: hidden;
}

.coupon-row:focus-within {
  border-color: var(--accent);
  border-style: solid;
  background: var(--card);
}

.coupon-row input {
  flex: 1;
  min-width: 0;
  border: 0;
  outline: none;
  background: transparent;
  padding: 16px 14px;
  text-align: center;
  font: inherit;
  font-family: ui-monospace, Menlo, monospace;
  font-size: 18px;
  text-transform: uppercase;
  letter-spacing: 0.15em;
  color: var(--accent);
}

.coupon-row input::placeholder {
  color: var(--faint);
  letter-spacing: 0.1em;
  font-size: 15px;
}

.coupon-row button {
  border: 0;
  margin: 6px;
  border-radius: var(--radius-sm);
  background: var(--accent);
  color: var(--bg);
  font: inherit;
  font-size: 15px;
  padding: 0 18px;
  cursor: pointer;
  white-space: nowrap;
}

.coupon-row button[disabled] {
  opacity: 0.55;
  cursor: default;
}

/* err (red — the user's mistake) / info (neutral gray — nothing to fix) */
.coupon-row.err {
  border-color: var(--warn-tx);
  border-style: solid;
  background: var(--warn-bg);
}

.coupon-row.info {
  border-color: var(--faint);
  border-style: solid;
  background: var(--bg);
}

@media (max-width: 420px) {
  .coupon-row {
    flex-direction: column;
  }
  .coupon-row button {
    padding: 13px;
    margin: 0 6px 6px;
  }
}

.msg {
  margin: 0;
  text-align: center;
  font-size: 13px;
  line-height: 1.4;
}

.msg.err {
  color: var(--warn-tx);
}

.msg.info {
  color: var(--muted);
}

.msg a {
  color: inherit;
}

.tsub {
  font-size: 11px;
  color: var(--muted);
  margin-top: 6px;
}

/* code cells */
.cells {
  display: flex;
  gap: 6px;
  justify-content: center;
}

.cell {
  flex: 1 1 0;
  min-width: 0;
  max-width: 48px;
  height: 56px;
  border: 1px solid var(--border);
  background: var(--card);
  border-radius: 10px;
  text-align: center;
  font: inherit;
  font-weight: 750;
  font-size: 22px;
  color: var(--accent);
}

.cell:focus {
  border-color: var(--accent);
}

.cells.err .cell {
  border-color: var(--warn-tx);
}

.linkbtn {
  border: 0;
  background: none;
  font: inherit;
  font-size: 11px;
  color: var(--muted);
  text-align: center;
  cursor: pointer;
  padding: 14px 6px;
}

.linkbtn:disabled {
  cursor: default;
}

.linkbtn-about {
  align-self: center;
  font-size: 14px;
  color: var(--warn-tx);
  text-decoration: underline;
  text-decoration-thickness: 1.5px;
  text-underline-offset: 3px;
  padding: 11px 22px;
}

/* subtle keyboard focus: accent underline, no outline box (avoids sticky-looking
   highlight). */
.linkbtn-about:focus-visible {
  outline: none;
  color: var(--accent);
  text-decoration-color: var(--accent);
  text-decoration-thickness: 3px;
  text-underline-offset: 4px;
}

/* pay step */
.pay-qr {
  display: grid;
  place-items: center;
}

.qr-img {
  width: 100%;
  max-width: 200px;
  height: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--card);
  image-rendering: pixelated;
}

.live {
  display: flex;
  align-items: center;
  gap: 7px;
  justify-content: center;
  font-size: 12px;
  color: var(--muted);
}

.live .dot,
.sn-support-status .dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #1f7a55;
}

@media (prefers-reduced-motion: no-preference) {
  .live .dot {
    animation: pulse 1.8s ease-in-out infinite;
  }

  /* card swap (step transitions) runs a fade-through animation via WAAPI
     (web/static/popup.js swap()), not CSS transitions — nothing to declare
     here. Let the OTP cells slide in when the code screen appears. */
  .cells .cell {
    animation: cell-in 0.24s ease both;
  }
}

@keyframes pulse {
  50% {
    opacity: 0.2;
  }
}

@keyframes cell-in {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
}

/* done step: numbered guide row. Named .step (not .hdr) — .hdr is the page
   nav header (base.html) and shares no styling with this. */
.step {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  font-size: 13px;
}

.step .num {
  margin-top: 2px;
}

.step-install > div {
  min-width: 0;
}

.copy {
  margin-left: auto;
  flex: none;
  font-size: 11px;
  font-weight: 700;
  color: var(--accent);
  border: 1px solid #cfdcd6;
  border-radius: 999px;
  padding: 8px 16px;
  min-height: 44px;
  background: var(--soft);
  cursor: pointer;
}

.small {
  font-size: 10.5px;
}

/* done step: "usually Happ is enough" box above the tabs. */
.intro {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 11px 14px;
  font-size: 14px;
  line-height: 1.55;
  margin: 0;
  text-align: center;
}

.intro b {
  font-weight: 800;
}

/* Pill sub-tabs: Happ / Incy tab row (AmneziaVPN's awg tab commented out,
   sn-iccf; .panel below swaps per tab, popup.js) and the friends card's
   gib/days mode switch (real form submits, no client-side panel swap). */
.tabs {
  display: flex;
  gap: 8px;
}

.tabs button {
  flex: 1;
  font: inherit;
  font-size: 13.5px;
  font-weight: 700;
  padding: 12px 8px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--card);
  color: var(--muted);
  cursor: pointer;
  transition:
    background 0.2s ease,
    color 0.2s ease,
    border-color 0.2s ease;
}

.tabs button.on {
  background: var(--soft);
  color: var(--accent);
  border-color: transparent;
}

.done-col {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
  margin-top: 20px;
}

/* author `.done-col{display:flex}` above wins the cascade over the UA
   `[hidden]{display:none}` rule (same specificity, author origin beats UA) —
   without this, all three panels render stacked at once. */
.done-col[hidden] {
  display: none;
}

/* per-platform download buttons, wrapping row below the install step's text. */
.prow {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 4px;
  justify-content: center;
  margin-top: 8px;
}

.pbtn {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 8px 10px;
  font-size: 11.5px;
  font-weight: 700;
  border-radius: 11px;
  text-decoration: none;
  white-space: nowrap;
  transition: box-shadow 120ms ease;
}

.qr-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}

/* small uppercase label under a .qr-wrap's QR, e.g. "для приложения" /
   "для друга" — tells the two beige rows apart in the done step. */
.qr-cap {
  font-size: 9px;
  font-weight: 650;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--faint);
}

/* floating pill above the copied field — appended into its .key anchor by
   showCopyToast (app.js, popup.js), toggled visible via .show. */
.toast {
  position: absolute;
  left: 50%;
  bottom: 100%;
  margin-bottom: 6px;
  transform: translate(-50%, 4px);
  opacity: 0;
  pointer-events: none;
  white-space: nowrap;
  background: #141712;
  color: var(--bg);
  font-size: 11px;
  border-radius: 999px;
  padding: 6px 14px;
  transition: opacity 0.18s ease, transform 0.18s ease;
}

.toast.show {
  opacity: 1;
  transform: translate(-50%, 0);
}

/* ---- account pages (login, profile, faq, support) ---- */
.page,
.profile {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin-bottom: 20px;
}

/* profile is a near-fullscreen dashboard, not the 1100px .container the rest
   of the site uses — width shared with .hdr-wrap above, see there. */
.profile {
  margin: 24px auto 20px;
}

/* dark green page, same trick as body:has(.public) above: the fill lives on
   the body so it covers the viewport, not just the cards. Landing-hero
   gradient, so the dashboard reads as the same surface. Also the notfound
   page, same gradient. */
body:has(.profile),
body:has(.notfound) {
  min-height: 100vh;
  background: linear-gradient(180deg, var(--accent), var(--accent-end));
}

/* the only profile text outside a card — --warn-tx is unreadable on green */
.profile > .errtx {
  color: #f0bcac;
}

/* wraps the profile cards so the .profile gap keeps working with one extra
   level of nesting (needed to dim them as a unit below) */
.profile-cards {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

/* no live subscription: the cards stay visible but inert, under the gate popup.
   inert (template attr, see profile.html) handles focus/mouse/screen-reader;
   this is just the visual dim. */
.profile-dimmed {
  opacity: 0.4;
}

/* card contents stack like a popup body */
.stack {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.cardh {
  margin: 0;
  font-size: 15px;
  letter-spacing: -0.01em;
}

/* ---- account dashboard (profile): a 3-column grid of .col wrappers, each
   holding one card (account, subscription, traffic, connection, devices,
   friends); every card is a plain .card except the glass .card.acct. ---- */
.profile-grid {
  display: grid;
  /* minmax(0,…) — a bare 1fr floors at the column's min-content, and the cards
     (nowrap device rows, tab row) blow past a phone viewport, widening the
     whole document. */
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
  align-items: start;
}

@media (max-width: 1280px) {
  .profile-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 900px) {
  .profile-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  /* dissolve the .col wrappers so their cards join the single stack directly
     and can be reordered individually: Аккаунт, Подписка, Трафик,
     Подключение, Устройства, Друзья (not source/column order). */
  .profile-grid .col {
    display: contents;
  }

  .card.acct {
    order: 1;
  }
  .card.sub {
    order: 2;
  }
  .card.traffic-card {
    order: 3;
  }
  .card.conn-card {
    order: 4;
  }
  .card.devices-card {
    order: 5;
  }
  .card.friends-card {
    order: 6;
  }
}

/* column wrapper: keeps cards inside a column flush against each other
   instead of leaving a void under a short card until the next grid row */
.profile-grid .col {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

/* generic card header row: title + a trailing count/action, no divider
   (unlike .row, which underlines each data line within a card) */
.hd {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
}

/* profile's own cards stack their contents like a popup body — scoped to
   these modifiers, not .card in general (landing/funnel cards keep their own
   padding-only layout). */
.card.acct,
.card.sub,
.card.traffic-card,
.card.friends-card,
.card.conn-card,
.card.devices-card {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.dim {
  color: var(--muted);
  font-size: 13px;
}

/* account card: identity hero + the "Удалить аккаунт" link. Glass like the
   header — a green plate would sink into the green page. Also the notfound
   card, same green page, same glass. */
.card.acct,
.notfound .card {
  background: rgba(255, 255, 255, 0.06);
  border-color: rgba(255, 255, 255, 0.12);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  color: #eef4ee;
}

.card.acct a,
.card.acct .linkbtn {
  color: #b7dcc4;
}

/* lighter than the plate's #9ab5a8 was — the glass ground is brighter */
.card.acct .dim {
  color: #cadbd2;
}

.card.acct .danger-quiet {
  color: var(--warn-tx-lite);
}

.idrows {
  display: flex;
  flex-direction: column;
}
.idrow {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 2px;
}
.idrows > * + * {
  border-top: 1px solid rgba(255, 255, 255, 0.1);
}
.idrow .val,
.idcta-txt .val {
  flex: 1;
  min-width: 0;
  overflow-wrap: anywhere;
  font-weight: 650;
  font-size: 14.5px;
}
.idrow .ico {
  width: 34px;
  height: 34px;
  flex: none;
  border-radius: 9px;
  background: rgba(255, 255, 255, 0.1);
  display: grid;
  place-items: center;
  color: #cfe6d8;
}
.idrow .ico svg {
  width: 18px;
  height: 18px;
  display: block;
}

/* ads-block toggle row (subscription card): label text left, switch right,
   description line sits below as a sibling .dim, border/padding from .row.col */
.settings-toggle {
  display: flex;
  flex-direction: row-reverse;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  cursor: pointer;
}
/* appearance:none keeps submit/focus native */
.settings-toggle input[type="checkbox"] {
  -webkit-appearance: none;
  appearance: none;
  flex: none;
  margin: 0;
  position: relative;
  width: 40px;
  height: 24px;
  border-radius: 999px;
  background: var(--muted);
  cursor: pointer;
  transition: background-color 0.15s ease;
}
.settings-toggle input[type="checkbox"]::after {
  content: "";
  position: absolute;
  top: 3px;
  left: 3px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
  transition: left 0.15s ease;
}
.settings-toggle input[type="checkbox"]:checked {
  background: var(--accent);
}
.settings-toggle input[type="checkbox"]:checked::after {
  left: 19px;
}
@media (prefers-reduced-motion: reduce) {
  .settings-toggle input[type="checkbox"],
  .settings-toggle input[type="checkbox"]::after {
    transition: none;
  }
}
.idbtn {
  flex: none;
  margin-left: auto;
  font: inherit;
  font-size: 12.5px;
  color: #eaf4ee;
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.22);
  border-radius: 10px;
  padding: 7px 14px;
  cursor: pointer;
  white-space: nowrap;
}
.idbtn:hover {
  background: rgba(255, 255, 255, 0.16);
}
.idbtn.ghost {
  color: #bfe0cd;
  background: transparent;
  border-color: rgba(255, 255, 255, 0.18);
}
.idbtn:focus-visible {
  outline: 2px solid #cfe6d8;
  outline-offset: 2px;
}

/* the unfilled login method: same visual weight as the .p-btns primary
   action (reused below), not a plain row, so a missing second method reads
   as a call to action instead of blending in. */
.idcta {
  padding: 11px 2px;
}
.idcta-txt {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

/* "Unlimited на паузе" plaque: the frozen-remainder note, split out of the
   plain .dim row so the resume action reads as its own unit, not a line
   buried among the card's other rows. */
.pause-plate {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  text-align: center;
  padding: 14px;
  background: var(--band);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}

/* the resume button reads as the plaque's primary action, not the outlined
   secondary look .btn-w carries in the row below */
.pause-plate .btn-w {
  width: 100%;
  background: var(--accent);
  color: var(--bg);
  border: 0;
  box-shadow: none;
}

/* subscription card actions */
.p-btns {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.p-btns-row {
  display: flex;
  gap: 8px;
}

/* the "Продлить"/"Промокод" buttons sit inside a <form> child of .p-btns /
   .p-btns-row (needed to POST); display:contents drops the form from layout
   so the button itself takes the flex slot instead of shrink-wrapping. */
.p-btns > form,
.p-btns-row > form {
  display: contents;
}

.p-btns-row > *,
.p-btns-row > form > .btn {
  flex: 1;
}

.p-btns > form > .btn {
  width: 100%;
}

/* unlimited traffic: one big number, no meter */
.traffic-big {
  font-size: 22px;
  font-weight: 700;
}

/* friends card empty-state teaser: the card's lead line, ordinary body size
   (.row's 14px) in accent ink, not the muted .dim footnote size */
.card.friends-card .teaser {
  font-size: 14px;
}

.tmeter {
  position: relative;
  display: flex;
  height: 8px;
  border-radius: 999px;
  overflow: hidden;
  background: var(--band);
}

.tmeter-base {
  background: var(--band);
  flex: none;
}

.tmeter-gift {
  background: var(--gold);
  flex: none;
}

.tmeter-used {
  position: absolute;
  left: 0;
  top: 0;
  height: 100%;
  background: var(--accent);
  border-radius: 999px;
}

.tlegend {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 12px;
  font-size: 11px;
  color: var(--muted);
}

.tlegend span {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}

.tdot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex: none;
}

.tdot.used {
  background: var(--accent);
}

.tdot.base {
  background: var(--band);
}

.tdot.gift {
  background: var(--gold);
}

/* heading row above a key block: bold title + muted trailing note, laid out
   flex space-between (title left, note right), e.g. "Подключение" / "ключ
   для приложения". Used by profile.html's friends card (the popup done step
   has its own .zone-bar now). */
.key-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 8px;
}

.key-head strong {
  font-size: 13.5px;
}

/* tinted panel around the referral key, so it reads as a distinct "invite a
   friend" block: profile.html's friends card wraps ref_key in it (the popup
   done step has its own .zone-ref panel now). ref_key.html itself stays bare. */
.ref-panel {
  display: flex;
  flex-direction: column;
  gap: 8px;
  background: var(--soft);
  border: 1px solid var(--done);
  border-radius: var(--radius);
  padding: 12px;
}

.ref-panel .friends-key {
  margin-top: 0;
  background: var(--card);
  border-color: var(--done);
}

/* done-step panels: connect zone + referral zone, each a bordered card with a
   full-width colored header bar. Scoped to .zone-connect/.zone-ref (not a bare
   .zone) — that class name is already taken by the login screen's Telegram/
   Почта zones above, which have their own unrelated look. */
.zone-connect,
.zone-ref {
  display: flex;
  flex-direction: column;
  border: 1px solid;
  border-radius: var(--radius);
  overflow: hidden;
}
.zone-bar {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 8px;
  padding: 9px 12px;
  font-size: 13px;
  font-weight: 700;
}
.zone-bar .dim {
  font-size: 11.5px;
}
.zone-body {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px;
}
.zone-connect {
  border-color: var(--done);
  background: var(--card);
}
.zone-connect > .zone-bar {
  background: var(--done);
}
.zone-connect .friends-key {
  margin-top: 0;
  background: var(--bg);
  border-color: var(--done);
}
.zone-ref {
  border-color: var(--gift-line);
  background: var(--gift-bg);
}
.zone-ref > .zone-bar {
  background: var(--gift-bar);
}
.zone-ref .friends-key {
  margin-top: 0;
  background: var(--card);
  border-color: var(--gift-line);
}

/* success hero above the done-step zones: check tick + title + short sub. */
.done-hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}
.done-hero .tick {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--soft);
  color: var(--ok);
  display: grid;
  place-items: center;
}
.done-hero .sub {
  margin: 0;
  font-size: 12.5px;
  color: var(--muted);
}

/* referral / connect-tabs link row: field + compact QR side by side inside
   the same bordered .key field, one row at every width. Shared by
   profile.html's friends row and connect_tabs.html's done-step url row. */
.friends-key .qr-wrap {
  flex: none;
}

.friends-key .qr-img {
  width: 96px;
  height: 96px;
  max-width: none;
}

/* awg's ~890-char vpn:// payload is QR version 21 (101 modules, 109 with
   quiet zone); at the shared 96px .friends-key sizing (same as referral's)
   that's under 1px/module — the resting QR is not scannable, only legible.
   Reading it needs the zoom .qr-zoom below provides.
   ponytail: deliberate — on a phone the connect flow uses the copy-link
   path instead, so a phone never needs to scan its own screen; the QR here
   is for reading at a distance from a desktop screen. revisit-after: never
   Two render paths, two different growth constraints:
   - popup (partials/popup.html + popup.js doneScreen): .zone-connect wraps
     .friends-key with overflow:hidden, so growth must stay inside that box.
     Desktop grows the QR leftward+upward only (transform-origin: right
     bottom) — room above is ample, below only ~40px. Leftward room before
     .zone-connect's own edge clips: ~464px in the 561px-wide popup.
   - profile (.card.conn-card, templates/profile.html): no .zone-connect,
     no clipping ancestor around .friends-key at all — growth is bounded
     only by the grid column width, ~353px at the 1281px breakpoint (3
     columns).
   The profile path is tighter (353px vs popup's 464px), so it's what
   --qr-scale has to fit inside: 353 / 96 = 3.68x before the column edge;
   3 leaves margin. */
.qr-zoom {
  position: relative;
  --qr-scale: 3;
}

.qr-zoom summary {
  list-style: none;
  cursor: zoom-in;
}

.qr-zoom summary::-webkit-details-marker {
  display: none;
}

.qr-zoom summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* bounce and zoom both animate transform, so they're split onto two
   elements (.qr-bounce wraps .qr-img inside <summary>) — same element would
   mean open/close fighting the infinite bounce. Both share the img's
   transform-origin so the split doesn't shift where either pivots.
   inline-block: transform is a no-op on non-replaced inline boxes, and a
   bare span is inline by default. */
.qr-zoom .qr-bounce {
  display: inline-block;
}

.qr-zoom .qr-img,
.qr-zoom .qr-bounce {
  transform-origin: right bottom;
}

@media (prefers-reduced-motion: no-preference) {
  .qr-zoom:not([open]) .qr-bounce {
    animation: qr-bounce 1.6s infinite;
  }

  /* plain transition, not a dedicated keyframe animation: with bounce moved
     off this element there's nothing left for it to fight, so a transition
     covers open AND close symmetrically — outside-click/Escape just flip
     [open] and get the same animation for free. Overshoot comes from the
     easing curve instead of a mid-keyframe, tuned to match the old qr-pop
     feel. */
  .qr-zoom .qr-img {
    transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1), filter 0.3s ease-out;
  }
}

@keyframes qr-bounce {
  0% { transform: translateY(0) scale(1, 1); animation-timing-function: ease-out; }
  8% { transform: translateY(-2px) scale(0.96, 1.05); }
  30% { transform: translateY(-12px) scale(1, 1); animation-timing-function: ease-in; }
  54% { transform: translateY(0) scale(1.06, 0.94); }
  62% { transform: translateY(0) scale(1, 1); animation-timing-function: ease-out; }
  72% { transform: translateY(-4px) scale(1, 1); animation-timing-function: ease-in; }
  80% { transform: translateY(0) scale(1.03, 0.97); }
  86%, 100% { transform: translateY(0) scale(1, 1); }
}

.qr-zoom[open] {
  z-index: 5;
}

.qr-zoom[open] .qr-img {
  transform: scale(var(--qr-scale));
  filter: drop-shadow(0 12px 24px rgba(23, 21, 18, 0.35));
}

.qr-zoom[open] summary {
  cursor: zoom-out;
}

@media (max-width: 560px) {
  /* origin: right center splits vertical growth up/down evenly; growth must
     stay inside the popup's .zone-connect overflow: hidden box, which is
     tighter than the profile path, so the scale is capped at 1.7x. */
  .qr-zoom .qr-img,
  .qr-zoom .qr-bounce {
    transform-origin: right center;
  }

  .qr-zoom {
    --qr-scale: 1.7;
  }
}

.key.copied {
  border-color: var(--ok);
}

.key.copied .copy {
  color: var(--ok);
  border-color: var(--ok);
}

/* the key row's icon-square copy button (referral link, connection key) */
.key .copy {
  position: relative;
  margin-left: 0;
  min-height: 0;
  border: 1px solid var(--border);
  background: #fff;
  color: var(--accent);
  border-radius: 10px;
  padding: 7px;
  display: grid;
  place-items: center;
}

.key .copy::after {
  content: '';
  position: absolute;
  inset: -6px;
}

/* referral progress bar: exactly ten notches (the path to the friend that
   unlocks Unlimited forever), joined by thin connectors; state is
   server-driven straight from the template, no client JS fill loop. */
.notches {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0;
  min-width: 0;
}

/* every state renders as a same-size (22px) circle except the free slot,
   a bare 12px dot */
.notch {
  position: relative;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--faint);
  flex: none;
}

.notch.active,
.notch.inactive,
.notch.invited {
  width: 22px;
  height: 22px;
}

/* active friend: solid gold disc */
.notch.active {
  border: 2px solid var(--gold);
  background: var(--gold);
}

/* a friend who went inactive: dim muted ring, no fill */
.notch.inactive {
  border: 2px solid var(--gold-muted);
  background: #fff;
  opacity: 0.55;
}

/* invited, not connected yet: dashed muted ring, no fill */
.notch.invited {
  border: 2px dashed var(--gold-muted);
  background: #fff;
}

.link-seg {
  flex: 1 1 4px;
  min-width: 2px;
  height: 2px;
  background: var(--line);
}

.link-seg.seg-gold {
  background: var(--gold);
}

/* closes the friends bar: tappable emoji, no border/background, opens the
   terms dialog — always full colour, appearance no longer carries state */
.notch.gift {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  padding: 0;
  border: none;
  background: none;
  font-size: 26px;
  line-height: 1;
  filter: drop-shadow(0 1px 2px rgba(138, 90, 0, 0.28));
  animation: gift-wiggle 5s ease-in-out infinite;
  cursor: pointer;
}

@keyframes gift-wiggle {
  0%,
  82%,
  100% {
    transform: rotate(0deg);
  }
  86% {
    transform: rotate(-9deg);
  }
  90% {
    transform: rotate(7deg);
  }
  94% {
    transform: rotate(-4deg);
  }
}

@media (prefers-reduced-motion: reduce) {
  .notch.gift {
    animation: none;
  }
}

@media (max-width: 820px) {
  .key {
    flex-wrap: wrap;
  }
  .key:not(.friends-key) code {
    flex: 1 1 100%;
  }
}

/* phone: the referral/connect row keeps its link beside the 96px QR down to
   ~110px of monospace — there the link takes the whole first line as well. */
@media (max-width: 560px) {
  .key.friends-key code {
    flex: 1 1 100%;
  }
}

.inlineform {
  display: inline;
}

.inlineform .linkbtn {
  padding: 0;
  text-decoration: underline;
}

/* device rows: rich card row that opens the device popup */
.devlist {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.devrow {
  display: flex;
  align-items: center;
  gap: 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--card);
  color: var(--accent);
  text-decoration: none;
  padding: 12px 14px;
  width: 100%;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.devrow:hover {
  border-color: var(--accent);
}

.dev-sprite {
  display: none;
}

.dev-ic {
  width: 38px;
  height: 38px;
  border-radius: 10px;
  background: var(--soft);
  display: grid;
  place-items: center;
  flex: none;
}

.dev-ic-svg {
  width: 20px;
  height: 20px;
  color: var(--muted);
}

.dev-mid {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.dev-name {
  font-weight: 650;
  font-size: 14px;
  display: flex;
  align-items: center;
  gap: 8px;
}

.dev-nm {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.dev-meta {
  font-size: 12px;
  color: var(--muted);
}

.popup-note code,
.dev-hwid {
  font: 11px ui-monospace, Menlo, monospace;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 1px 5px;
  white-space: nowrap;
  flex: none;
}

.dev-seen {
  flex: none;
  text-align: right;
  font-size: 12px;
  white-space: nowrap;
}

.danger {
  color: var(--warn-tx);
}

.danger-solid {
  background: var(--warn-tx);
  color: #fff;
}

/* quiet "Удалить аккаунт" link, small and underlined in a card header. */
.danger-quiet {
  font-size: 12.5px;
  color: var(--warn-tx);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.howto p {
  margin: 0;
  font-size: 13px;
  color: var(--muted);
}

.howto .step {
  padding: 3px 0;
}

/* ---- not found ---- */
/* body-fill and glass card are shared with public/profile above, see there. */
.notfound {
  margin: 60px auto;
}

.notfound .card .muted {
  color: rgba(255, 255, 255, 0.72);
}

/* ---- support chat widget ---- */
#sn-fabs {
  position: fixed;
  right: 22px;
  bottom: 22px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  z-index: 900;
}

#sn-support-fab,
#sn-bot-fab {
  width: 58px;
  height: 58px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: 0 8px 24px rgba(23, 21, 18, 0.32);
  text-decoration: none;
}

#sn-support-fab {
  position: relative;
}

#sn-support-fab img {
  width: 100%;
  height: 100%;
  display: block;
  border-radius: 50%;
}

#sn-support-fab[hidden] {
  display: none;
}

.sn-support-badge {
  position: absolute;
  top: -2px;
  right: -2px;
  min-width: 20px;
  height: 20px;
  padding: 0 5px;
  border-radius: 10px;
  background: #e5484d;
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  line-height: 20px;
  text-align: center;
}

.sn-support-badge[hidden] {
  display: none;
}

#sn-support-panel {
  position: fixed;
  right: 22px;
  bottom: 22px;
  width: 420px;
  max-width: calc(100% - 32px);
  max-height: calc(100vh - 44px);
  display: flex;
  flex-direction: column;
  background: var(--card);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: 0 18px 48px rgba(23, 21, 18, 0.34);
  z-index: 950;
}

#sn-support-panel[hidden] {
  display: none;
}

/* JS (app.js fitWidth) sets an inline width from the longest message; ease the
   step so the panel grows instead of jumping. */
@media (prefers-reduced-motion: no-preference) {
  #sn-support-panel {
    transition: width 0.18s ease;
  }
}

/* phone: the hwid chip costs the device name half its width; it is still in
   the device popup. */
@media (max-width: 560px) {
  .dev-name .dev-hwid {
    display: none;
  }
}

.sn-support-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px;
  background: var(--accent);
  color: #fff;
}

.sn-support-avatar {
  width: 38px;
  height: 38px;
  border-radius: var(--radius-sm);
  flex: none;
}

.sn-support-id {
  display: flex;
  flex-direction: column;
  line-height: 1.25;
  margin-right: auto;
}

.sn-support-id strong {
  font-size: 15px;
}

.sn-support-status {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  opacity: 0.85;
}

#sn-support-close {
  border: none;
  background: transparent;
  color: #fff;
  cursor: pointer;
  padding: 4px;
  display: flex;
  border-radius: 8px;
  flex: none;
}

#sn-support-log {
  flex: 1;
  min-height: 260px;
  max-height: min(72vh, 580px);
  overflow-y: auto;
  background: var(--band);
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.sn-b {
  max-width: 82%;
  padding: 10px 13px;
  font-size: 14px;
  line-height: 1.4;
  overflow-wrap: anywhere;
}

.sn-b-bot {
  align-self: flex-start;
  background: var(--card);
  color: var(--accent);
  border-radius: 14px 14px 14px 4px;
}

.sn-b-user {
  align-self: flex-end;
  background: var(--accent);
  color: #fff;
  border-radius: 14px 14px 4px 14px;
}

/* markdown inside bubbles (marked + DOMPurify, see addBubble in app.js).
   Colours are inherited so both variants — .sn-b-bot on card, .sn-b-user on
   accent — stay readable without a second palette. */
.sn-b > :first-child {
  margin-top: 0;
}

.sn-b > :last-child {
  margin-bottom: 0;
}

.sn-b p {
  margin: 0 0 8px;
}

.sn-b h3,
.sn-b h4 {
  margin: 10px 0 6px;
  font-size: 15px;
  line-height: 1.3;
}

.sn-b ul,
.sn-b ol {
  margin: 0 0 8px;
  padding-left: 20px;
}

.sn-b li {
  margin: 2px 0;
}

.sn-b blockquote {
  margin: 0 0 8px;
  padding-left: 10px;
  border-left: 2px solid currentColor;
  opacity: 0.75;
}

.sn-b code,
.sn-b pre {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  background: rgba(23, 21, 18, 0.07);
}

.sn-b code {
  font-size: 0.92em;
  padding: 1px 4px;
  border-radius: 5px;
}

.sn-b pre {
  margin: 0 0 8px;
  padding: 9px 11px;
  border-radius: 8px;
  overflow-x: auto;
}

.sn-b pre code {
  padding: 0;
  background: none;
}

/* accent bubble: a dark tint would read as a hole, lighten instead */
.sn-b-user code,
.sn-b-user pre {
  background: rgba(255, 255, 255, 0.18);
}

.sn-b a {
  color: inherit;
  text-decoration: underline;
}

.sn-b-time {
  display: block;
  margin-top: 4px;
  font-size: 11px;
  opacity: 0.65;
}

/* attachment inside a bubble: a download row, never a preview (see fileLink in
   app.js and the download headers in internal/server/support.go) */
.sn-b-file {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-top: 6px;
  padding: 7px 10px;
  border: 1px solid currentColor;
  border-radius: 10px;
  color: inherit;
  text-decoration: none;
}

.sn-b-file-name {
  overflow-wrap: anywhere;
}

.sn-b-file-meta {
  margin-left: auto;
  flex: none;
  font-size: 11px;
  opacity: 0.7;
}

#sn-support-form {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px;
  border-top: 1px solid var(--border);
  background: var(--card);
}

.sn-support-row {
  display: flex;
  align-items: flex-end;
  gap: 8px;
}

/* files chosen but not sent yet, listed above the input */
#sn-support-files {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

/* the author `display:flex` above beats the UA `[hidden]{display:none}` rule
   (same specificity, author origin wins) — without this the empty strip keeps
   taking a row of the form, same pattern as `.done-col[hidden]` above */
#sn-support-files[hidden] {
  display: none;
}

.sn-support-file {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  font-size: 13px;
  color: var(--accent);
  background: var(--band);
  border-radius: var(--radius-sm);
}

.sn-support-file-name {
  overflow-wrap: anywhere;
}

.sn-support-file-size {
  margin-left: auto;
  flex: none;
  font-size: 11px;
  opacity: 0.7;
}

.sn-support-file-del {
  flex: none;
  width: 22px;
  height: 22px;
  padding: 0;
  font-size: 16px;
  line-height: 1;
  color: inherit;
  background: none;
  border: none;
  border-radius: 6px;
  cursor: pointer;
}

#sn-support-error {
  margin: 0;
  font-size: 13px;
  color: var(--warn-tx);
}

#sn-support-input {
  flex: 1;
  padding: 11px 13px;
  font-size: 15px;
  font-family: inherit;
  line-height: 1.4;
  color: var(--accent);
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  resize: none;
  overflow-y: hidden; /* JS autoGrow flips to auto past the 10-line cap */
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

#sn-support-input::placeholder {
  color: var(--muted);
  opacity: 0.85;
}

/* send + attach: same 44px square; the attach one stays quiet, it is the
   secondary action of the row */
#sn-support-form button[type="submit"],
#sn-support-attach {
  width: 44px;
  height: 44px;
  flex: none;
  border: none;
  border-radius: var(--radius-sm);
  background: var(--accent);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

#sn-support-attach {
  background: var(--band);
  color: var(--accent);
}

/* phone: chat takes the whole screen, like a normal messenger */
@media (max-width: 560px) {
  #sn-support-panel {
    inset: 0;
    width: auto;
    max-width: none;
    height: 100vh;
    height: 100dvh;
    max-height: none;
    border-radius: 0;
  }

  #sn-support-log {
    min-height: 0;
    max-height: none;
  }

  /* 16px keeps iOS Safari from zooming the page on focus */
  #sn-support-input {
    font-size: 16px;
  }
}
