/* Landing page styles for the Socials (5000) app — matches the 8000 look. */

.site-header {
  position: sticky; top: 0; z-index: 100;
  background: rgba(255,255,255,.85); backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--border);
}
.site-header .container {
  display: flex; align-items: center; justify-content: space-between; height: 68px;
}
.brand { display: flex; align-items: center; gap: 10px; font-weight: 800; font-size: 20px; color: var(--text); text-decoration: none; }
.brand .brand-mark {
  width: 38px; height: 38px; border-radius: 11px;
  background: linear-gradient(135deg, var(--brand-500), var(--accent-500));
  display: flex; align-items: center; justify-content: center; color: #fff; font-size: 20px;
}
/* Slogan under the wordmark. Stacked in a column so it reads as part of the
   lockup, and small/letter-spaced so it never competes with the page h1. */
.brand .brand-text { display: flex; flex-direction: column; line-height: 1.05; }
.brand .brand-slogan {
  font-size: 10.5px; font-weight: 600; letter-spacing: .09em;
  text-transform: uppercase; color: var(--brand-600); margin-top: 2px;
}
[dir="rtl"] .brand .brand-slogan { letter-spacing: 0; }
.nav-links { display: flex; align-items: center; gap: 28px; }
.nav-links a { color: var(--text-2); font-weight: 500; font-size: 15px; text-decoration: none; }
.nav-links a:hover { color: var(--brand-600); }

.hero { padding: 96px 0 calc(80px + var(--hero-glint)); text-align: center; position: relative;
  isolation: isolate; overflow: hidden;
  /* The strip the skyline's reflection sits in. Used for BOTH the reflection's
     height and the skyline's lift, so the mirror can never overlap the artwork
     or run out of room. */
  --hero-glint: clamp(56px, 6vw, 104px);
  background:
    radial-gradient(900px 500px at 80% -10%, rgba(99,102,241,.14), transparent 60%),
    radial-gradient(700px 400px at 10% 10%, rgba(34,211,238,.12), transparent 55%), #fff;
}
/*
  Hero art — two decorative layers, both the designer's SVGs and both UNDER the
  copy: `.hero .container` is raised to z-index 1 and neither layer takes pointer
  events, so no line of text can ever be covered or made unclickable.

  Landscape (the skyline): shown at its NATURAL aspect ratio (`width: 100%`,
  `height: auto`) so the whole artwork is on screen, tower tops included. An
  earlier version cover-cropped it into a fixed-height band, which silently
  sliced off everything above the crop — including the tallest tower, which
  reaches the very top edge of the artwork. The only fade left is HORIZONTAL
  (the two ends dissolve into the page); a top fade cannot be used at all, since
  the tall tower touches the artwork's top edge and any vertical ramp erases it.

  Hands (the raised fists): pinned to the bottom RIGHT and pushed a little past
  the edge, so the arms are cut off by the section and the fists "peak" up into
  the hero. Drawn after the landscape so they paint in front of the skyline.
*/
.hero-landscape {
  position: absolute; left: 0; right: 0; bottom: var(--hero-glint); z-index: 0;
  width: 100%; height: auto; max-height: 100%; object-fit: cover;
  object-position: center bottom;
  opacity: .6; pointer-events: none;
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 9%, #000 91%, transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0, #000 9%, #000 91%, transparent 100%);
}
/* Very minimal mirror of the skyline directly under its base: the same artwork
   flipped vertically (`scaleY(-1)`, default origin, so the artwork's BOTTOM edge
   becomes the top of the box and meets the skyline's ground line) and clipped to
   the reserved strip. It fades downward AND sideways like the skyline, and stays
   faint — it is a grounding touch, not a second skyline. `loading="lazy"` because
   it is pure decoration; the URL is shared with the skyline, so it is cached. */
.hero-reflection {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 0;
  height: var(--hero-glint); overflow: hidden; pointer-events: none;
  opacity: .16;
  -webkit-mask-image: linear-gradient(to bottom, #000 0 12%, transparent 92%);
  mask-image: linear-gradient(to bottom, #000 0 12%, transparent 92%);
}
.hero-reflection img {
  position: absolute; left: 0; top: 0; width: 100%; height: auto;
  transform: scaleY(-1);
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 9%, #000 91%, transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0, #000 9%, #000 91%, transparent 100%);
}
.hero-hands {
  position: absolute; right: clamp(8px, 4vw, 64px); bottom: -34px; z-index: 0;
  width: auto; height: clamp(170px, 26vh, 300px);
  pointer-events: none;
}
/* Soft white veil behind the copy, above the artwork: strongest where the text
   sits, invisible at the edges so the skyline and the fists keep their colour.
   This is what lets the skyline reach up behind the headline without costing
   legibility. */
.hero-veil {
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: radial-gradient(56% 44% at 50% 44%,
                              rgba(255, 255, 255, .95) 0%,
                              rgba(255, 255, 255, .8) 45%,
                              rgba(255, 255, 255, 0) 100%);
}
.hero .container { max-width: 1000px; margin: 0 auto; padding: 0 24px; position: relative; z-index: 1;
  display: flex; flex-direction: column; align-items: center; gap: 24px; }
.eyebrow { display: inline-flex; align-items: center; gap: 8px; padding: 7px 16px; border-radius: var(--r-pill); background: var(--brand-50); color: var(--brand-600); font-size: 13.5px; font-weight: 600; }
/* Brand mark above the headline. Sized by height (the PNG is 786x227) so the
   aspect ratio is preserved without a wrapper, and capped on phones so it can
   never crowd out the headline. */
.hero-logo { display: block; height: 52px; width: auto; margin: 0 auto; }
/* Headline is a full sentence now ("Iran's social media command center — hosted
   in Iran, built for Persian platforms"), not a two-word slogan. The old
   clamp(38px, 6vw, 60px) was sized for the short line and made it wrap to EIGHT
   lines at 375px; the floor is the thing to watch, since 6vw is below 38px on
   phones so the floor always won. 27px floor = 4 comfortable lines at 375px and
   320px, and the 52px ceiling with the wider container = 2 lines on desktop. */
.hero h1 { font-size: clamp(27px, 5.2vw, 52px); letter-spacing: -0.02em; margin: 0; }
/* Two headline lines, each at its natural width. `hero.title1` / `hero.title2`
   are the line breaks; wrapping them in block spans is what keeps the h1's TEXT
   a single readable sentence for search snippets and screen readers. */
.hero-title { display: flex; flex-direction: column; align-items: center; }
.hero-title .h1-line { display: block; text-wrap: balance; }
/* The headline is ONE sentence now, so it can be bigger again; the subheadline
   carries the second sentence ("Hosted in Iran." / "Built for Persian
   platforms.") on its own lines. The gradient lives on the last line, which is
   what keeps the hero recognisably branded. */
.hero-sub { margin: 0; font-size: clamp(17px, 2.3vw, 23px); font-weight: 700;
  line-height: 1.45; color: var(--brand-600); letter-spacing: -0.01em; }
/* The middle line is the DETAIL (what the studio actually does), not the claim: the
   first line says what the product IS and the last line carries the brand gradient,
   so this one steps down one size and uses slate ink instead of indigo. Three lines at
   full weight and brand colour read as a wall and bury the headline above them. The
   white veil behind the hero copy (.hero-veil) is what makes --text-2 safe here. */
.hero-sub-body { display: inline-block; font-size: .84em; font-weight: 600;
  line-height: 1.5; color: var(--text-2); }
.hero .grad { background: linear-gradient(120deg, var(--brand-600), var(--accent-500)); -webkit-background-clip: text; background-clip: text; color: transparent; }
/* Reassurance under the buttons ("no credit card required · setup in 2 minutes"):
   the two facts that decide the click. Muted, but NOT --text-3: that grey vanished
   into the skyline artwork behind it, so it gets --text-2 on a soft white pill —
   still quieter than the buttons above, and legible over whatever edges past the
   veil there. */
.hero-note {
  margin: 0; font-size: 14.5px; font-weight: 600; color: var(--text-2);
  background: rgba(255, 255, 255, .94); border-radius: var(--r-pill);
  padding: 5px 14px;
}
/* The slogan as a display line under the h1 — brand voice, deliberately NOT
   inside the h1 so the heading stays keyword-dense for search. Stepped down one
   size so it reads as a tagline under the subheadline instead of competing with
   it (both are brand indigo, so size is what separates them). */
.hero-slogan {
  margin: 0; font-size: clamp(15px, 1.7vw, 18px); font-weight: 700;
  letter-spacing: .01em; color: var(--brand-600);
}
.hero-slogan::before, .hero-slogan::after { content: "—"; opacity: .45; margin: 0 10px; }
/* Iran-hosting / data-ownership reassurance, directly under the CTAs where the
   sign-up decision is actually made. */
.trust-line {
  margin: 4px 0 0; font-size: 14px; color: var(--text-2);
  display: inline-flex; align-items: center; gap: 7px; flex-wrap: wrap;
  justify-content: center; max-width: 640px;
}
/* Iran-hosting badge. Promoted from a line under the CTAs to a pill directly
   beneath the hero headline (the .eyebrow pill's own styling, one step stronger):
   for this audience the data-ownership promise is what decides the signup, so it
   sits above the buttons instead of below them. */
.hero-badge {
  margin: 0; padding: 10px 18px; border-radius: var(--r-pill);
  background: var(--brand-50); border: 1px solid var(--brand-100);
  color: var(--brand-700); font-size: 14.5px; font-weight: 600;
  display: inline-flex; align-items: center; gap: 9px; max-width: 660px;
  text-align: center; line-height: 1.55;
}
/* The flag that opens the badge. Sized in `em` so it tracks the badge's own font
   size — including the phone rule that shrinks the badge to 13.5px — which is
   what keeps it inside the pill's padding instead of overflowing the rounded
   edge. The other motifs are tinted (images/iran/brand/); the flag is not: a
   recoloured national flag is a different flag. */
.hero-badge .badge-flag { height: 1.75em; width: auto; flex: none; }
/* ---------------------------------------------------------------- For Studios
   The compact teaser for the Photographers Dashboard. Its whole job is to be
   NOTICED by the one visitor in twenty who is a photographer, and then get out
   of the way — so it is a single clickable band rather than a section with its
   own sub-navigation, and it is deliberately the only block on this page with a
   warm neutral background.

   Height target is 180–220 px on desktop. That is why the padding is 26px and
   not the section's usual 84px: the copy is three short lines, and any more air
   than this turns a teaser into a second feature section. */
.studios-teaser { padding: 30px 24px; }
.st-teaser {
  display: grid;
  grid-template-columns: 1fr 300px;
  align-items: center;
  gap: 30px;
  max-width: 1000px;
  margin: 0 auto;
  padding: 26px 30px;
  border-radius: 22px;
  text-decoration: none;
  color: inherit;
  /* Warm, not white: distinct from the sections above and below it without
     introducing a new hue, and it makes the arriving photograph feel framed. */
  background: linear-gradient(120deg, #fdfaf6 0%, #f6f1ea 100%);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-sm);
  transition: box-shadow .18s ease, transform .18s ease, border-color .18s ease;
}
.st-teaser:hover {
  transform: translateY(-2px);
  border-color: var(--brand-100);
  box-shadow: 0 16px 38px rgba(79, 70, 229, .13);
}
.st-teaser-text { min-width: 0; }
.st-teaser-eyebrow {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--brand-600);
  margin: 0 0 8px;
}
/* Slightly more editorial than the feature grid: a serif-tight display size with
   negative tracking reads as a magazine standfirst, which is the register the
   photographer audience is used to. */
.st-teaser-head {
  font-size: clamp(24px, 3vw, 33px);
  letter-spacing: -0.022em;
  line-height: 1.15;
  margin: 0 0 8px;
  color: #0f172a;
}
.st-teaser-body {
  font-size: 15px;
  line-height: 1.6;
  color: var(--text-2);
  margin: 0 0 12px;
}
.st-teaser-cta {
  font-size: 14.5px;
  font-weight: 600;
  color: var(--brand-600);
  display: inline-block;
}
/* The arrow travels on hover — the one piece of motion here, and it points at
   the link rather than decorating the band. */
.st-teaser:hover .st-teaser-cta { text-decoration: underline; }
.st-teaser-art img {
  display: block;
  width: 100%;
  /* 162px, measured, not guessed: with the 26px card padding and the border the
     band lands at 216px, inside the 180–220px the brief asked for. At 172px it
     was 226px — 6px over, and the image is what sets the height, not the copy. */
  height: 162px;
  object-fit: cover;
  border-radius: 14px;
  box-shadow: 0 8px 22px rgba(15, 23, 42, .14);
}
/* RTL: the grid already mirrors, but the image needs to keep its own crop
   centred rather than recomposing, and the arrow in the CTA lives inside the
   translated string, so nothing else flips. */
body.is-fa .st-teaser-art img { object-position: center; }

@media (max-width: 860px) {
  .st-teaser { grid-template-columns: 1fr; gap: 18px; padding: 22px 22px; }
  /* Photo on top, then the text, then the CTA — the brief's mobile order. The
     markup keeps the text first for search engines and screen readers, so the
     swap is done here. */
  .st-teaser-art { order: -1; }
  .st-teaser-art img { height: 190px; }
}
@media (max-width: 560px) {
  .studios-teaser { padding: 22px 18px; }
  .st-teaser { padding: 18px; border-radius: 16px; }
  .st-teaser-art img { height: 160px; }
}
@media (prefers-reduced-motion: reduce) {
  .st-teaser { transition: none; }
  .st-teaser:hover { transform: none; }
}

/* Power of Narrative — the slogan's own quiet section. It is the one block on the
   page with no product UI in it, so it is also the one block that carries the
   artwork: a soft indigo wash, the hand-drawn swoosh behind the type and the
   tinted mosaic as grain. Nothing here is load-bearing for a visitor who lands
   on the section directly (the copy is plain text on top). */
.narrative { padding: 88px 24px; }
.narrative-card {
  position: relative; overflow: hidden; max-width: 1000px; margin: 0 auto;
  border-radius: 28px; padding: 78px 34px 82px; text-align: center;
  background: linear-gradient(160deg, #fff 0%, var(--brand-50) 58%, #ecf8fc 100%);
  border: 1px solid var(--brand-100);
  box-shadow: 0 18px 50px rgba(79,70,229,.08);
}
/* The arcs run wider than the card on purpose, so they leave through the edges
   instead of stopping mid-air inside it. */
.narrative-art {
  position: absolute; left: 50%; top: 50%; width: 132%; max-width: none;
  transform: translate(-50%, -50%); opacity: .62; pointer-events: none; z-index: 0;
}
.narrative-texture {
  position: absolute; inset: 0; z-index: 0; opacity: .05; pointer-events: none;
  background-repeat: repeat; background-size: 240px auto;
}
.narrative-card .container { position: relative; z-index: 1; max-width: 740px; margin: 0 auto; padding: 0; }
/* Gradient type, the same treatment as the headline and the stat numbers, so the
   slogan reads as brand voice rather than as another paragraph. */
.narrative-title {
  font-size: clamp(30px, 4.6vw, 48px); letter-spacing: -0.02em; margin: 0 0 24px;
  background: linear-gradient(120deg, var(--brand-600), var(--accent-500));
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.narrative-body { font-size: 18px; line-height: 1.85; color: var(--text-2); margin: 0 0 12px; }
.narrative-body:last-child { margin-bottom: 0; }

/* Product-tour modal ("See how it works"). Dark card so a video reads as video
   rather than as another white marketing panel. */
.tour-overlay { position: fixed; inset: 0; z-index: 60; display: flex; align-items: center;
  justify-content: center; padding: 20px; background: rgba(15, 23, 42, .74); }
.tour-card { width: 100%; max-width: 900px; background: #0b1220; border-radius: 16px;
  overflow: hidden; box-shadow: 0 24px 60px rgba(2, 6, 23, .5); }
.tour-head { display: flex; align-items: flex-start; justify-content: space-between;
  gap: 12px; padding: 12px 14px 12px 18px; color: #fff; }
.tour-title { margin: 0; font-size: 15px; font-weight: 700; }
.tour-note { margin: 3px 0 0; font-size: 12.5px; color: rgba(255, 255, 255, .68); }
.tour-close { flex: none; background: transparent; border: 0; color: #fff; font-size: 20px;
  line-height: 1; padding: 4px 10px; border-radius: 10px; cursor: pointer; }
.tour-close:hover { background: rgba(255, 255, 255, .14); }
.tour-video, .tour-embed { display: block; width: 100%; aspect-ratio: 16 / 9;
  background: #000; border: 0; }
.tour-missing { padding: 26px 20px 30px; color: #e2e8f0; font-size: 14.5px; line-height: 1.7;
  text-align: center; }
body.tour-open { overflow: hidden; }

/* AI Photo Edits pop-up (landing-photo-deck.js).
   Light card, unlike the tour/watch modals: those exist to show VIDEO and the dark
   surround makes it read better, while this one exists to show the app's own SCREENS,
   which are white — a dark frame around them fights the content.

   The deck inside is the SAME `.shot-deck` markup and CSS as the showcase section, so
   the fan, the tilt, the hover-open and the transitions are one implementation. Only
   two things change here: the deck fills the card (no 96px bottom margin, which exists
   to separate it from the section below) and it is capped a little narrower. */
.photo-deck-overlay { position: fixed; inset: 0; z-index: 60; display: flex;
  align-items: center; justify-content: center; padding: 18px;
  background: rgba(15, 23, 42, .74); }
.photo-deck-overlay[hidden] { display: none; }
.photo-deck-card { width: 100%; max-width: 1080px; max-height: 100%; overflow: auto;
  background: #fff; border-radius: 18px; padding: 18px 20px 14px;
  box-shadow: 0 24px 60px rgba(2, 6, 23, .45); }
.photo-deck-head { display: flex; align-items: flex-start; justify-content: space-between;
  gap: 14px; margin-bottom: 14px; }
.photo-deck-title { margin: 0; font-size: 17px; font-weight: 800; color: var(--text); }
.photo-deck-sub { margin: 4px 0 0; font-size: 13.5px; color: var(--text-2); }
.photo-deck-close { flex: none; border: 0; cursor: pointer; font-size: 22px; line-height: 1;
  padding: 4px 12px; border-radius: 12px; background: var(--surface, #f8fafc);
  color: var(--text-2); }
.photo-deck-close:hover { background: var(--brand-50); color: var(--brand-700); }
/* The deck inside the pop-up sizes from the VIEWPORT HEIGHT, not just its width.
   The deck box is 16:10 but the fanned cards step DOWN past its bottom edge (each
   depth adds 7px, 11px while hovered), so a deck that merely fits the width still
   pushes its own ‹ › bar — and the dialog's close button — off a laptop screen. The
   1.6 factor converts the height budget back into a width, because `aspect-ratio`
   is what sets the height. 300px is the chrome around the deck: card padding, the
   title block, the 76px the fan needs below the box (11px per depth while hovered,
   over six cards behind the front one), and the control bar. */
.photo-deck-overlay .shot-deck {
  width: min(100%, 920px, calc((100vh - 320px) * 1.6));
  margin: 0 auto 76px;
}
.photo-deck-overlay .shot-bar { margin-bottom: 4px; }
body.photo-deck-open { overflow: hidden; }
@media (max-width: 700px) {
  .photo-deck-card { padding: 14px 12px 10px; border-radius: 14px; }
  .photo-deck-title { font-size: 15px; }
  .photo-deck-sub { font-size: 12.5px; }
  /* The seven-slide fan is too tight to read on a phone, so the peeking cards step
     back further and the front one stays put. */
  .photo-deck-overlay .shot-card {
    transform: translateY(calc(var(--i) * 4px))
               rotate(calc(var(--dir) * var(--i) * .8deg))
               scale(calc(1 - var(--i) * .01));
  }
  .photo-deck-overlay .shot-deck:hover .shot-card,
  .photo-deck-overlay .shot-deck:focus-within .shot-card {
    transform: translateY(calc(var(--i) * 6px))
               rotate(calc(var(--dir) * var(--i) * 1.4deg))
               scale(calc(1 - var(--i) * .008));
  }
}

/* "Watch YouTube → Clip It" preview (landing-watch.js). Dark card for the same
   reason as the tour modal: it exists to show a video. The card itself is a doorway,
   so it is visibly interactive rather than just another copy panel. */
/* Doorway cards carry a DEEPER version of the same theme border (600 rather
   than 500) plus a stronger brand glow, so a card that opens something is never
   mistaken for one that is only copy. Written as two classes on purpose: the
   single-class rule that used to sit here was silently overruled by the
   `.feature-card` border further down the file. */
.feature-card.feature-card-action {
  cursor: pointer;
  background: linear-gradient(#fff, #fff) padding-box,
              linear-gradient(135deg, var(--brand-600), var(--accent-500)) border-box;
  box-shadow: 0 10px 26px rgba(99,102,241,.26), 0 2px 6px rgba(15,23,42,.06);
}
.feature-card.feature-card-action:hover {
  transform: translateY(-4px);
  box-shadow: 0 18px 38px rgba(99,102,241,.34), 0 4px 10px rgba(15,23,42,.08);
}
.feature-card-action:focus-visible { outline: 2px solid var(--brand-600, #4f46e5); outline-offset: 2px; }
.feature-cta { font-weight: 700; color: var(--brand-600, #4f46e5); white-space: nowrap; }
/* The Subtitles card links to the RTL proof with the same CTA treatment, but as a real
   anchor: the card itself is not a doorway (a whole-card role=button would swallow
   text selection), so this is an ordinary link inside the body line. */
a.feature-cta { text-decoration: none; }
a.feature-cta:hover, a.feature-cta:focus-visible { text-decoration: underline; }

/* Watch-YouTube demo pop-up (landing-watch.js).
   LIGHT card, matching the photo decks (.photo-deck-card): it shows the app's own
   screens and a visitor arrives here straight from the same feature grid, so two
   different modal styles on one page was the odd one out. It also has to be BIG — the
   whole point of the pop-up is the video, and the old 620px dark card made it a
   thumbnail next to the photo decks' 1080px frames.
   The width is therefore capped by the VIEWPORT HEIGHT as well: a 16:9 player at full
   width would push the card's own controls off a laptop screen, and the same
   `calc((100vh - …) * 16 / 9)` trick the deck uses keeps everything on screen with no
   inner scrolling and no letterboxing. 320px is the chrome around the player: card
   padding, the title block, the caption/cap lines, and the CTA row. */
.wd-overlay { position: fixed; inset: 0; z-index: 60; display: flex; align-items: center;
  justify-content: center; padding: 20px; background: rgba(15, 23, 42, .74); }
.wd-card { width: min(100%, 1080px, calc((100vh - 320px) * 16 / 9)); max-height: 92vh;
  overflow: auto; background: #fff; color: var(--text, #0f172a); border-radius: 18px;
  padding: 18px 20px 14px; box-shadow: 0 24px 60px rgba(2, 6, 23, .45); }
.wd-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.wd-title { margin: 0; font-size: 17px; font-weight: 800; color: var(--text); }
.wd-note { margin: 4px 0 0; font-size: 13.5px; color: var(--text-2, #475569); }
.wd-close { flex: none; border: 0; cursor: pointer; font-size: 22px; line-height: 1;
  padding: 4px 12px; border-radius: 12px; background: var(--surface, #f8fafc);
  color: var(--text-2); }
.wd-close:hover { background: var(--brand-50); color: var(--brand-700); }

.wd-demo { display: flex; align-items: center; gap: 12px; width: 100%; margin-top: 14px;
  padding: 10px; border: 1px solid var(--border, #e2e8f0); border-radius: 12px;
  background: #fff; color: var(--text); text-align: start; cursor: pointer; }
.wd-demo:hover { background: var(--surface, #f8fafc); }
.wd-demo-thumb, .wd-row-thumb { position: relative; flex: none; width: 148px; height: 83px;
  border-radius: 8px; overflow: hidden; background: #000; }
.wd-row-thumb { width: 104px; height: 58px; }
.wd-demo-thumb img, .wd-row-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.wd-play { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-size: 20px; color: #fff; text-shadow: 0 2px 8px rgba(0, 0, 0, .7);
  background: rgba(2, 6, 23, .22); }
.wd-row-thumb .wd-play { font-size: 14px; }
.wd-demo-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.wd-demo-label { font-size: 11px; text-transform: uppercase; letter-spacing: .04em;
  color: var(--text-3, #94a3b8); }
.wd-demo-title { font-size: 14.5px; font-weight: 600; }

.wd-search { display: flex; gap: 8px; margin-top: 14px; }
.wd-input { flex: 1 1 auto; min-width: 0; padding: 11px 13px; border-radius: 10px;
  border: 1px solid var(--border, #e2e8f0); background: #fff;
  color: var(--text); font-size: 14px; }
.wd-input::placeholder { color: var(--text-3, #94a3b8); }
.wd-btn { flex: none; padding: 11px 18px; border: 0; border-radius: 10px; cursor: pointer;
  font-weight: 700; font-size: 13.5px; color: #fff;
  background: linear-gradient(135deg, var(--brand-500, #6366f1), var(--accent-500, #06b6d4)); }
.wd-btn:disabled { opacity: .6; cursor: progress; }
.wd-status { margin: 10px 0 0; font-size: 12.5px; color: var(--text-2); min-height: 16px; }
.wd-results { margin-top: 8px; display: flex; flex-direction: column; gap: 8px; }
.wd-row { display: flex; align-items: center; gap: 10px; padding: 8px; border-radius: 10px;
  border: 1px solid var(--border, #e2e8f0); cursor: pointer; }
.wd-row:hover { background: var(--surface, #f8fafc); }
.wd-row:focus-visible { outline: 2px solid var(--brand-600, #4f46e5); outline-offset: 2px; }
.wd-row-body { min-width: 0; flex: 1 1 auto; }
.wd-row-title { margin: 0; font-size: 13.5px; font-weight: 600; color: var(--text); }
.wd-row-meta { margin: 2px 0 0; font-size: 11.5px; color: var(--text-3, #94a3b8); }
.wd-row-cta { flex: none; font-size: 11.5px; font-weight: 700; color: var(--brand-600, #4f46e5); }
.wd-foot { margin: 12px 0 0; padding-top: 10px; border-top: 1px solid var(--border, #e2e8f0);
  font-size: 11.5px; color: var(--text-3, #94a3b8); }
/* The player and its tap-to-hear button share this box: `.wd-unmute` is absolutely
   positioned over the video, so the wrapper has to be the positioned ancestor. The
   spacing that used to sit on `.wd-video` lives here now. */
.wd-player { position: relative; margin-top: 14px; }
.wd-video { display: block; width: 100%; border-radius: 12px;
  background: #000; aspect-ratio: 16 / 9; }
/* Phones refuse an unmuted autoplay that has no user gesture behind it, so a shared
   /try link starts the clip MUTED and needs one tap for the sound. This is that tap.
   A real button covering the whole video — the largest target a phone has, so any tap
   counts — and it is dismissed by its own click, which hands the native controls back
   the instant the sound is on. */
.wd-unmute { position: absolute; inset: 0; z-index: 2; display: flex;
  align-items: center; justify-content: center; padding: 0 18px; border: 0;
  border-radius: 12px; cursor: pointer; text-align: center;
  font: inherit; font-size: 15px; font-weight: 700; color: #fff;
  background: rgba(2, 6, 23, .42); }
.wd-unmute:hover { background: rgba(2, 6, 23, .55); }
.wd-unmute:focus-visible { outline: 2px solid #fff; outline-offset: -4px; }
.wd-unmute[hidden] { display: none; }
.wd-demo-caption { margin: 10px 0 0; font-size: 13.5px; font-weight: 600; color: var(--text); }
/* The trial's length limit. Quiet by default (it is information, not an error), and it
   turns amber only when the player actually reached the cap — so the visitor who just
   got stopped is the one who sees why. The amber is the DARK one: #fbbf24 was chosen
   against a navy card and disappears on white. */
.wd-cap { margin: 8px 0 0; font-size: 12.5px; color: var(--text-2, #475569); }
.wd-cap.is-hit { color: #b45309; font-weight: 700; }
/* The pointer to the search box under the demo player. It replaced a full-width
   "Download & clip this one" button: the visitor has just been given the preview, and
   a signup ask for a clip they did not choose is the wrong next step. Quiet on purpose
   — it is a signpost, not a second call to action competing with the search button. */
.wd-next { margin: 10px 0 0; font-size: 13px; color: var(--text-2, #475569); }
.wd-share { margin-top: 8px; width: 100%; padding: 9px 12px; border-radius: 10px;
  border: 1px solid var(--border, #e2e8f0); background: #fff; cursor: pointer;
  color: var(--text-2); font-size: 12.5px; font-weight: 600; }
.wd-share:hover { background: var(--surface, #f8fafc); }
body.wd-open { overflow: hidden; }
.hero-cta { display: flex; gap: 14px; align-items: center; flex-wrap: wrap; justify-content: center; }

.social-proof { padding: 58px 0; border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); background: var(--surface); position: relative; overflow: hidden; }
/* Mosaic texture behind the counters, tiled at a fixed size (the source motif is
   a small triangle pattern — stretched over the full strip it became five pale
   slabs), masked off the left/right edges where it would otherwise end in a hard
   line, and kept at single-digit opacity so the gradient digits stay legible. */
.social-proof .sp-texture {
  position: absolute; inset: 0; pointer-events: none; z-index: 0;
  background-repeat: repeat; background-size: 300px auto; opacity: .07;
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 14%, #000 86%, transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0, #000 14%, #000 86%, transparent 100%);
}
.social-proof .container { position: relative; z-index: 1; }
/*
   This block used to BE the flex row: the four `.sp-item` were its direct
   children, `--sp-gap` spread them out, and the `.sp-item + .sp-item::before`
   rules drew the hairlines between them.

   Then the heading and the subtitle were made VISIBLE above them (they used to
   be screen-reader-only) and the four counters were wrapped in `.sp-items` — but
   only the MARKUP changed. The container was still a row with wrapping on, so it
   laid out three children side by side: [heading] [subtitle] [.sp-items], and
   inside that unstyled block the four counters fell back to block layout and
   stacked VERTICALLY. Hence the deformed strip.

   So the row layout moves down one level, where the counters actually are, and
   the container becomes the column that stacks heading → sub → counters. The
   dividers keep working because the `.sp-item`s are still siblings of each other
   (now inside `.sp-items`), and they still inherit `--sp-gap` from here.
*/
.social-proof .container {
  --sp-gap: clamp(24px, 6vw, 92px);
  display: flex; flex-direction: column; align-items: center;
  text-align: center;
}
/* The row of four counters. This is the rule that has to exist for them to be
   horizontal at all — without it they are plain block divs. */
.sp-items {
  display: flex; justify-content: center; align-items: stretch;
  gap: var(--sp-gap); flex-wrap: wrap; width: 100%;
}
/* The heading and the subtitle. They are the same pattern as every other section
   on this page (`.section-head`), restated because this block has its own class
   names; they had no styling whatsoever before, so the browser defaults applied. */
.sp-title { font-size: clamp(30px, 4vw, 40px); letter-spacing: -0.01em; margin: 0 0 14px; }
.sp-sub { color: var(--text-2); font-size: 17px; margin: 0 0 52px; max-width: 640px; }
/* The stat value. This selector MUST match the markup: it was `.sp-item h2`,
   but the numbers were demoted from <h2> to <div class="sp-num"> for a correct
   document outline — which silently dropped the size. Both selectors are kept so
   an older cached template cannot regress the look.

   These are the biggest type on the page on purpose: four real numbers, counted
   up in place (see landing-stats.js). They carry the hero's indigo→cyan gradient
   so they read as one family with the headline, and `tabular-nums` stops the
   digits shuffling sideways while the count-up runs. */
.sp-item { position: relative; display: flex; flex-direction: column; justify-content: center; min-width: 0; }
.sp-item h2,
.sp-item .sp-num {
  font-size: clamp(56px, 7.6vw, 96px); font-weight: 800; line-height: 1;
  letter-spacing: -0.035em; margin: 0; font-variant-numeric: tabular-nums;
  background: linear-gradient(120deg, var(--brand-600), var(--accent-500));
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
/* Hairline rules between the stats, drawn with a pseudo-element so they can be
   dropped on the wrapped/mobile layout without touching the markup. */
.sp-item + .sp-item::before {
  content: ""; position: absolute; inset-block: 12%; inset-inline-start: calc(var(--sp-gap, 46px) / -2);
  width: 1px; background: linear-gradient(to bottom, transparent, var(--border), transparent);
}
.sp-item p {
  color: var(--text-2); font-size: 15px; font-weight: 600; letter-spacing: .02em;
  margin: 12px 0 0;
}

/* ---------------------------------------------------------------------------
   Inside the product: a fanned DECK of the real app screens.

   Every card is identical markup carrying its index in `--i` and its fan
   direction in `--dir`; this block turns those two numbers into the stack. The
   front card sits straight and undistorted, and each card behind it steps down
   a few pixels, tilts further to its own side and shrinks a touch — so the deck
   peeks out below and both sides instead of piling up. Hovering (or tabbing to
   it) opens the fan. Nothing here is written per screenshot, so reordering or
   adding one is a template-only edit.

   The cards step DOWNWARD on purpose: an upward stack would climb into the
   heading above. The images are pre-normalised to one 16:10 canvas by
   scripts/build_marketing_shots.py, which is what makes `object-fit: contain` an
   exact fit here — no cropping, no letterboxing, and the border and shadow wrap
   the visible panel rather than empty space.
--------------------------------------------------------------------------- */
.shot-deck {
  position: relative; width: min(100%, 1000px); margin: 0 auto 96px;
  aspect-ratio: 16 / 10;
  /* How many cards may sit in the fan behind the front one. The deck's script reads
     this number and fades everything deeper out (`is-deep`), so on a phone the ten
     cards it cannot usefully stack are not just invisible but OUT of the stacking
     maths — see paint() in landing-deck.js for what happened when they were not.
     Desktop: every slide, because the fan is the point and there is room for it. */
  --fan: 99;
  /* A swipe here is the deck's, a drag up/down is the page's. */
  touch-action: pan-y;
}
/* A soft brand glow, so the deck sits on something instead of floating. */
.shot-deck::before {
  content: ""; position: absolute; inset: 6% 2% 10%; border-radius: 50%;
  background: radial-gradient(closest-side, rgba(99,102,241,.16),
                              rgba(6,182,212,.10) 62%, transparent);
  filter: blur(6px);
}
.shot-card {
  position: absolute; inset: 0; margin: 0;
  z-index: calc(30 - var(--i));
  /* Slightly darker with each step, so the depth reads even where the white
     panels blend into the page. */
  filter: brightness(calc(1 - var(--i) * .015));
  transform: translateY(calc(var(--i) * 7px))
             rotate(calc(var(--dir) * var(--i) * .9deg))
             scale(calc(1 - var(--i) * .015));
  transition: transform .45s cubic-bezier(.22, .61, .36, 1), opacity .3s ease;
}
/* Deeper than the fan allows: faded out and untouchable, but still IN the deck, so
   flipping far enough brings it forward again. Set by landing-deck.js from --fan
   (CSS cannot compare a custom property against another number). */
.shot-card.is-deep { opacity: 0; pointer-events: none; }
.shot-card img {
  display: block; width: 100%; height: 100%; object-fit: contain;
  border-radius: 12px; border: 1px solid var(--border); background: #fff;
  box-shadow: 0 18px 40px rgba(15, 23, 42, .18);
}
.shot-deck:hover .shot-card,
.shot-deck:focus-within .shot-card {
  transform: translateY(calc(var(--i) * 11px))
             rotate(calc(var(--dir) * var(--i) * 1.7deg))
             scale(calc(1 - var(--i) * .012));
}
@media (prefers-reduced-motion: reduce) {
  .shot-card { transition: none; }
}
.shots-legend {
  max-width: 780px; margin: 0 auto; text-align: center;
  color: var(--text-2); font-size: 13.5px; font-weight: 600; letter-spacing: .02em;
}
/* The deck's own controls: ‹ name › under the stack. The name is announced when
   the deck flips (`aria-live`), which is how a screen reader learns what is on
   screen without nine images carrying alt text. */
.shot-deck { cursor: pointer; }
.shot-deck:focus-visible { outline: 2px solid var(--brand-600); outline-offset: 6px; border-radius: 14px; }
.shot-bar { display: flex; align-items: center; justify-content: center; gap: 14px; margin: 0 0 16px; }
.shot-nav {
  width: 38px; height: 38px; flex: none; border-radius: 50%; cursor: pointer;
  border: 1px solid var(--border); background: #fff; color: var(--text);
  font-size: 20px; line-height: 1; display: inline-flex; align-items: center;
  justify-content: center; transition: background .2s, border-color .2s, color .2s;
}
.shot-nav:hover { background: var(--brand-50); border-color: var(--brand-100); color: var(--brand-700); }
[dir="rtl"] .shot-nav { transform: scaleX(-1); }
.shot-here { min-width: 190px; text-align: center; font-size: 14px; font-weight: 700; color: var(--text); }
/* Phones: three cards read as a deck, and the rest of the slides are only rendered
   when they come forward. The legend below names every screen and a swipe flips to
   the next one, so nothing is lost.

   This used to be `#shotDeck .shot-card:nth-child(n + 5) { display: none; }`, which
   looked tidier than it was: the deck's script still counted the ten hidden cards, so
   a flip put a `display: none` slide at depth 0 — the caption named a screen that was
   not on screen — while the cards that WERE visible sat at depths 8-10, rotated and
   pushed ~50px down through the nav buttons ("Activity & Logs" and friends showed a
   different picture than the desktop deck did, and the stack looked misaligned).
   Hiding by DEPTH, in the script, keeps the arithmetic and the pixels in agreement.
   A smaller fan is still a fan; three is the most that is legible at this width. */
@media (max-width: 700px) {
  .shot-deck { margin-bottom: 56px; --fan: 3; }
  .shot-card {
    transform: translateY(calc(var(--i) * 5px))
               rotate(calc(var(--dir) * var(--i) * 1.4deg))
               scale(calc(1 - var(--i) * .02));
  }
  .shot-deck:hover .shot-card,
  .shot-deck:focus-within .shot-card {
    transform: translateY(calc(var(--i) * 7px))
               rotate(calc(var(--dir) * var(--i) * 2.2deg))
               scale(calc(1 - var(--i) * .018));
  }
}

.section { padding: 84px 24px; }
.section-head { text-align: center; max-width: 640px; margin: 0 auto 52px; }
.section-head h2 { font-size: clamp(30px,4vw,40px); letter-spacing:-0.01em; margin: 0 0 14px; }
.section-head p { color: var(--text-2); font-size: 17px; margin: 0; }

/* ----------------------------------------------------------------------------
   FEATURES — the section backdrop.

   The artwork is the designer's blurred master (images/backgrounds/2.jpg)
   built to web size by scripts/build_features_background.py; the URL arrives on
   the <div> INLINE (templates/landing.html) so it can carry ?v={{ asset_v }} —
   a background written here could not be cache-busted, and an updated artwork
   would keep showing the old one until someone hard-refreshed.

   `isolation` makes this section its own stacking context: the backdrop sits at
   z-index 0 and the copy at 1, so neither has to know what the rest of the page
   is doing with z-index.

   The wash: the artwork is a saturated magenta -> amber -> cyan gradient over a
   near-black base, so at full strength it fights the dark heading. Dropping the
   LAYER's opacity blends it toward the white page underneath — that IS the veil,
   and it is why no second overlay element is needed. Bright bands survive it;
   the black base settles to a pale grey.
   ---------------------------------------------------------------------------- */
#features { position: relative; isolation: isolate; }
.features-bg {
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background-size: cover; background-position: center; background-repeat: no-repeat;
  opacity: .34;
  /* The section's own top/bottom edges are where the artwork would otherwise
     meet the white sections above and below it in a hard horizontal line — the
     master has no soft edge of its own. Fading the layer out over the first and
     last tenth dissolves both joins, the way `.sp-texture` masks off its left
     and right ends instead of ending on a cut. */
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 11%, #000 89%, transparent 100%);
  mask-image: linear-gradient(180deg, transparent 0, #000 11%, #000 89%, transparent 100%);
}
/* Everything the section SAYS rides above the artwork. One rule rather than a
   z-index per element, so the heading block, the banner, the grid and anything
   added later are all covered — a layer that silently covers the copy is exactly
   the bug this comment exists to prevent. */
#features > .section-head,
#features > .sp-banner,
#features > .features-grid { position: relative; z-index: 1; }

.features-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 22px; max-width: 1140px; margin: 0 auto; }
/* Theme-coloured border: the signature indigo -> cyan gradient, drawn as a real
   2px border by layering the card's white fill over the gradient and clipping
   each to its own box (`padding-box` / `border-box`) — the `transparent` border
   colour is what lets the gradient show through. A `border-color` cannot be a
   gradient, and a gradient background with no border would bleed over the
   rounding. The shadow is ALWAYS on, not just on hover, because the cards now
   sit on the blurred backdrop above and need to read as raised tiles against it. */
.feature-card {
  background: linear-gradient(#fff, #fff) padding-box,
              linear-gradient(135deg, var(--brand-500), var(--accent-500)) border-box;
  border: 2px solid transparent;
  border-radius: var(--r-lg); padding: 26px 24px;
  box-shadow: 0 6px 18px rgba(79,70,229,.14), 0 2px 5px rgba(15,23,42,.05);
  transition: transform .18s ease, box-shadow .18s ease;
  display: flex; align-items: flex-start; gap: 18px; text-align: start;
}
.feature-card:hover { transform: translateY(-4px); box-shadow: 0 14px 30px rgba(79,70,229,.22), 0 4px 10px rgba(15,23,42,.07); }
.feature-icon { flex: none; width: 60px; height: 60px; border-radius: 16px; display: flex; align-items: center; justify-content: center; background: var(--brand-50); }
.feature-icon img { width: 100%; height: 100%; object-fit: contain; padding: 13px; }
.feature-body { flex: 1; min-width: 0; }
/* Title + NEW pill are two FLEX items rather than one inline run. As an inline
   span the pill was the end of an RTL text run, so on a title that wrapped it
   landed on the second line in the MIDDLE of the title ("…کلیپش [جدید] کن"), and
   on a title that just fit it pushed itself onto a line of its own. */
.feature-card h3 { display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  font-size: 18px; margin: 0 0 8px; line-height: 1.3; }
.feature-card p { color: var(--text-2); font-size: 15px; margin: 0; line-height: 1.5; }
/* Cards now carry a headline AND a body, so they stack: a 60px icon beside three
   lines of copy was cramped at the grid's 230px minimum. The headline is the
   promise (bold, full ink); the body stays muted underneath it. Everything is
   aligned with `start` rather than `left`, so the same rules read correctly in the
   Farsi page (where the whole card is mirrored) without an [dir="rtl"] override on
   every element. */
.feature-card { flex-direction: column; align-items: flex-start; gap: 14px; }
.feature-card .feature-head { font-weight: 700; color: var(--text); font-size: 15.5px; margin: 0 0 7px; }
/* "New" pill on the cards that advertise capabilities nobody else has. */
.badge-new { display: inline-block; padding: 2px 9px;
  border-radius: var(--r-pill); background: linear-gradient(120deg, var(--brand-600), var(--accent-500));
  color: #fff; font-size: 10.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; }

/* ----------------------------------------------------------------------------
   SMART PUBLISHING BANNER — the featured strip between the heading and the grid.

   It borrows the CARDS' OWN language on purpose: a gradient border drawn the same
   way (white fill over the gradient, clipped to padding-box/border-box), the same
   radius and shadow, and copy aligned with `start` so it mirrors with the page.

   Full width of the grid, not of the section: `max-width: 1140px` is the SAME
   number as `.features-grid`, so the banner's edges line up with the first and
   last card at every width, and `margin: 0 auto` keeps both centred together.

   On phones the grid becomes an edge-to-edge scroller (see below) while the
   banner stays inside the section's own 24px gutter — deliberately: a static
   block that bleeds off the screen would read as a crop, not as a swipe affordance.
   ---------------------------------------------------------------------------- */
.sp-banner {
  position: relative;
  /* The page has no global box-sizing reset, so without this `max-width` would be
     the CONTENT box and the 46px padding + 2px border would push the banner 96px
     wider than the grid it is meant to line up with. */
  box-sizing: border-box;
  max-width: 1140px;
  margin: 0 auto 26px;
  padding: 40px 46px;
  display: grid;
  /* The copy takes the room it needs; the diagram is capped so it never crowds
     the text at the narrow end of the desktop range (900-1080px). */
  grid-template-columns: minmax(0, 1.3fr) minmax(0, .7fr);
  align-items: center;
  gap: 44px;
  border-radius: var(--r-lg);
  /* The "featured" accent lives IN THE BORDER, as the first stops of a single
     VERTICAL gradient: solid gold across the top, dissolving down the sides into
     the brand indigo and then the accent cyan. One continuous gradient, so there
     is no seam anywhere.

     It used to be a separate 4px ::before strip inside the border, fading gold →
     cyan. That put a second, differently-coloured band BETWEEN the border and the
     card's white background, and the gold-to-cyan blend read as a smear at the top
     of the card — reported as "the border on top is not smooth". Moving the gold
     into the border removes the band entirely: whatever colour is at the top IS
     the border, and nothing sits between it and the background. */
  background: linear-gradient(#fff, #fff) padding-box,
              linear-gradient(180deg, #d4af37 0%, #d4af37 1.4%,
                              var(--brand-500) 16%, var(--accent-500) 100%) border-box;
  border: 2px solid transparent;
  box-shadow: 0 12px 30px rgba(79,70,229,.16), 0 2px 6px rgba(15,23,42,.05);
  text-align: start;
  /* Clips the CTA focus outline to the rounded corners. Nothing else needs to
     overflow: the accent is part of the border now, not a child element. */
  overflow: hidden;
}
.sp-banner-copy { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; min-width: 0; }
/* Its own pill, NOT `.badge-new`: the grid's badge count is pinned at three and
   this banner is not one of the twelve cards. Bigger and bolder than the card
   pill because it is the only badge in the strip. */
.sp-banner-badge {
  display: inline-block; padding: 4px 13px; border-radius: var(--r-pill);
  background: linear-gradient(120deg, var(--brand-600), var(--accent-500));
  color: #fff; font-size: 11px; font-weight: 800;
  letter-spacing: .07em; text-transform: uppercase;
}
[dir="rtl"] .sp-banner-badge { letter-spacing: 0; }
.sp-banner-title { margin: 6px 0 0; font-size: clamp(24px, 2.6vw, 33px); line-height: 1.15; letter-spacing: -0.01em; color: var(--text); }
.sp-banner-sub { margin: 0; font-weight: 700; font-size: clamp(17px, 1.6vw, 21px); line-height: 1.35; color: var(--brand-600); }
.sp-banner-body { margin: 4px 0 0; color: var(--text-2); font-size: 16px; line-height: 1.6; max-width: 48ch; }
.sp-banner-cta {
  margin-top: 16px; display: inline-flex; align-items: center; gap: 9px;
  padding: 12px 22px; border-radius: var(--r-pill);
  /* box-sizing: border-box is REQUIRED here: the page has no global box-sizing
     reset, so `width: 100%` (set at <=520px below) was the CONTENT box and the
     44px of horizontal padding pushed the button past the banner's border on a
     phone. max-width is a belt-and-braces guard. */
  box-sizing: border-box; max-width: 100%;
  background: linear-gradient(120deg, var(--brand-600), var(--accent-500));
  color: #fff; font-weight: 700; font-size: 15px; text-decoration: none;
  box-shadow: 0 8px 20px rgba(99,102,241,.30);
  transition: transform .18s ease, box-shadow .18s ease;
}
.sp-banner-cta:hover { transform: translateY(-2px); box-shadow: 0 12px 26px rgba(99,102,241,.38); color: #fff; }
.sp-banner-cta:focus-visible { outline: 2px solid var(--brand-700); outline-offset: 2px; }
/* The arrow is an inline SVG (see the template): a real glyph would be drawn
   unchanged in the RTL layout and point the wrong way. Mirror the SVG instead. */
.sp-banner-arrow { flex: none; transition: transform .18s ease; }
.sp-banner-cta:hover .sp-banner-arrow { transform: translateX(3px); }
[dir="rtl"] .sp-banner-arrow { transform: scaleX(-1); }
[dir="rtl"] .sp-banner-cta:hover .sp-banner-arrow { transform: scaleX(-1) translateX(3px); }

/* ---- the diagram: one post in, several destinations out ------------------ */
.sp-banner-art { display: flex; flex-direction: column; gap: 10px; min-width: 0; justify-self: end; width: 100%; max-width: 420px; }
.sp-banner-src {
  display: flex; align-items: center; gap: 11px; padding: 11px 14px;
  border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface);
  font-size: 14px; font-weight: 700; color: var(--text);
}
/* The THREE platforms Smart Publishing can watch (mirror.SOURCES: Bale, Telegram,
   Rubika) as one overlapped trio, so the chip shows the choice rather than a row of
   names it has no room for. Each mark carries a ring in the chip's own colour, which
   is what makes the overlap read as a stack. */
.sp-banner-src-icons { display: inline-flex; flex: none; align-items: center; }
.sp-banner-src-icons img { flex: none; border-radius: 8px; }
.sp-banner-src-icons img + img { margin-inline-start: -7px; box-shadow: 0 0 0 2px var(--surface, #f8fafc); }
.sp-banner-flow { display: grid; place-items: center; color: var(--brand-500); line-height: 0; }
.sp-banner-dests { list-style: none; margin: 0; padding: 0; display: grid;
  /* auto-fit, not a fixed two-up: the diagram lives in a ~350px column on desktop
     (2x2), gets the whole ~640-820px when the banner stacks (one row of four), and
     is a single column on a phone. One declaration, three honest layouts. */
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 8px; }
.sp-banner-dest {
  display: flex; align-items: center; gap: 8px; padding: 9px 11px;
  border: 1px solid var(--border); border-radius: var(--r-md); background: #fff;
  box-shadow: var(--shadow-sm); font-size: 13px; font-weight: 600; color: var(--text-2);
}
.sp-banner-dest img { flex: none; border-radius: 6px; }
.sp-banner-dest span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The tick sits at the far END of the chip in both directions (`margin-inline-start:
   auto`), so the Farsi chips read icon -> name -> tick from the right. */
.sp-banner-dest i { margin-inline-start: auto; font-style: normal; font-weight: 800; color: var(--success, #059669); }
/* The same-platform destination: brand-tinted, so "another group" is visibly the
   same network as the source above it and not a fourth platform. */
.sp-banner-dest-self { border-color: var(--brand-200); background: var(--brand-50); color: var(--brand-700); }

/* Tablet and below: stack (copy, then diagram), per the mobile layout. The diagram
   is left flush with the copy rather than centred, because its SOURCE chip is the
   first thing to read — centring it detached it from the paragraph above. */
@media (max-width: 900px) {
  .sp-banner { grid-template-columns: 1fr; gap: 26px; padding: 30px 26px 32px; }
  /* The diagram gets the whole width, so `auto-fit` turns the chips into one row
     instead of a narrow 2x2 stranded in a wide banner. */
  .sp-banner-art { justify-self: stretch; max-width: none; }
}
@media (max-width: 520px) {
  .sp-banner { padding: 24px 20px 26px; border-radius: var(--r-md); }
  .sp-banner-body { font-size: 15px; }
  .sp-banner-cta { width: 100%; justify-content: center; }
}

/* Phones: the grid is a row you swipe, not a twelve-card column. Stacked it was
   most of a screen per card before the visitor reached anything else on the page —
   and the cards ARE the pitch, so they are worth more as one-at-a-time slides with
   the next one peeking in from the edge.

   A native scroller rather than a carousel script: `scroll-snap` does the paging,
   the cards stay ordinary DOM (so the new card, the doorways and their dialogs are
   untouched), nothing has to be kept in sync, and the whole thing still works with
   JavaScript off. The padding/margin pair cancels the section's own 24px inset so a
   card can sit flush against the screen edge while the row keeps its end gaps — and
   the same pair reserves VERTICAL room for the card shadow, which `overflow-x: auto`
   would otherwise clip (an axis that scrolls makes the other one compute to auto
   too). Both sides are 24px because that is what the card's shadow actually
   reaches: 6px offset + 18px blur. At the old 10px the row cut it off in a straight
   line under every card; because the margin cancels the padding, the cards do not
   move. */
@media (max-width: 700px) {
  .features-grid {
    display: flex; gap: 14px; overflow-x: auto;
    margin: -24px -24px; padding: 24px 24px;
    scroll-snap-type: x mandatory; scroll-padding-inline: 24px;
    overscroll-behavior-x: contain; -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .features-grid::-webkit-scrollbar { display: none; }
  /* 78% shows the next card's edge. That edge is the only affordance the row has —
     there is no arrow and no scrollbar to explain it — so it is not optional. */
  .feature-card { flex: 0 0 78%; scroll-snap-align: start; }
}

/* RTL highlight — same treatment as the narrative card (wash, mosaic grain, swoosh
   behind), because it is the second block whose job is to make a point rather than
   to show a feature. */
.rtl-proof { padding: 84px 24px; }
.rtl-card { position: relative; overflow: hidden; max-width: 1120px; margin: 0 auto; border-radius: 28px;
  padding: 64px 40px; border: 1px solid var(--brand-100);
  background: linear-gradient(150deg, #fff 0%, var(--brand-50) 62%, #ecf8fc 100%); }
.rtl-art { position: absolute; left: 50%; top: 50%; width: 120%; max-width: none;
  transform: translate(-50%, -50%); opacity: .45; pointer-events: none; z-index: 0; }
.rtl-texture { position: absolute; inset: 0; z-index: 0; opacity: .05; pointer-events: none;
  background-repeat: repeat; background-size: 240px auto; }
.rtl-grid { position: relative; z-index: 1; display: grid; grid-template-columns: 1.05fr .95fr;
  gap: 44px; align-items: center; }
.rtl-title { font-size: clamp(28px, 3.6vw, 40px); letter-spacing: -0.02em; margin: 0 0 20px; }
.rtl-body { font-size: 17px; line-height: 1.8; color: var(--text-2); margin: 0 0 14px; }
.rtl-strong { color: var(--brand-700); font-weight: 700; }
.rtl-demo { display: flex; flex-direction: column; gap: 14px; }
.rtl-pane { border-radius: var(--r-lg); padding: 15px 18px 17px; background: #fff;
  border: 1px solid var(--border); box-shadow: var(--shadow-sm); }
.rtl-pane-bad { border-color: #fecdd3; background: linear-gradient(180deg, #fff, #fff1f2); }
.rtl-pane-good { border-color: #a7f3d0; background: linear-gradient(180deg, #fff, #ecfdf5); }
.rtl-pane-label { display: inline-block; font-size: 10.5px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--text-3); }
.rtl-pane-bad .rtl-pane-label { color: #be123c; }
.rtl-pane-good .rtl-pane-label { color: #047857; }
.rtl-sample { margin: 9px 0 0; font-size: 20px; line-height: 1.65; color: var(--text); }
/* What a tool without RTL shaping does to the same line: every letter isolated and
   the run reversed. (Inline-block per character, inside an LTR direction.) */
.rtl-note { margin: 0; font-size: 12.5px; color: var(--text-3); text-align: center; }
/* The two proof panes are IMAGES now, not DOM text — see the template comment and
   scripts/build_rtl_proof.py. They are the same 1200x260 canvas, so they line up
   whatever width the grid gives them, and they carry real alt text: these are not
   decoration, they are the evidence for the section's claim. */
.rtl-shot { display: block; width: 100%; height: auto; margin: 9px 0 0;
  border-radius: 10px; border: 1px solid var(--border); background: #fff; }

/* Platform cards: a grid of flip cards rather than a row of pills (seven pills
   read as a logo strip and say nothing). The front carries the platform's own
   brand colour, its icon and whether it is an Iranian or an international
   account; the back carries what the product does with it.

   The flip lives on .pcard-inner (a transform on the inner wrapper) so both faces
   stay in the document — `display: none` on a face would take the copy away from
   screen readers and crawlers. Tap and keyboard focus flip the card; hover only
   lifts it (see the .pcard rules below). */
.platform-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 16px; max-width: 1000px; margin: 0 auto; perspective: 1400px; }
/* BOTH faces are fixed to this height (they are absolutely positioned inside
   .pcard-inner), so the tallest back sets it. The back now carries up to FOUR
   lines — Soroush Plus adds "Text Only" to the three shared guarantees — and the
   Persian strings wrap to two lines at the narrowest column the grid can produce
   (minmax 220px). Measured in Chromium with a real Arabic face at 235px and 220px
   columns: 172px clipped the last line by 10px, 200px leaves the 18px bottom
   padding intact. The front face is centred, so it just breathes a little more. */
.pcard { height: 200px; border-radius: var(--r-lg); cursor: pointer; outline-offset: 3px;
  transition: transform .25s ease; }
/* A hover LIFT, not a hover FLIP. Flipping on hover made the card's own geometry
   change under the pointer, which fought scrolling (browsers re-scroll to keep a
   moving element in view, which moves the pointer off the card again) and left the
   back unreadable on touch, where hover is sticky or absent. Tap and keyboard
   focus now do the flipping, so the interaction is identical on every device. */
.pcard:hover { transform: translateY(-3px); }
.pcard:hover .pcard-face { box-shadow: var(--shadow-md); }
.pcard-inner { position: relative; width: 100%; height: 100%; transform-style: preserve-3d;
  transition: transform .6s cubic-bezier(.2,.75,.2,1); }
.pcard:focus-visible .pcard-inner, .pcard.is-flipped .pcard-inner { transform: rotateY(180deg); }
.pcard-face { position: absolute; inset: 0; overflow: hidden; border-radius: var(--r-lg);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 9px;
  padding: 18px 14px; text-align: center; background: #fff; border: 1px solid var(--border);
  box-shadow: var(--shadow-sm); -webkit-backface-visibility: hidden; backface-visibility: hidden; }
.pcard-bar { position: absolute; inset: 0 0 auto 0; height: 4px; background: var(--pc, var(--brand-500)); }
.pcard-icon { width: 48px; height: 48px; display: grid; place-items: center; border-radius: 14px;
  background: #fff; border: 1px solid var(--border);
  background: color-mix(in srgb, var(--pc, #6366f1) 12%, #fff); }
.pcard-icon img { width: 27px; height: 27px; object-fit: contain; }
.pcard-name { font-weight: 700; font-size: 15.5px; color: var(--text); }
.pcard-tag { font-size: 10.5px; font-weight: 700; letter-spacing: .02em; text-transform: uppercase;
  color: var(--brand-600); background: var(--brand-50); border-radius: var(--r-pill); padding: 4px 10px;
  /* Two tags are full sentences ("Watch, Download, Clip. No VPN Required."), so the
     pill wraps instead of the type shrinking. */
  text-align: center; line-height: 1.35; }
.pcard-back { transform: rotateY(180deg); justify-content: flex-start; align-items: flex-start;
  text-align: start; background: linear-gradient(160deg, #fff 0%, var(--brand-50) 100%);
  border-color: var(--brand-100); }
/* The back repeats the platform icon beside its name: the back is a different
   layout every time it is turned up, and without the icon it stops being obvious
   which platform you are looking at. */
.pcard-back .pcard-name { display: flex; align-items: center; gap: 8px; }
.pcard-back .pcard-back-icon { width: 22px; height: 22px; object-fit: contain; flex: none; }
.pcard-list { list-style: none; margin: 4px 0 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.pcard-list li { position: relative; padding-inline-start: 18px; font-size: 13.5px; line-height: 1.4; color: var(--text-2); }
.pcard-list li::before { content: ""; position: absolute; inset-inline-start: 0; top: .42em;
  width: 8px; height: 8px; border-radius: 50%;
  background: linear-gradient(120deg, var(--brand-500), var(--accent-500)); }
.pcards-hint { text-align: center; color: var(--text-3); font-size: 13.5px; margin: 22px 0 0; }
@media (prefers-reduced-motion: reduce) { .pcard-inner { transition: none; } }
@media (max-width: 860px) {
  .rtl-grid { grid-template-columns: 1fr; gap: 30px; }
  .rtl-card { padding: 48px 22px; }
}

.pricing-section { background: var(--surface); }
.pricing-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 20px; max-width: 1140px; margin: 0 auto; }
.price-card { background: #fff; border: 1px solid var(--border); border-radius: var(--r-lg); padding: 28px 24px; display: flex; flex-direction: column; gap: 16px; position: relative; }
.price-card.popular { border: 2px solid var(--brand-500); box-shadow: var(--shadow-brand); }
.popular-badge { position: absolute; top: -14px; left: 50%; transform: translateX(-50%); background: var(--brand-600); color: #fff; font-size: 12px; font-weight: 700; padding: 5px 14px; border-radius: var(--r-pill); }
.price-card .price-name { font-weight: 700; font-size: 17px; }
.price-card .price-amt { font-size: 40px; font-weight: 800; }
.price-card .price-amt span { font-size: 16px; font-weight: 500; color: var(--text-3); }
/* ---- Monthly / Annual toggle (landing-pricing.js) -------------------------
   Shared by the landing page, /pricing and /studios. ANNUAL IS THE DEFAULT. Under
   it the headline is the equivalent MONTHLY cost, printed in FULL ("1,333,000",
   not "1.3M") with "— toumans billed annually" BENEATH it (the note is a block,
   see below); Monthly swaps that one word back. The full number is longer than the
   abbreviated monthly one, so the price never wraps — design.css sets
   white-space: nowrap on the card price, and letting it wrap would push the
   currency line onto a third row exactly as it used to on the Starter card. */
.billing-toggle {
  display: flex; align-items: center; justify-content: center;
  gap: 6px; flex-wrap: wrap; margin: 0 auto 26px;
  background: var(--surface-2, #f1f5f9); border: 1px solid var(--border);
  border-radius: var(--r-pill); padding: 5px; width: fit-content; position: relative;
}
.bt-opt {
  appearance: none; border: 0; background: transparent; cursor: pointer;
  font: inherit; font-size: 14px; font-weight: 700; color: var(--text-3);
  padding: 8px 20px; border-radius: var(--r-pill); transition: background .15s, color .15s;
}
.bt-opt.is-on { background: #fff; color: var(--brand-600); box-shadow: 0 1px 3px rgba(15,23,42,.14); }
.bt-opt:focus-visible { outline: 2px solid var(--brand-500); outline-offset: 2px; }
.bt-save {
  position: absolute; inset-inline-start: 100%; margin-inline-start: 10px;
  background: #16a34a; color: #fff; font-size: 11.5px; font-weight: 800;
  padding: 4px 11px; border-radius: var(--r-pill); white-space: nowrap;
}
/* The badge is hidden on narrow screens: it is an aside, and the toggle has to
   stay centred without it. */
@media (max-width: 720px) { .bt-save { position: static; margin: 0 0 0 4px; } }
[dir="rtl"] .bt-save { inset-inline-start: auto; inset-inline-end: 100%; margin-inline-start: 0; margin-inline-end: 10px; }
/* ONE price size for BOTH billing states on the landing page.
   The two states used to differ — 40px on Monthly, 28px on Annual — so toggling
   made the price visibly jump. They now share the Annual size, which is the one
   the disclosure needs: it has to fit the FULL equivalent number (625,000 /
   1,333,000 / 4,416,000) rather than the abbreviation the monthly state shows
   (750K / 1.6M / 5.3M).
   Scoped to `#pricing`, which only the landing page has: pricing.html and
   studios.html load this same stylesheet and keep the 40px size above. */
#pricing .price-card .price-amt { font-size: 28px; letter-spacing: -0.4px; }
/* The "— toumans billed monthly/annually" note sits on its OWN LINE, under the
   figure. Inline after the number it read as one run-on line and wrapped at the
   card edge; as a block it is a footnote to the price, which is what it is.
   NOT scoped to `#pricing`: /pricing and /studios show the same contract. */
.price-card .price-amt [data-p-annual-note],
.price-card .price-amt [data-p-monthly-note] {
  display: block; font-size: 12px; font-weight: 600; color: var(--text-3);
  margin-top: 3px;
  /* design.css sets `white-space: nowrap` on `.price-amt` (which is why the
     monthly price never split across lines), and a child inherits it. The note
     is the ONE part of the price block that must be allowed to wrap: both notes
     are ~180px of text in a card whose content box can be as narrow as ~162px,
     so nowrap pushed them out of the card on every paid plan. */
  white-space: normal;
}
/* The wrapper span around the NUMBER must not inherit the small grey style the
   unit spans get: in the annual state the amount is wrapped (so the script can
   swap its text), and without this rule the price rendered at 16px grey instead
   of as the price. The "— toumans billed …" note keeps the small type
   deliberately. */
.price-card .price-amt [data-p-amount] { font-size: inherit; font-weight: inherit; color: inherit; }
/* Cards WITHOUT a toggle (a plan whose yearly switch is off, or a sheet that does
   not load landing-pricing.js) must still read monthly, so the markup ships the
   annual note hidden and the unknown state is the monthly one. */
.price-card [hidden] { display: none !important; }
.price-card ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
/* Each feature row is a fixed bullet + a run of mixed value/label text (e.g.
   "Up to  2  connected accounts"). Justifying it in the READING DIRECTION keeps
   the value and its label together and flush to the correct margin, instead of
   the ragged wrapping that happened when the spans were inline. */
.price-card ul li {
  display: flex; gap: 9px; align-items: baseline;
  font-size: 14.5px; color: var(--text-2);
  justify-content: flex-start;
  text-align: start;
}
.price-card ul li .tick { color: #16a34a; font-weight: 800; flex: none; }
.price-card ul li .li-body {
  flex: 1 1 auto;
  text-align: start;
  direction: inherit;
  unicode-bidi: plaintext;
}
/* RTL: the bullet sits on the right and the text hugs the right margin. */
[dir="rtl"] .price-card ul li { text-align: right; }
[dir="rtl"] .price-card ul li .li-body { text-align: right; }
[dir="ltr"] .price-card ul li { text-align: left; }
[dir="ltr"] .price-card ul li .li-body { text-align: left; }
.price-card .btn { margin-top: auto; }
.price-note { text-align: center; color: var(--text-3); font-size: 14px; margin: 26px 0 0; }

/* The YouTube mark used INLINE as a row icon: the Watch Now rows on /pricing
   (the plan card and the three comparison-table rows) and the same row in the
   landing pricing block. It replaces the 🎬 that stood for "watch YouTube"
   there, so it has to sit on the text's baseline like the emoji did and follow
   whatever size the row is set in — hence `em`, not px. `contain` in a 1.1em
   square keeps the footprint the emoji had; `flex: none` stops it being squeezed
   in the flex rows. */
.yt-ico { width: 1.15em; height: 1.15em; object-fit: contain; flex: none;
  vertical-align: -0.2em; display: inline-block; }

/* ---------------------------------------------------------------------------
   Buttons.
   These classes (btn, btn-lg, btn-primary, btn-ghost, btn-white) were used by
   landing.html but NEVER DEFINED — styles.css holds a .btn-primary, but the
   landing page only loads design.css + landing.css, so every button on this
   page fell back to plain link styling. Defined here so they render as real
   buttons on both the hero and the CTA band.
   --------------------------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font-weight: 600; font-size: 15px; line-height: 1;
  padding: 12px 22px; border-radius: var(--r-pill, 999px);
  border: 1px solid transparent; cursor: pointer;
  text-decoration: none; white-space: nowrap;
  transition: transform .15s ease, box-shadow .15s ease, background .15s ease;
}
.btn:hover { transform: translateY(-1px); }
.btn-sm { padding: 9px 18px; font-size: 14px; }
.btn-lg { padding: 15px 28px; font-size: 17px; }
.btn-primary { background: var(--brand-600); color: #fff; box-shadow: 0 6px 16px rgba(79,70,229,.28); }
.btn-primary:hover { background: var(--brand-700); }
.btn-ghost { background: #fff; color: var(--text); border-color: var(--border-2, var(--border)); }
.btn-ghost:hover { background: var(--surface-2); }
/* On the dark CTA band a white button is needed — otherwise a ghost button is
   invisible against the gradient. */
.btn-white { background: #fff; color: var(--brand-600); box-shadow: 0 8px 22px rgba(0,0,0,.22); }
.btn-white:hover { background: var(--brand-50); }

/* The way into the DETAILED pricing page, under the landing plan cards. AFTER
   the .btn base ON PURPOSE: both are single-class selectors, so `.btn` (defined
   above) would win the shared padding/font-size if this came first. A FILLED
   brand-gradient button rather than a text link — it is the only route from the
   landing page to the comparison table, and a quiet link under four plan cards
   is exactly what a visitor scanning for "more detail" misses. */
.pricing-full-cta { text-align: center; margin: 26px 0 0; }
.btn-full-plans {
  background: linear-gradient(135deg, var(--brand-600), var(--accent-500, #06b6d4));
  color: #fff; font-weight: 800; font-size: 16px; padding: 15px 30px;
  border-color: transparent;
  box-shadow: 0 10px 24px rgba(79,70,229,.28);
}
.btn-full-plans:hover { transform: translateY(-2px); box-shadow: 0 14px 30px rgba(79,70,229,.34); }

.cta-band { padding: 80px 24px; text-align: center; background: linear-gradient(135deg, var(--brand-600), var(--brand-700)); color: #fff; }.cta-band h2 { font-size: clamp(30px,4vw,40px); margin: 0 0 16px; }
.cta-band p { color: rgba(255,255,255,.85); font-size: 18px; margin: 0 0 28px; }

.site-footer { background: #0f172a; color: #cbd5e1; padding: 52px 24px 30px; }
/* Tehran skyline sitting on the white page immediately above the footer
   (`landscapedark.svg`, the ink version of the hero artwork). Centred and capped
   in width so it is never cropped — at full bleed the 852:312 ratio would be
   ~530px of silhouette on a desktop, and cutting it to a band would take the
   tower tops with it, which is exactly what the hero already learned. */
.footer-skyline { background: #fff; padding: 26px 24px 0; text-align: center; overflow: hidden; }
/* Masked at the sides so the silhouette's own edges do not end as a slab
   (the hero skyline uses the same trick). Its baseline sits exactly on the
   footer's #0f172a, so the city reads as one continuous horizon. */
.footer-skyline img { display: block; width: 100%; max-width: 760px; height: auto; margin: 0 auto;
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 2.5%, #000 97.5%, transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0, #000 2.5%, #000 97.5%, transparent 100%); }
.site-footer .container { max-width: 1140px; margin: 0 auto; }
.site-footer .footer-grid { display: grid; grid-template-columns: 2fr 1fr 1fr 1fr; gap: 40px; margin-bottom: 36px; }
.site-footer h4 { color: #fff; font-size: 15px; margin: 0 0 16px; }
/* Footer column labels. These were <h4>, which made the heading outline jump
   h2 -> h4 and told search engines they were page sections. They are
   navigational labels, so they are plain <p> elements styled to match. */
.site-footer .footer-head { color: #fff; font-size: 15px; font-weight: 600; margin: 0 0 16px; }
.site-footer ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.site-footer ul a { color: #94a3b8; font-size: 14.5px; text-decoration: none; }
.site-footer ul a:hover { color: #fff; }
/* Enamad trust seal, under the logo.
   Sized with max-* rather than a fixed size so whatever the seal's image actually
   returns is respected up to a cap — the endpoint chooses its own dimensions and a
   hard height would distort a wide or square seal. `display: block` matters too: it
   is an inline-level <a>, so its line box would otherwise add the font's descender
   space under the logo.

   Deliberately NO background, padding or border on the image. It comes from a
   third-party host that answers 403 to anything outside Iran, so it WILL sometimes
   fail to load — and a decorative white slab is a worse sight than nothing. With
   `alt=""` a failed image collapses to zero size, so the footer simply looks the
   way it did before the seal was added. */
.site-footer .enamad-seal { display: inline-block; margin-top: 16px; line-height: 0; }
.site-footer .enamad-seal img {
  display: block; width: auto; height: auto; max-width: 170px; max-height: 96px;
}
.footer-bottom { border-top: 1px solid #1e293b; padding-top: 22px; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 12px; font-size: 14px; color: #64748b; }

/* ---- Footer "Follow us" row (templates/_footer_social.html) ---------------
   The invite to join OUR channels, sitting between the link columns and the
   copyright divider. Loaded by all four public pages, because every one of them
   pulls this same stylesheet (landing.css) — see the note in that template.

   WHY A CHIP. The four platform logos have different natural shapes: Telegram
   and Bale are opaque coloured discs, Eitaa a rounded square, Rubika a bright
   cube on a light ground. Dropped straight onto the navy footer at one size they
   read as four unmatched images. The chip is a soft translucent disc that gives
   every logo the same footprint, so the row reads as ONE set — and it stays
   quiet enough that it does not compete with the logo above it.

   `.site-footer .footer-social-list` is written with BOTH classes on purpose:
   `.site-footer ul` (line ~1036) sets `flex-direction: column` at a higher
   specificity (0,1,1) than a lone `.footer-social-list` (0,1,0), so the row
   would silently stack vertically without it. Same trap as the `.sp-items` /
   `.feature-card-action` bugs. */
.footer-social { text-align: center; margin-bottom: 30px; }
.footer-social-label { color: #fff; font-size: 15px; font-weight: 600; margin: 0; }
.footer-social-sub { color: #94a3b8; font-size: 13.5px; margin: 6px 0 0; }
.site-footer .footer-social-list {
  list-style: none; margin: 16px 0 0; padding: 0;
  display: flex; flex-direction: row; flex-wrap: wrap;
  justify-content: center; align-items: center; gap: 12px;
}
.site-footer .footer-social-chip {
  width: 40px; height: 40px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: rgba(255, 255, 255, .08);
  border: 1px solid rgba(255, 255, 255, .18);
  text-decoration: none;
  transition: background .18s ease, border-color .18s ease, transform .18s ease;
}
.site-footer .footer-social-chip:hover {
  background: rgba(255, 255, 255, .16);
  border-color: rgba(255, 255, 255, .34);
  transform: translateY(-2px);
}
/* A visible focus ring is the whole keyboard affordance here: the chip has no
   text label of its own, so without this a tab-through is invisible. */
.site-footer .footer-social-chip:focus-visible {
  outline: 2px solid #fff; outline-offset: 2px;
}
/* `object-fit: contain` because the logos are not all square: it letterboxes
   rather than stretching a non-square mark into a distorted one. */
.site-footer .footer-social-chip img {
  display: block; width: 24px; height: 24px; object-fit: contain;
}

/* ---- Contact sales popup (shared landing + /pricing) --------------------- */
.cs-contact-overlay {
  position: fixed; inset: 0; z-index: 200;
  background: rgba(15, 23, 42, .55);
  display: flex; align-items: center; justify-content: center; padding: 20px;
  backdrop-filter: blur(2px);
}
.cs-contact-card {
  background: #fff; border-radius: var(--r-lg); padding: 26px 24px;
  width: 100%; max-width: 440px; box-shadow: var(--shadow-lg);
  font-family: inherit;
}
.cs-contact-close {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; flex: none; border: none; cursor: pointer;
  font-size: 15px; line-height: 1; font-weight: 700;
  color: #fff; background: #ef4444; border-radius: 50%; padding: 0;
  transition: background .15s, transform .15s;
}
.cs-contact-close:hover { background: #dc2626; transform: scale(1.08); }

/* ---- i18n / language toggle + RTL (public pages) -------------------------- */
.i18n-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 34px; height: 34px; padding: 0 8px; border: 1px solid var(--border-2);
  border-radius: 999px; background: #fff; cursor: pointer;
  font-size: 14px; font-weight: 700; color: var(--text-2);
  transition: all .15s; line-height: 1;
}
.i18n-toggle:hover { border-color: var(--brand-400); color: var(--brand-600); box-shadow: var(--shadow-sm); }

body.is-fa { letter-spacing: 0 !important; }

/* Visually hidden but still read by screen readers and crawlers. Used to give
   the social-proof stats block and the pricing comparison table a real section
   heading without adding visible chrome. NOTE: this must remain in the DOM —
   display:none would remove the heading from the accessibility tree and make it
   worthless for the document outline. */
.sr-only {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
html[dir="rtl"] body { text-align: right; }
[dir="rtl"] .site-header .container, [dir="rtl"] .hero-cta,
[dir="rtl"] .footer-grid, [dir="rtl"] .pricing-grid {
  text-align: right;
}
[dir="rtl"] .nav-links { direction: rtl; }
[dir="rtl"] .price-card .price-amt span { margin-right: 2px; }

@media (max-width: 820px) {
  .site-footer .footer-grid { grid-template-columns: 1fr 1fr; }
  .nav-links { display: none; }
}
@media (max-width: 520px) {
  .site-footer .footer-grid { grid-template-columns: 1fr; }
  /* Reserve the artwork's OWN height under the copy. The artwork is absolutely
     positioned at the bottom of the section, so with the old 40px of padding the
     Azadi tower stood BEHIND the buttons and the note pill — the copy sat on top of
     the landmark and its top was hidden behind "Start for Free". The height is the
     section width x 286/374, i.e. 76.5vw, so the padding is expressed in the same
     units instead of a magic number that only holds at one phone width. */
  .hero { padding: 60px 0 calc(76.5vw + var(--hero-glint) + 10px); --hero-glint: 24px; }
  /* On phones the badge sentence can't fit a pill's natural width, so stop it
     from squeezing into a tall blob: let it use the full column and step the
     text down one size. */
  .hero-badge { max-width: 100%; font-size: 13.5px; padding: 9px 14px; }
  .hero-logo { height: 42px; }
  /* On a phone the hero is almost entirely copy, so the fists are dropped and the
     artwork becomes the AZADI tower instead of the skyline (see the <picture> in
     templates/landing.html): at 1.3:1 this width fills ~300px of artwork where the
     2.7:1 skyline gave 143px. The box is driven by an explicit aspect-ratio so it is
     the right size BEFORE the file lands — the <img> still carries the skyline's
     852x312 attributes for the desktop case, which would otherwise be a layout shift
     here. Opacity is raised from the skyline's .5: this artwork is a solid flag-red
     poster, and half strength would leave it washed-out pink behind the copy. */
  .hero-landscape {
    aspect-ratio: 374 / 286; opacity: .78;
    -webkit-mask-image: none; mask-image: none;
  }
  .hero-hands { display: none; }
  /* No mirror on phones: the faint reflection under the skyline is a horizon trick,
     and an upside-down landmark just reads as a mistake. `--hero-glint` shrinks with
     it, since it exists only to reserve the strip the reflection sat in. */
  .hero-reflection { display: none; }
  .hero { --hero-glint: 24px; }
  /* Four stat tiles no longer fit one row, and flex-wrapping them stacked them
     into a ~400px column (the desktop gap is 72px). A 2x2 grid keeps the row
     readable without eating a whole screen.
     NOTE: the grid goes on `.sp-items` (the counters' own row), NOT on
     `.container` — the container is the column that also holds the heading and
     the subtitle, so grid-ing it put the heading in a cell. */
  .social-proof { padding: 34px 0; }
  .social-proof .sp-items { display: grid; grid-template-columns: 1fr 1fr; gap: 22px 14px; }
  .sp-item .sp-num { font-size: 48px; }
  /* No rules in the wrapped layout — they would sit in the middle of the grid. */
  .sp-item + .sp-item::before { display: none; }
}
/* The skyline is shown at its natural ratio, so on a very wide screen it is
   taller than the hero's content — and `max-height: 100%` would then crop the
   artwork from the TOP, which is exactly where the tall tower's top is. Growing
   the section's bottom padding gives the artwork the room it needs instead of
   clipping it. */
@media (min-width: 2000px) {
  .hero { padding-bottom: calc(11vw + var(--hero-glint)); }
}

/* ---------------------------------------------------------------------------
   Is It AI? — the landing spotlight and its guest pop-up.

   The spotlight is the PUBLIC door to the /is-it-ai tool: that page is
   login-gated, so this card ("Try it") opens the SAME tool in a dialog where a
   visitor with no account may check a few images (IS_IT_AI_GUEST_LIMIT in
   app.py). The dialog borrows the cards' gradient-border language (like
   .sp-banner) so it reads as part of this page, and it reuses the tool's own
   .iia-* markup + stylesheet (css/is_it_ai.css) rather than re-implementing the
   drop zone, the preview and the result tables.
   --------------------------------------------------------------------------- */
.iia-promo { display: flex; justify-content: center; }
.iia-promo-card {
  box-sizing: border-box; width: 100%; max-width: 900px;
  display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center;
  gap: 28px; padding: 36px 40px; border-radius: var(--r-lg);
  background: linear-gradient(#fff, #fff) padding-box,
              linear-gradient(135deg, var(--brand-500), var(--accent-500)) border-box;
  border: 2px solid transparent;
  box-shadow: 0 12px 30px rgba(79,70,229,.16), 0 2px 6px rgba(15,23,42,.05);
  text-align: start;
}
.iia-promo-art {
  width: 84px; height: 84px; border-radius: 22px;
  display: flex; align-items: center; justify-content: center;
  font-size: 44px; line-height: 1; background: var(--brand-50);
}
.iia-promo-copy { min-width: 0; }
.iia-promo-title { margin: 0; font-size: clamp(24px, 2.6vw, 32px); letter-spacing: -0.01em; color: var(--text); }
.iia-promo-q { margin: 6px 0 0; font-weight: 700; font-size: clamp(17px, 1.6vw, 20px); color: var(--brand-600); }
.iia-promo-body { margin: 8px 0 0; color: var(--text-2); font-size: 16px; line-height: 1.6; max-width: 60ch; }
.iia-promo-cta {
  margin-top: 16px; display: inline-flex; align-items: center; gap: 9px;
  padding: 12px 22px; border: 0; cursor: pointer; border-radius: var(--r-pill);
  box-sizing: border-box; max-width: 100%;
  background: linear-gradient(120deg, var(--brand-600), var(--accent-500));
  color: #fff; font-weight: 700; font-size: 15px; font-family: inherit;
  box-shadow: 0 8px 20px rgba(99,102,241,.30);
  transition: transform .18s ease, box-shadow .18s ease;
}
.iia-promo-cta:hover { transform: translateY(-2px); box-shadow: 0 12px 26px rgba(99,102,241,.38); }
.iia-promo-cta:focus-visible { outline: 2px solid var(--brand-700); outline-offset: 2px; }
/* The arrow is an inline SVG (see the template): the "→" glyph is not
   Bidi_Mirrored, so in the Farsi layout it would point the wrong way. */
.iia-promo-arrow { flex: none; transition: transform .18s ease; }
.iia-promo-cta:hover .iia-promo-arrow { transform: translateX(3px); }
[dir="rtl"] .iia-promo-arrow { transform: scaleX(-1); }
[dir="rtl"] .iia-promo-cta:hover .iia-promo-arrow { transform: scaleX(-1) translateX(3px); }

/* ---- the guest pop-up ---------------------------------------------------- */
.iia-modal-overlay {
  position: fixed; inset: 0; z-index: 70; display: flex;
  align-items: flex-start; justify-content: center;
  padding: 20px; overflow: auto; background: rgba(15, 23, 42, .74);
}
.iia-modal-overlay[hidden] { display: none; }
.iia-modal {
  width: 100%; max-width: 720px; margin: auto 0; background: #fff;
  border-radius: 18px; padding: 18px 20px 14px;
  box-shadow: 0 24px 60px rgba(2, 6, 23, .45);
}
.iia-modal-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 14px; margin-bottom: 10px; }
.iia-modal-title { margin: 0; font-size: 18px; font-weight: 800; color: var(--text); }
.iia-modal-sub { margin: 4px 0 0; font-size: 13.5px; color: var(--text-2); }
.iia-modal-close {
  flex: none; border: 0; cursor: pointer; font-size: 22px; line-height: 1;
  padding: 4px 12px; border-radius: 12px; background: var(--surface, #f8fafc);
  color: var(--text-2);
}
.iia-modal-close:hover { background: var(--brand-50); color: var(--brand-700); }
.iia-guest-note {
  margin: 0 0 14px; font-size: 13px; font-weight: 600; color: var(--brand-600);
  background: var(--brand-50); border-radius: var(--r-md); padding: 9px 13px;
}
.iia-guest-note[hidden] { display: none; }
/* The sign-up CTA shown once the guest allowance is spent. Amber, like the
   "Important" strip on the tool page: a nudge, not an error. */
.iia-signup {
  display: flex; flex-wrap: wrap; align-items: center; gap: 12px; justify-content: space-between;
  background: #fffbeb; border: 1px solid #fde68a; border-radius: var(--r-md);
  padding: 14px 16px; margin-bottom: 18px;
}
.iia-signup[hidden] { display: none; }
.iia-signup-text { margin: 0; color: #92400e; font-size: .9rem; font-weight: 600; line-height: 1.6; }
.iia-signup-btn { text-decoration: none; flex: none; }
.iia-modal-foot {
  text-align: center; color: var(--text-3); font-size: .76rem;
  border-top: 1px solid var(--border); padding-top: 14px; margin: 16px 0 0;
}
body.iia-modal-open { overflow: hidden; }

@media (max-width: 620px) {
  .iia-promo-card { grid-template-columns: 1fr; text-align: center; padding: 28px 22px; justify-items: center; }
  .iia-promo-art { width: 68px; height: 68px; font-size: 36px; border-radius: 18px; }
  .iia-promo-cta { width: 100%; justify-content: center; }
  .iia-modal { padding: 14px 14px 10px; border-radius: 14px; }
  .iia-modal-title { font-size: 16px; }
  .iia-signup { flex-direction: column; align-items: stretch; }
  .iia-signup-btn { text-align: center; }
}
