/* MyKid site — b-near.me's landing grammar.
 *
 * The shapes, scales and names are that project's landing.css: a 1240px page
 * with a 34px inset, a navbar under a hairline, a hero of copy beside the
 * mark, a chip over an h1 set at weight 200 with one word lifted to 500 in the
 * accent, a muted lede, pill buttons, and rounded cards that lift on hover.
 *
 * Where it differs it is because MyKid is a different product: no orbit of
 * reach-nodes — b-near's circle has members, this one has a child — and the
 * sections below the hero are this app's four things rather than that app's
 * three cards.
 */

/* ── Base ─────────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--bn-font);
  font-size: var(--fs-body);
  font-weight: 400;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-wrap: pretty;
}

h1, h2, h3 { margin: 0; font-weight: 500; line-height: 1.2; }
p { margin: 0; }
img, svg { display: block; max-width: 100%; }
a { color: var(--accent-deep); text-underline-offset: 3px; }

:focus { outline: none; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 4px; }
::selection { background: var(--color-accent-200); }

/* `clip`, with `hidden` above it only as a fallback for browsers without it.
   They are not interchangeable: `overflow-x: hidden` silently makes the element
   a scroll container, and `position: sticky` inside a scroll container sticks
   to that container rather than to the viewport — which would quietly un-pin
   the "Como funciona" panel. `clip` clips without any of that.
   It is here because the hero's aura reaches past the page's own width by
   design, and 18px of horizontal scrollbar is not a design. */
html, body { overflow-x: hidden; overflow-x: clip; }
html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { animation: none !important; }
}

.shell { min-height: 100vh; display: flex; flex-direction: column; }

.wrap {
  max-width: var(--page);
  margin: 0 auto;
  width: 100%;
  padding-left: var(--inset);
  padding-right: var(--inset);
}

/* ── Navbar ───────────────────────────────────────────────────────────── */
.navbar { background: var(--bg); border-bottom: 1px solid var(--line); }
.nav { display: flex; align-items: center; gap: var(--s-4); height: 66px; }
.brand { display: flex; align-items: center; gap: 10px; color: var(--text); text-decoration: none; margin-right: auto; }
.brand img { width: 30px; height: 30px; border-radius: 9px; }
.wordmark { font-family: var(--bn-wordmark); font-size: 20px; font-weight: 400; line-height: 1; }
.wordmark b { font-weight: 700; }

.nav-link { color: var(--text-dim); text-decoration: none; font-size: var(--fs-body-sm); white-space: nowrap; }
.nav-link:hover { color: var(--accent-deep); }
/* The language picker, as on b-near.me (2026-11-09): a pill with the current
   language that opens a small menu. Same tokens as b-near's, since the site
   shares its design system; the items are links to the other page. */
.lang-picker { position: relative; display: flex; align-items: center; }
.lang-trigger {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 7px 12px; min-height: 32px;
  border-radius: var(--r-pill); border: 1px solid var(--bn-line); background: var(--bn-card);
  color: var(--color-accent-700); font-family: inherit; font-size: var(--fs-cap); font-weight: 500;
  letter-spacing: 0.04em; line-height: 1; cursor: pointer; transition: border-color .2s ease;
}
.lang-trigger:hover, .lang-picker[data-open="true"] .lang-trigger { border-color: var(--color-accent-300); }
.lang-caret { width: 10px; height: 10px; transition: transform .2s ease; }
.lang-picker[data-open="true"] .lang-caret { transform: rotate(180deg); }
.lang-menu {
  position: absolute; top: calc(100% + 6px); right: 0; z-index: 30;
  display: none; flex-direction: column; align-items: stretch; gap: 2px;
  padding: 4px; min-width: 88px;
  border-radius: var(--r-tile); border: 1px solid var(--bn-line); background: var(--bn-card);
  box-shadow: var(--shadow-card);
}
.lang-picker[data-open="true"] .lang-menu { display: flex; }
.lang-menu a {
  display: flex; align-items: center;
  padding: 9px 14px; min-height: 38px;
  border-radius: var(--r-pill); color: var(--bn-muted); text-decoration: none;
  font-size: var(--fs-cap); font-weight: 500; letter-spacing: 0.04em; white-space: nowrap;
  transition: background .2s ease, color .2s ease;
}
.lang-menu a:hover { background: var(--color-accent-100); color: var(--color-accent-700); }
.lang-menu a[aria-current="page"] { background: var(--accent-fill); color: #fff; }
@media (max-width: 440px) { .lang-trigger { padding: 6px 9px; gap: 4px; } .lang-caret { width: 9px; height: 9px; } }
@media (max-width: 620px) { .nav-link { display: none; } }

/* ── Pills ────────────────────────────────────────────────────────────── */
.pill-cta {
  display: inline-flex; align-items: center; justify-content: center;
  padding: 12px 22px; border: 0; border-radius: var(--r-pill);
  background: var(--accent-fill); color: var(--on-accent);
  font-family: inherit; font-size: var(--fs-body-sm); font-weight: 600;
  text-decoration: none; cursor: pointer;
  box-shadow: var(--shadow-accent);
  transition: transform .2s var(--ease-lift), box-shadow .2s var(--ease-lift);
}
.pill-cta:hover { transform: translateY(-2px); box-shadow: var(--shadow-accent-hi); }
.pill-cta-lg { padding: 15px 30px; font-size: var(--fs-body); }

.pill-quiet {
  display: inline-flex; align-items: center; justify-content: center;
  padding: 12px 22px; border-radius: var(--r-pill);
  border: 1px solid var(--line); background: var(--card); color: var(--text);
  font-size: var(--fs-body-sm); font-weight: 500; text-decoration: none;
  transition: transform .2s var(--ease-lift), border-color .2s ease;
}
.pill-quiet:hover { transform: translateY(-2px); border-color: var(--color-accent-300); }
.pill-quiet-lg { padding: 15px 30px; font-size: var(--fs-body); }

.nav .pill-cta { padding: 9px 18px; box-shadow: none; }
.nav .pill-cta:hover { box-shadow: var(--shadow-accent); }

/* ── Hero ─────────────────────────────────────────────────────────────── */
.hero {
  flex: 1;
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  align-items: center;
  gap: clamp(48px, 6vw, 110px);
  /* Vertical longhand, never the shorthand. `.hero` is `class="wrap hero"`,
     and a `padding: x 0 y` here has the same specificity as `.wrap`'s
     padding-left/right and comes later in the file, so it silently set the
     page's side gutter to zero — on every width, for as long as the site has
     existed. It looked like a mobile problem because that is where a missing
     16px shows; raising --inset did nothing, because this was overriding it.
     Anything carrying `.wrap` sets padding-top and padding-bottom only. */
  padding-top: var(--s-6);
  padding-bottom: var(--s-8);
}
.hero-copy { max-width: 660px; animation: bnRise .8s var(--ease-lift) both; }

/* The chip sits directly above the headline, on its left edge, the way
   b-near.me's does (Sérgio, 2026-11-09, with a screenshot of b-near's hero).
   It used to span both columns, centred on the page as a label on the whole
   hero; read beside b-near it looked detached from the line it introduces.
   On a desktop it keeps `.chip`'s own 26px under it. */
.hero .chip { align-self: flex-start; }
.chip {
  display: inline-flex; align-items: center; gap: 9px;
  padding: 7px 11px; border-radius: var(--r-pill);
  background: var(--color-accent-100); color: var(--color-accent-800);
  font-size: var(--fs-meta);
  margin-bottom: 26px;
}
/* A dot at each end, so the line is held rather than just started. */
.chip .dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--color-accent); display: block;
  animation: bnPulse 2.4s ease-in-out infinite;
}
/* Offset, so the two breathe against each other instead of blinking in
   unison — two dots on the same beat read as one thing flashing twice. */
.chip .dot:last-child { animation-delay: -1.2s; }

.hero h1 {
  font-size: clamp(38px, 5.4vw, 74px);
  font-weight: 200;
  line-height: 1.04;
  letter-spacing: -0.032em;
  margin-bottom: 22px;
  text-wrap: balance;
  overflow-wrap: break-word;
}
/* One word carries the accent and the weight. b-near lifts the word its whole
   product turns on; here it is the one thing the child cannot do yet. */
.hero h1 em { font-style: normal; font-weight: 500; color: var(--color-accent); }

.lede {
  font-size: var(--fs-lede); font-weight: 300; line-height: 1.62;
  color: var(--text-dim); max-width: 47ch; margin-bottom: 34px;
}

.hero-actions { display: flex; flex-wrap: wrap; gap: var(--s-3); align-items: center; }

/* The mark stands on its own ground, the way the icon does.
 *
 * A white head on a #fbfbfa page has no edge, and the aura that was here was a
 * workaround for that — light spilling outwards to fake one. The icon solved it
 * years earlier and better: it puts the white face on an indigo square. This is
 * that square at hero size.
 *
 * The gradient is the icon's own `diagonal(INDIGO_LIT, INDIGO_DEEP)` — lit
 * corner top-left, deep corner bottom-right, which is what 135deg means here —
 * so the panel and the app icon beside it in a phone's dock are the same
 * object. */
.orb-slot {
  position: relative;
  height: min(70vh, 560px);
  min-height: 380px;
  border-radius: 40px;
  background: linear-gradient(135deg, #7c86f0 0%, #383ca8 100%);
  box-shadow: 0 30px 60px -28px rgba(56, 60, 168, 0.55);
  overflow: hidden;
}

/* The icon's sheen: `s.sheen(20u, 16u, 34u, WHITE, 0.16)` in make-icons.js, a
   soft highlight off the lit corner. Its comment is the reason it exists at all
   and applies here too — a flat fill and a lit one read the same in a
   screenshot and differently on a screen. */
/* The mark's own box. It lives here rather than in the component, which sets
   only `display` — see the note in mykid-orb.js's connectedCallback. */
.orb-slot mykid-orb { position: absolute; inset: 0; }

.orb-glow {
  position: absolute;
  inset: 0;
  background: radial-gradient(46% 40% at 30% 24%, rgba(255, 255, 255, 0.18) 0%, transparent 70%);
  pointer-events: none;
}

/* Wider than a phone, the mark stands in its own light rather than on a panel.
 *
 * The indigo square is the phone treatment and stays there, where it is a
 * full-bleed band and the strongest thing on a small screen. On a laptop it
 * reads as one more card in a page of cards, and the mark is the one thing on
 * the page that should not be in a box.
 *
 * Which brings back the problem the panel was solving: a white head on a warm
 * #fbfbfa ground has no edge of its own. The aura is that edge, in three stops
 * — a tight bright core behind the face, a wider indigo body, and a violet
 * skirt that reaches past the orbit so the stars sit inside the light too.
 * It is stronger than the first version of it was, because the first version
 * was too faint to do the job it is here for.
 *
 * The slot has to stop clipping for any of it to show. */
@media (min-width: 621px) {
  .orb-slot {
    background: none;
    box-shadow: none;
    border-radius: 0;
    overflow: visible;
  }
  /* Every stop reaches zero *inside* every boundary, and that is the whole
     reason these numbers look the way they do.
     An ellipse written `R% S%` has its horizontal radius at R% of the box, so
     a stop that goes transparent at T% of that reaches R x T of the box width
     from the centre. The first version was 76% x 78% = 59% of the box — past
     the box's own half-width of 50%, so the aura was still 5.8 luminance units
     dark where the page's `overflow-x: clip` cut it, which is a straight
     vertical line about 2% deep down the side of the window. An eye catches a
     straight edge long before it catches a 2% change in a gradient.
     So each stop ends at 100% of its ellipse, and the widest ellipse is 42% of
     the box: ~297px from centre against the ~313px of room between the mark's
     centre and the page edge. Nothing is clipped by anything. The lost spread
     is paid back in the stops themselves, which are stronger. */
  .orb-glow {
    inset: -20% -16%;
    background:
      radial-gradient(19% 17% at 50% 46%, rgba(120, 132, 246, 0.80) 0%, transparent 100%),
      radial-gradient(30% 27% at 50% 48%, rgba(79, 91, 213, 0.50) 0%, transparent 100%),
      radial-gradient(42% 38% at 50% 50%, rgba(125, 91, 240, 0.26) 0%, transparent 100%);
  }
}

@keyframes bnRise { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
@keyframes bnPulse { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.35); opacity: .55; } }

/* ── Sections ─────────────────────────────────────────────────────────── */
/* Longhand for the same reason `.hero` uses it: `class="wrap section"`. */
.section { padding-top: var(--s-8); padding-bottom: var(--s-8); }
.section-head { max-width: 560px; margin-bottom: var(--s-6); }
.eyebrow {
  font-size: var(--fs-meta); font-weight: 600; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--accent-deep); margin-bottom: var(--s-2);
}
.section-head h2 { font-size: clamp(26px, 3vw, 38px); font-weight: 200; letter-spacing: -0.02em; line-height: 1.12; }
.section-head p { margin-top: var(--s-3); color: var(--text-dim); font-weight: 300; font-size: var(--fs-lede); }

/* ── Cards ────────────────────────────────────────────────────────────── */
.cards { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--s-4); }
.card {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-card-lg); padding: var(--s-6);
  transition: transform .25s var(--ease-lift), box-shadow .25s var(--ease-lift);
}
.card:hover { transform: translateY(-4px); box-shadow: var(--shadow-card); }
.card-sym {
  width: 44px; height: 44px; border-radius: var(--r-tile);
  background: var(--color-accent-100);
  display: grid; place-items: center; margin-bottom: var(--s-4);
}
.card-sym svg { width: 26px; height: 26px; }
.card h3 { font-size: var(--fs-h2); font-weight: 500; margin-bottom: 10px; }
.card p { font-size: var(--fs-body-sm); line-height: 1.65; color: var(--text-dim); }

/* ── Steps ────────────────────────────────────────────────────────────── */
/* ── Stats ────────────────────────────────────────────────────────────── */
.stats { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s-4); }
/* Each figure in a frame of its own (asked for 2026-11-09): loose numbers on
   the page ground read as decoration, framed they read as four facts. Same
   card as "O que faz", so the page has one kind of frame. */
.stat {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-card); padding: var(--s-5) var(--s-5) var(--s-6);
}
.stat-num { font-size: var(--fs-stat); font-weight: 200; color: var(--accent); line-height: 1.1; letter-spacing: -0.02em; }
.stat-label { font-size: var(--fs-meta); color: var(--text-dim); margin-top: var(--s-1); }

/* ── Closing band ─────────────────────────────────────────────────────── */
.close-band {
  background: var(--accent-fill); color: var(--on-accent);
  border-radius: var(--r-card-lg);
  padding: clamp(34px, 5vw, 62px);
  margin-bottom: var(--s-8);
}
.close-band h2 { font-size: clamp(26px, 3.4vw, 42px); font-weight: 200; letter-spacing: -0.024em; line-height: 1.12; }
.close-band p { margin-top: var(--s-4); font-weight: 300; font-size: var(--fs-lede); opacity: .92; max-width: 46ch; }
.close-band .pill-quiet { margin-top: var(--s-6); background: #fff; border-color: #fff; color: var(--accent-deep); }

/* ── Footer ───────────────────────────────────────────────────────────── */
.foot {
  border-top: 1px solid var(--line);
  padding: var(--s-6) 0;
  display: flex; flex-wrap: wrap; gap: var(--s-3) var(--s-4);
  align-items: center;
  font-size: var(--fs-meta); color: var(--text-dim);
}
.foot a { color: var(--text-dim); text-decoration: none; }
.foot a:hover { color: var(--accent-deep); }
.foot .spacer { margin-left: auto; }

/* ── Narrow ───────────────────────────────────────────────────────────── */
@media (max-width: 960px) {
  .hero { grid-template-columns: 1fr; padding-top: var(--s-4); gap: var(--s-5); }

  /* Stacked, the column is: headline, chip, mark — and then the lede and the
     buttons underneath. The three that matter are adjacent, which they cannot
     be while the headline, the lede and the buttons travel together as one
     block with the chip and the mark after it.
     `display: contents` is what separates them: `.hero-copy` stops producing a
     box and its three children become grid items in their own right, orderable
     one at a time. Nothing moves in the markup, so the document order a screen
     reader and a keyboard follow is untouched — there the chip still precedes
     the heading it labels, and the lede still follows it. */
  .hero-copy { display: contents; }
  /* Above the headline here too, as on b-near.me; centred, because the
     stacked hero is one centred column. As a grid item its own margin would
     land on top of the row gap (measured once at 16 above, 42 below), so the
     gap alone spaces it. */
  .hero .chip     { order: 1; margin-bottom: 0; justify-self: center; }
  .hero h1        { order: 2; margin-bottom: 0; }
  .orb-slot       { order: 3; }
  .hero .lede     { order: 4; margin-bottom: 0; }
  .hero-actions   { order: 5; }

  /* A box with `display: contents` has nothing to animate, so the rise moves
     to the three things that now have boxes of their own. */
  .hero h1, .hero .lede, .hero-actions { animation: bnRise .8s var(--ease-lift) both; }

  .orb-slot { height: 38vh; min-height: 260px; }
  .cards { grid-template-columns: 1fr; }
  .steps { grid-template-columns: 1fr; }
}

/* On a phone the mark was eating the screen.
 *
 * At 42vh plus the navbar and the hero's own padding, the first thing a visitor
 * saw was a face and the second thing was more face: the chip sat at the fold
 * and the headline — which is what the page has to say — was below it, with the
 * buttons off-screen entirely. Measured on a 393x852 phone.
 *
 * The mark still leads, because it is the best thing here and b-near's own
 * landing leads with its orb. It just stops being the whole first screen: at
 * 30vh capped to 250px, the chip, both lines of the headline and the first CTA
 * are above the fold on that phone, and the mark is still the largest single
 * object on it. */
@media (max-width: 620px) {
  .hero { padding-top: var(--s-2); padding-bottom: var(--s-6); gap: var(--s-4); }
  /* On a phone the ground is a band, not a card: square corners, and out
     through the page's gutter to both edges of the screen.
     A rounded rectangle this size on a narrow screen reads as a *tile* — one
     more card in a column of cards, and the smallest thing on the page that
     ought to be the largest. Edge to edge it is the surface the mark lives on.
     The negative margins are exactly the gutter `.wrap` pads by, which reaches
     the viewport because below 620px the page is nowhere near `--page` wide;
     the shadow goes with the corners, having nothing left to lift off. */
  .orb-slot {
    height: 30vh; min-height: 200px; max-height: 250px;
    border-radius: 0;
    margin-left: calc(-1 * var(--inset));
    margin-right: calc(-1 * var(--inset));
    box-shadow: none;
  }
  /* Well short of the screen edge. The camera fits the orbit to the element,
     so whatever width this is, the stars end up near its edges — and against a
     full-bleed band that means a star cut in half by the side of the phone,
     which reads as a bug rather than as a crop. 82% leaves them about 35px of
     air on each side. */
  .orb-slot mykid-orb { inset: 0 9%; }
  /* Sizes only. The bottom margins these used to carry are the stacked hero's
     business, not the breakpoint's: as grid items each one lands on top of the
     row gap and doubles it — the headline's 16 plus the gap's 16 put 32px under
     the headline against 16 everywhere else. The gap spaces them, and nothing
     else does. */
  /* Centred on a phone (asked for 2026-11-09): stacked, the chip and the mark
     both sit on the page's centre line, and a left-aligned headline between
     them was the one thing off-axis. text-wrap: balance keeps the two lines
     close to equal, so centring does not leave a stub. */
  .hero h1 { font-size: clamp(32px, 8.6vw, 44px); text-align: center; }
  .lede { font-size: 16.5px; }
  /* Full-width, stacked: two pills side by side at this width leaves each one
     too narrow to read and too close to the other to aim at. */
  .hero-actions { flex-direction: column; align-items: stretch; }
  .hero-actions .pill-cta, .hero-actions .pill-quiet { width: 100%; }
  .section { padding-top: var(--s-7); padding-bottom: var(--s-7); }
  .close-band { padding: 28px 22px; }
}
/* b-near.me narrows its page inset here and so does this, for the reason its
   own comment gives: the surfaces would otherwise agree on a desktop and
   disagree on a phone. Same breakpoint, same value — --s-4, 16px, read off
   the live stylesheet rather than guessed at.
   This held --s-5 for a while, on the argument that MyKid's hero puts a 3D
   object in the gutter's way and b-near's does not. True then, false now: the
   mark's ground is full-bleed on a phone, so the object is outside the gutter
   rather than in it, and nothing is left to pay 6px for. */
@media (max-width: 720px) {
  :root { --inset: var(--s-4); }
  .stats { grid-template-columns: repeat(2, 1fr); }
}

/* ── The concept page ──────────────────────────────────────────
 *
 * Rides on everything above for the nav, the page box and the footer, and adds
 * only what a page of prose needs. The measure is 68 characters and narrower
 * than the landing's on purpose: this is the one page somebody reads from top
 * to bottom, and past about 70 characters a line stops being read and starts
 * being work. b-near.me's own long-form pages are set the same way.
 */
.prose { padding-top: var(--s-6); padding-bottom: var(--s-8); }

.prose h1 {
  font-size: clamp(28px, 4vw, 44px); font-weight: 200;
  letter-spacing: -0.03em; line-height: 1.12;
  margin: 0 0 var(--s-4); max-width: 24ch; text-wrap: balance;
}
.prose-lede {
  max-width: 62ch; margin: 0 0 var(--s-8);
  font-size: var(--fs-lede); font-weight: 300; line-height: 1.6;
  color: var(--text-dim); text-wrap: pretty;
}
.prose-section { max-width: 68ch; margin-bottom: var(--s-7); }
/* Sentence case, and small. These are section headings inside an argument, not
   titles competing with the h1 — the source document writes them in capitals
   and capitals at this length are read slower, so the weight carries the job
   instead. */
.prose-section h2 {
  font-size: 17px; font-weight: 500; letter-spacing: -0.015em;
  color: var(--text); margin: 0 0 var(--s-2);
}
.prose-section p {
  margin: 0 0 var(--s-3);
  font-size: var(--fs-body); line-height: 1.7;
  color: var(--text-dim); text-wrap: pretty;
}
.prose-section p:last-child { margin-bottom: 0; }
/* The closing line is the one thing on the page that is not an argument, so it
   is set apart rather than louder. */
.prose-ask {
  max-width: 68ch; margin: var(--s-8) 0 0;
  padding-top: var(--s-5); border-top: 1px solid var(--line);
  font-size: var(--fs-body); line-height: 1.7; color: var(--text);
  text-wrap: pretty;
}

/* ── How it works: the steps, and a screen for each ───────────────────────
 *
 * The screens are drawn in HTML with the app's own symbols, not screenshotted.
 * A screenshot of an app that is still changing is a promise that goes stale
 * quietly and nobody notices for months; this can only be wrong in ways that
 * are visible on the page. `symbol-blocks.json` is generated from
 * `client/static/kid/symbol-svg.js`, so the pictures here are the same objects
 * the tablet renders — not a likeness of them.
 */
/* The band is a runway and the panel pins inside it.
 *
 * `.how` is taller than the window on purpose: that extra height is the scroll
 * the steps are read from. 240vh over three steps leaves each about 45vh of
 * travel, which is a comfortable thumb's worth — b-near uses 300vh over four,
 * the same share each.
 *
 * Without the runway the panel has nothing to be sticky in and scrolls away
 * with the page, which is what the first version of this section did. */
.how { position: relative; }
.how-panel {
  position: sticky; top: 0;
  /* svh, with vh above it as the fallback. Plain vh includes the collapsing
     URL bar and makes the panel jump as it hides; dvh re-pins on every bar
     movement, which is worse. Not dvh. */
  min-height: 100vh;
  min-height: 100svh;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 340px);
  gap: clamp(32px, 5vw, 72px);
  /* Both columns centred on each other, which is the one thing that makes the
     pair read as one object rather than as a column of text beside a picture.
     Measured against b-near's own page: its two centres are 9px apart. Here
     they were 117px, because the device spanned the rows and centred while the
     heading and the rail stacked from the top of theirs. */
  align-items: center;
  padding: var(--s-6) 0;
}
.how-copy { display: grid; gap: var(--s-5); }
.how-panel .section-head { margin-bottom: 0; }
/* The eyebrow runs a rule out to the end of its column — it is a label on a
   section, and the line is what makes it read as one rather than as a stray
   line of small caps. */
.how-panel .eyebrow { display: flex; align-items: center; gap: var(--s-4); }
.how-panel .eyebrow::after {
  content: ''; flex: 1; height: 1px; background: var(--line);
}
/* Tall enough for its tallest step, always. The bodies are different lengths,
   so without this the column's centre moves every time a step opens and the
   heading slides up and down the page under a thumb that is only scrolling.
   The number is measured at runtime rather than written here, because it
   depends on the font, the width and the language. */
.how-rail { min-height: var(--rail-h, auto); }
/* (N - 1) x 100vh: each step gets a screenful of scrolling and the last one
   needs no runway after it. Four steps since 2026-11-09, so 300vh. */
.how-runway { height: 300vh; }

/* The rail is one vertical line with the open step marked on it, not a stack
   of horizontal rules. Rules box each step into its own row and give the four
   of them equal weight; a line down the side belongs to the rail as a whole and
   lets one segment of it say which step you are on. b-near's does the same, and
   this is read off its page rather than guessed at.

   A disclosure, not a tablist: the body belongs under the step it explains,
   where somebody reading that step already is. */
.how-item { border-left: 2px solid var(--line); padding-left: var(--s-5); }
.how-item[data-open="true"] { border-left-color: var(--accent); }
.how-step {
  width: 100%; display: flex; align-items: baseline; gap: var(--s-4);
  padding: var(--s-4) 0 var(--s-2); border: 0; background: none; cursor: pointer;
  font-family: inherit; text-align: left; color: var(--text-dim);
  transition: color .2s ease;
}
.how-item[data-open="true"] .how-step { color: var(--text); }
.how-n {
  font-size: var(--fs-meta); font-weight: 600; letter-spacing: 0.06em;
  color: var(--color-accent-400); font-variant-numeric: tabular-nums;
}
.how-item[data-open="true"] .how-n { color: var(--accent); }
.how-t { font-size: var(--fs-h2); font-weight: 500; letter-spacing: -0.015em; }
.how-b {
  margin: 0; max-width: 54ch;
  font-size: var(--fs-body-sm); line-height: 1.7; color: var(--text-dim);
  /* Closed is height 0, not display:none, so the open one can be animated and
     the closed ones stay in the accessibility tree behind `aria-expanded`. */
  display: grid; grid-template-rows: 0fr;
  transition: grid-template-rows .32s var(--ease-lift), padding-bottom .32s var(--ease-lift);
  padding-bottom: 0;
}
/* The collapse is `grid-template-rows: 0fr -> 1fr`, which is the only way to
   animate to a content-sized height. It needs a real element inside the row to
   clip — with the text sitting directly in the <p> there is nothing to give
   `overflow: hidden` to, and every body stayed open with no error anywhere. */
.how-b > span { display: block; overflow: hidden; min-height: 0; }
.how-item[data-open="true"] .how-b { grid-template-rows: 1fr; padding-bottom: var(--s-4); }

.how-stage { display: grid; justify-items: center; gap: var(--s-4); min-height: 0; }

/* ── The device ─────────────────────────────────────────────
 *
 * Everything inside the screen is sized in `em` off one font-size, and that
 * font-size is a share of the device's own width. The device is not one size:
 * it is 300px beside the steps on a laptop and as little as 166px on a short
 * phone, where it is sized by height so the heading and caption still fit. In
 * fixed pixels the card's contents stopped fitting at the small end and the
 * time pushed out through the bezel — "the app images are getting out from the
 * phone limit", measured at 9.2px past the frame at 360x640.
 *
 * One container query and one `em` scale removes the whole class of bug: the
 * screen is the same picture at every size rather than the same pixels.
 */
.phone {
  width: 100%; max-width: 300px; aspect-ratio: 300 / 600;
  container-type: inline-size;
  border-radius: 14.7%/7.3%; padding: 3%;
  background: linear-gradient(160deg, #2a2d55 0%, #14162e 100%);
  box-shadow: 0 34px 60px -30px rgba(20, 22, 60, .6), 0 0 0 1px rgba(255,255,255,.06) inset;
}
.phone-face {
  position: relative; height: 100%; border-radius: 12%/6%; overflow: hidden;
  /* The child's own ground, from kid/app.css's default theme. */
  background: linear-gradient(170deg, #241a2c 0%, #1b1320 58%, #2b1c2a 100%);
  /* em, not %, and that is not fussiness: percentage padding resolves against
     the containing block's WIDTH on every side, while `top` and `height`
     resolve against its HEIGHT. Mixed, the notch and the screen's top padding
     drift apart as the device changes shape — the notch sat on top of the week
     strip. One basis for both, and the basis is the font-size that already
     tracks the device's width. */
  padding: 2.4em 1.1em 1.4em;
  font-size: clamp(8px, 5.6cqw, 13.5px);
}
.phone-notch {
  position: absolute; top: .55em; left: 50%; translate: -50% 0;
  width: 21%; height: .95em; border-radius: 999px; background: #0d0a12;
}
.phone-home {
  position: absolute; bottom: .4em; left: 50%; translate: -50% 0;
  width: 28%; height: .3em; border-radius: 999px; background: rgba(255,255,255,.26);
}
.phone-screens { position: relative; height: 100%; overflow: hidden; }

/* Only the inner screen moves; the frame stays put. That is what makes it read
   as a device showing different things rather than as a carousel.
   `visibility`, never `display`: `display: none` destroys the layout being
   animated back into, and hidden keeps them out of the accessibility tree all
   the same, so a reader does not meet all three at once. */
.ps {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; gap: .74em;
  opacity: 0; visibility: hidden; translate: 0 0;
  transition: translate .5s cubic-bezier(.4, 0, .2, 1), opacity .4s ease;
}
.ps.is-live { opacity: 1; visibility: visible; translate: 0 0; }
.ps.from-right { translate: 100% 0; }
.ps.from-left { translate: -100% 0; }
.ps.to-left { visibility: visible; opacity: 0; translate: -100% 0; }
.ps.to-right { visibility: visible; opacity: 0; translate: 100% 0; }
.ps.no-anim { transition: none; }

.ps-head { margin: 0 .15em .15em; font-size: 1em; font-weight: 600; line-height: 1.35; color: #fffdf9; }
.ps-note { margin: auto .15em 0; font-size: .8em; line-height: 1.5; color: rgba(255,253,249,.62); }

/* 01 · who to talk to */
.ps-people { display: grid; gap: .74em; }
.ps-person {
  display: flex; align-items: center; gap: .8em;
  padding: .8em .88em; border-radius: 1.33em;
  background: #fffdf9; color: #2a2030;
  font-size: 1.04em; font-weight: 600;
}
.ps-sym { width: 2.5em; height: 2.5em; flex: none; display: block; }
.ps-sym svg { width: 100%; height: 100%; display: block; }

/* 02 · the pairing code */
.ps-code { display: grid; grid-template-columns: repeat(6, 1fr); gap: .37em; }
.ps-code span {
  aspect-ratio: 3 / 4; display: grid; place-items: center;
  border-radius: .74em; background: rgba(255,253,249,.12);
  color: #fffdf9; font-size: 1.26em; font-weight: 700;
}

/* 03 · the day */
.ps-week { display: flex; gap: .3em; padding: 0 .15em .3em; font-size: .78em; color: rgba(255,253,249,.5); }
.ps-week span { flex: 1; text-align: center; }
.ps-week span.is-today { color: #fffdf9; font-weight: 700; }
.ps-card {
  display: flex; align-items: center; gap: .74em;
  padding: .67em .82em; border-radius: 1.19em;
  background: #fffdf9; color: #2a2030;
}
.ps-card-t { font-size: 1em; font-weight: 600; margin-right: auto; }
.ps-time { font-size: .89em; color: #6b6172; font-variant-numeric: tabular-nums; }
/* A request the grown-up has not answered yet is drawn faded, the way both
   calendars in the app draw one. It is not a different card. */
.ps-card.is-wish { opacity: .46; }
.ps-wish { font-size: .78em; color: #6b6172; font-style: italic; }
.ps-stars { display: flex; align-items: center; gap: .52em; margin-top: .15em; padding: 0 .22em; font-size: .82em; color: rgba(255,253,249,.72); }
.ps-sym-sm { width: 1.6em; height: 1.6em; }
.ps-call {
  margin-top: auto; padding: 1.04em; border-radius: 1.48em;
  background: #1f9d55; color: #fff;
  text-align: center; font-size: 1.11em; font-weight: 700; letter-spacing: .06em;
  box-shadow: 0 10px 22px -12px rgba(31, 157, 85, .9);
}

/* 02 · the games */
.ps-budget { display: flex; align-items: center; gap: .6em; padding: 0 .15em .15em; }
.ps-budget-bar { flex: 1; height: .45em; border-radius: 999px; background: rgba(255,253,249,.18); overflow: hidden; }
.ps-budget-bar i { display: block; width: 38%; height: 100%; border-radius: 999px; background: #e8743c; }
.ps-budget-t { font-size: .78em; color: rgba(255,253,249,.72); }
.ps-tiles { display: grid; grid-template-columns: 1fr 1fr; gap: .6em; }
.ps-tile {
  display: grid; justify-items: center; gap: .37em;
  padding: .96em .44em; border-radius: 1.19em;
  background: #fffdf9; color: #2a2030;
  font-size: .85em; font-weight: 600; text-align: center;
}
.ps-tile-n {
  width: 2.6em; height: 2.6em; border-radius: .87em;
  display: grid; place-items: center;
  background: #efe6f2; color: #7d5bf0; font-size: 1em; font-weight: 700;
}
/* A game whose time is gone for today. The app closes it rather than hiding
   it, so the child can see it is there and that it will come back. */
.ps-tile.is-off { opacity: .42; }
/* The games screen holds both groups, so its tiles are shorter. */
.ps[data-screen="2"] { gap: .55em; }
.ps[data-screen="2"] .ps-tile { padding: .6em .44em; gap: .25em; }
.ps[data-screen="2"] .ps-tile-n { width: 2.1em; height: 2.1em; }
/* Games for two in the grown-ups' green, so "with mum or dad" reads at a glance. */
.ps-tile.is-duo .ps-tile-n { background: #e3f4ea; color: #1f9d55; }
.ps-sub { margin: .2em .15em 0; font-size: .74em; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: rgba(255,253,249,.6); }
/* The pairing screen's button is indigo, the child app's colour: it is the
   tablet's own first screen, before the family's green exists on it. */
.ps-call.ps-go { background: #4f5bd5; box-shadow: 0 10px 22px -12px rgba(79, 91, 213, .9); }
/* The pairing screen's note sits under the code, not at the foot. */
.ps-note-top { margin-top: .4em; }
/* Write is the second of the child's two buttons: the same shape as Call,
   quieter, so Call stays the one the eye finds. */
.ps-call + .ps-write {
  margin-top: .6em; background: rgba(255,253,249,.12); color: #fffdf9; box-shadow: none;
}

.how-screen-label {
  margin: 0; font-size: var(--fs-cap); font-weight: 500;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-dim);
}
/* Under the device, the step again — but only where the rail is not there to
   say it. Side by side they are the same words twice. */
.how-cap { display: none; justify-items: center; gap: 4px; max-width: 36ch; text-align: center; }
.how-cap-h { margin: 0; display: flex; align-items: baseline; gap: 8px; }
.how-cap-n {
  font-size: var(--fs-meta); font-weight: 600; letter-spacing: .06em;
  color: var(--accent); font-variant-numeric: tabular-nums;
}
.how-cap-t { font-size: var(--fs-h3); font-weight: 500; color: var(--text); }
.how-cap-b { margin: 0; font-size: var(--fs-meta); line-height: 1.6; color: var(--text-dim); text-wrap: pretty; }


@media (max-width: 900px) {
  /* The rail goes: the caption is the step here, and the phone is what there
     is room for. The runway stays, so the scroll still drives the screens. */
  .how-runway { height: 200vh; }
  /* One column: the heading on top, the device under it, the caption under
     that — and all three have to fit a screen at once, which is what the
     device's height is derived from rather than guessed at. */
  .how-panel {
    grid-template-columns: 1fr;
    grid-template-areas: "head" "stage";
    grid-template-rows: auto 1fr;
    gap: var(--s-4);
  }
  .how-rail { display: none; }
  .how-cap { display: grid; }
  /* The phone leads on a narrow screen: the picture is the reason to read the
     steps, and under them it is below the fold. Smaller, too — at its full
     300px it is 600px tall, which is most of a phone screen spent before the
     first word of the first step. */
  /* Still sticky on a phone, and this is where it earns its keep: the device
     is above the steps here, so without it every tap on a step changes a
     screen that has already scrolled off the top. */
  /* Sized by HEIGHT here, not width. The heading above it and the caption below
     it are the point of the section; a device sized by width takes whatever it
     likes of a short screen and pushes the caption off the bottom. The aspect
     ratio gives the width back. */
  .phone { width: auto; height: min(52svh, 430px); max-width: none; }
}

@media (prefers-reduced-motion: reduce) {
  .how-b { transition: none; }
  /* The screens still change with the scroll — that is the section, not an
     effect on it. They stop travelling to get there. */
  .ps { transition: none; translate: none; }
}

/* The setup used to be a line here, demoted as "not what somebody deciding
   came to look at". Since 2026-11-09 it is step 01 of the rail instead: the
   section is called "how it works", and how it starts is part of that. */

/* ── The hero's orbit ─────────────────────────────────────────────────────
 *
 * A crescent drawn wider than the mark's slot, with pills on it naming the
 * kinds of thing a child's day is made of. Its left side crosses the gap
 * between the mark and the copy and closes just short of the text, so the
 * headline and the buttons stand *inside* the circle rather than beside a
 * picture of one. Without it the hero is two pictures side by side with cold
 * page between them; a third column will not fit and widening the gap steals
 * from the headline.
 *
 * THE LAYOUT ENGINE IS ONE ROTATION AND NO TRIGONOMETRY. Each node is a
 * full-size square laid over the whole circle with its content pinned to the
 * left-middle — which is the 180° point of the inscribed circle. Rotating the
 * square therefore walks its label around the arc, and no radius is ever
 * written down or kept in step with the container's width. The label
 * counter-rotates by the same angle so it stays upright. A position is then
 * just `--a: 35deg`.
 */
.orbit {
  position: absolute; left: 50%; top: 50%;
  /* 120%, measured, not copied. The pattern this comes from uses 127% and says
     in as many words not to take that number on trust — so it was measured
     here, as clearance between the orbit's box and the copy column, at nine
     widths from 980 to 1920 and five percentages:

       width   112%   118%   124%   127%   132%
       1200    41.6   26.2   10.9    3.2   -9.6

     127% leaves 3.2px and 132% runs 9.6px *under* the text. The note's other
     warning held too: the margin is tightest in the MIDDLE of the range, at
     1200, not at either end — the column ratio and the gap's clamp move
     against each other. MyKid's grid is 1.05fr to 1fr, so the copy takes more
     of the page here than it does there, which is why the ceiling is lower.
     120% leaves 18px at its worst, which is the arc's 7px glow and real air
     besides; 122% leaves 13.8 and starts to crowd. */
  width: 120%;
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  pointer-events: none;     /* it must not take a click or a drag from the mark */
  z-index: 2;
  animation: orbitIn 1.4s cubic-bezier(.2, .8, .2, 1) .25s both;
}
.orbit-arc { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }

.orbit-node {
  position: absolute; inset: 0;
  display: grid; place-items: center start;
  transform: rotate(var(--a));
}
.orbit-node b {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 10px 5px 8px;
  border-radius: 999px;
  border: 1px solid var(--color-accent-200);
  background: #fff;
  box-shadow: 0 4px 14px rgba(79, 91, 213, .13);
  font-size: 11.5px; font-weight: 500; white-space: nowrap;
  color: var(--text);
  transform: rotate(calc(var(--a) * -1));
  animation: orbitFloat 7s ease-in-out infinite;
  transition: opacity .42s ease;
}
.orbit-node[data-fade="out"] b { opacity: 0; }

/* The middle one is nearest the copy, so it is the one that is bigger. */
.orbit-node.n-mid b { font-size: 12.5px; padding: 6px 12px 6px 9px; }
/* Negative delays, so the three are never in phase. */
.orbit-node.n-hi b { animation-delay: -2.3s; }
.orbit-node.n-lo b { animation-delay: -4.6s; }

.orbit .od {
  width: 7px; height: 7px; border-radius: 50%; flex: none;
  display: block; background: var(--color-accent);
}
/* The bare dots sit on the page rather than on a pill, so they need a white
   ring to stay legible wherever the arc or the aura passes behind them. They
   can be centred on the arc where a pill cannot: 9px and symmetric costs 4.5px
   of clearance, not 47. */
.orbit-node.n-dot .od {
  width: 9px; height: 9px;
  transform: rotate(calc(var(--a) * -1)) translateX(-50%);
  box-shadow: 0 0 0 3.5px var(--bg), 0 2px 7px rgba(79, 91, 213, .18);
  animation: orbitFloat 7s ease-in-out infinite;
  animation-delay: -1.1s;
}
.orbit-node.n-dot:last-of-type .od { animation-delay: -5.7s; }

/* Read by orbit.js and never shown: the names belong in copy.json with every
   other string, not in a JavaScript array that English would need its own
   copy of. */
.orbit-names { display: none; }

@keyframes orbitIn {
  from { opacity: 0; transform: translate(-50%, -50%) scale(.94); }
  to   { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}
@keyframes orbitFloat { 0%, 100% { translate: 0 0; } 50% { translate: 0 -5px; } }

/* Nothing for it to do once the hero stacks, which here is 960px and not the
   980 the pattern was written against. */
@media (max-width: 960px) { .orbit { display: none; } }

@media (prefers-reduced-motion: reduce) {
  .orbit { animation: none; }
  .orbit-node b, .orbit-node.n-dot .od { animation: none; }
}

/* ── Pricing ─────────────────────────────────────────────────────────── */
.price-card {
  max-width: 460px;
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-card-lg); padding: var(--s-7) var(--s-6);
  box-shadow: var(--shadow-card);
}
.price { display: flex; align-items: baseline; gap: var(--s-2); flex-wrap: wrap; }
.price-num { font-size: 52px; font-weight: 200; letter-spacing: -0.03em; line-height: 1; color: var(--accent); }
.price-per { font-size: var(--fs-body); color: var(--text-dim); }
.price-trial { margin-top: var(--s-3); font-size: var(--fs-body); font-weight: 500; }
.price-list { list-style: none; margin: var(--s-5) 0 var(--s-6); padding: 0; display: flex; flex-direction: column; gap: var(--s-3); }
.price-list li { position: relative; padding-left: 28px; font-size: var(--fs-body-sm); line-height: 1.5; color: var(--text-dim); }
.price-list li::before {
  content: ''; position: absolute; left: 0; top: 2px;
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--color-accent-100);
  box-shadow: inset 0 0 0 5px var(--color-accent-100), inset 0 0 0 9px var(--accent);
}
.price-note { margin-top: var(--s-4); font-size: var(--fs-meta); color: var(--text-dim); line-height: 1.5; }

/* ── Pricing, centred (2026-11-09) ─────────────────────────────────────
   One plan stands alone, so it sits on the page's centre line; the list
   inside the card stays left-aligned, because ticks read down a left edge. */
.price-section .section-head { margin-left: auto; margin-right: auto; text-align: center; }
.price-section .price-card { margin-left: auto; margin-right: auto; }
.price-section .price { justify-content: center; }
.price-section .price-trial, .price-section .price-note { text-align: center; }
.price-section .pill-cta { display: flex; width: 100%; }

/* "Como instalar" in the footer is a button that looks like its links. */
.foot-link { background: none; border: 0; padding: 0; font: inherit; color: var(--text-dim); cursor: pointer; }
.foot-link:hover { color: var(--accent-deep); }

/* The chip's line ("Acompanhar o progresso do seu filho tem muito valor",
   2026-11-09) is longer than a phone is wide: it wraps to two lines, so those
   are centred and balanced between the two dots rather than ragged left. */
@media (max-width: 620px) {
  .hero .chip { text-align: center; text-wrap: balance; max-width: 100%; }
}
