/* THE SITE'S DARK (her call, 4 Oct 2026): the old grey #191D24 is gone from
   this page; the home page's #0D0914 replaces it. --c-dark is redefined here,
   not in the shared tokens.css, which home.html still reads. */
:root { --c-dark: #0D0914; }

/* ==========================================================================
   TSIVIA — mentoring.html  ("ליווי עיצוב אישי")
   --------------------------------------------------------------------------
   Figma file 2Yx93XsRt6hLfp4jN52y8T, desktop frame 3444:1122, **1920 x 7019**.

   Built 1:1 from the frame itself, not from the Codex export — she changed the
   frame after that export and almost every y moved. The Codex build has the
   page at 7408, About at 4022 and an EMPTY plans section; the live frame is
   7019, About at 3687 and the plans cards exist. docs/mentoring.md has the
   before/after.

   SAME SCALING MODEL AS style.css AND home.css: every length is its literal
   Figma pixel value times --u, and js/mentoring.js sets --u = clientWidth/1920.

   WHY THIS IS ITS OWN FILE
   ------------------------
   index.html is signed off and home.html is mid-flight. Their section geometry
   is a list of absolute y coordinates on DIFFERENT artboards (11314 and 9562
   against this frame's 7019), so nothing here could be layered on top of
   either without fighting every number. The components below are the same
   recipes re-measured against this frame. A fix belonging to more than one
   page has to be made in each of them, deliberately.

   ANIMATIONS ARE NOT IN YET — her instruction: 1:1 first, motion after, and
   then exactly the same motion as the other two pages.

   THE PAGE MAP (literal Figma y)

       header          0
       hero         229.14  DESIGN / BETTER / tag / tagline / CTA
       services    1158     "ליווי אישי", three cards at 1431 / 1431 / 1518
       audience    2407     "מזהים את עצמכם?", rows 2667 / 2804 / 3089
       about       3413     ABOUT ME ghost, photo, "היי, אני צִבְיָה :)" 3687
       plans       4915.54  "בוחרים איך מתקדמים", two cards at 5196.9
       contact     6125.46  CTA, LET'S TALK 6383.46
       footer bar  6917.46  141 tall in the frame, CLIPPED by the 7019 end to
                            101.54 — the same trim the other two pages made
   ========================================================================== */

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

/* Set by js/mentoring.js for the one frame in which --u changes. Without it
   every re-measure animates anything that transitions a --u-derived property
   — the audience rows' height above all. See the note in js/mentoring.js. */
.is-resettling *,
.is-resettling *::before,
.is-resettling *::after {
  transition: none !important;
  animation-play-state: paused !important;
}

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

body {
  /* CSS fallback only — 100vw counts the scrollbar and block layout does not.
     js/mentoring.js overwrites --u with a value measured from clientWidth. */
  --u: min(1px, 100vw / 1920);
  margin: 0;
  /* Like home.html and unlike index.html, the ground is #F7F7F7 and the dark
     is a SHAPE laid over it (Figma "Rectangle 110", 1920 x 4116 at y 758),
     not the page itself. Anything outside that shape reads light. */
  background: #F7F7F7;
  color: var(--c-dark);
  font-family: var(--f-body);
  font-weight: var(--fw-light-on-white);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

img { display: block; max-width: 100%; }
a   { text-decoration: none; color: inherit; }
p   { margin: 0; }
h1, h2, h3 { margin: 0; font-weight: inherit; }

.page {
  position: relative;
  width: 100%;
  height: calc(6646 * var(--u));  /* the frame (6766) less the 120 she took out after About, 21 Sep */
  /* BOTH AXES. The waves are wider than the artboard by design, and the
     footer plate hangs 75 BELOW it by design too — which with overflow-x
     alone left 121 design px of empty scroll after the footer. The artboard
     is the page; anything past it is meant to be cut, in both directions. */
  overflow: clip;
}

/* Parked by CLIPPING IT TO NOTHING, never by left:-9999px. The document is
   RTL, where a negative offset is real scrollable space — that is what shoved
   index.html's footer off screen, and here it opened 9998px of horizontal
   scroll. `body { overflow-x: hidden }` does NOT contain it: when `html` is
   `overflow: visible` the body's value is propagated to the viewport and the
   body itself is treated as visible. docs/traps.md. */
.skip-link {
  position: absolute;
  top: 0; right: 0;
  width: 1px; height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  z-index: 300;
  background: var(--c-dark);
  color: #F7F7F7;
}
.skip-link:focus {
  width: auto; height: auto;
  overflow: visible;
  clip-path: none;
  top: calc(16 * var(--u));
  right: calc(16 * var(--u));
  padding: calc(12 * var(--u)) calc(20 * var(--u));
}


/* ==========================================================================
   THE BACKGROUND STACK
   --------------------------------------------------------------------------
   One container, and DOM order IS paint order — it mirrors the child order of
   the Figma frame. Everything rotated or blur-expanded is placed by the CENTRE
   of its Figma bounding frame: Figma centres such a child inside its frame, so
   the frame's top-left is not the picture's and only the centre survives a
   rotation.
   ========================================================================== */
.page-bg {
  position: absolute;
  inset: 0;                /* exactly the page — 100% below IS y 7019 */
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
}

.page-bg > img { position: absolute; max-width: none; }

/* --- the silvery wave  (3444:1126 hero / 3444:1280 foot) -----------------
   Frame (-554, -881) 2385 x 1337 -> centre (638.5, -212.5). Figma paints a
   gradient over it running to white between 65.333% and 88.856% of the box;
   a mask does the same job without a wrapper, because what is behind it at
   that point IS the near-white page.

   THE HAZE IS BAKED INTO THE FILE, not applied as a live `filter`. The
   thirteen frosted columns in front of this carry a 103.38px BACKDROP blur in
   the frame; twenty-six live backdrop-filters is the purple-screen bug at
   double strength, and a live `filter` is the other half of it — a filter
   forces its element onto a GPU texture at DEVICE resolution, and 2385 x 1337
   design px is 4770 x 2674 at DPR 2, past the 4096 limit most GPUs enforce.
   A layer that cannot be rasterised is painted as a flat fill, which is the
   purple panel she photographed. docs/traps.md.
   __scratch/wave-hero-unblurred.png is the clean source; the bake is
   `sharp(...).blur(46 * 1675/2385)`.
   ------------------------------------------------------------------------ */
.glow {
  position: absolute;
  translate: -50% -50%;
  border-radius: 50%;
}
.glow--deep  { background: radial-gradient(closest-side ellipse, rgba(105,94,190,0.50) 0%, rgba(105,94,190,0.30) 45%, rgba(105,94,190,0) 100%); }
.glow--light { background: radial-gradient(closest-side ellipse, rgba(159,147,255,0.55) 0%, rgba(159,147,255,0.32) 44%, rgba(159,147,255,0) 100%); }

/* hero half — every centre is (frame.left + w/2, frame.top + h/2) */
.glow--e22 {
  left: calc(-93.759 * var(--u));
  top: calc(4897.2745 * var(--u));
  width: calc(2900.97 * var(--u));
  height: calc(1823.21 * var(--u));
  rotate: 49.97deg;
  /* Halved, 20 Sep: she asked for the purple on the left to be lighter. It
     is the only glow left on the page — the other ten went into her two
     background plates — so this is the whole wash over the plans. */
  background: radial-gradient(closest-side ellipse, rgba(159,147,255,0.21) 0%, rgba(159,147,255,0.11) 40%, rgba(159,147,255,0) 100%);
}

/* footer half — the same set mirrored, all measured UP FROM THE PAGE BOTTOM */
.dark-band {
  left: 50%;
  translate: -50% 0;
  top: calc(758 * var(--u));
  width: calc(1920 * var(--u));
  height: calc(3996 * var(--u));   /* 4116 in the frame; bottom raised 120, 21 Sep — dark-band.svg too */
}

/* --- the chrome ribbon, "גל הירו"  (3447:1482) ---------------------------
   ROTATED AND MIRRORED, so it is placed by its frame's CENTRE. Frame
   (-241.99, 272.66) 2589.96 x 1414.842 -> centre (1052.99, 980.081). The
   PICTURE is a different shape entirely: 2544.045 x 581.927, scaleY(-1) and
   rotate(-19.94deg). Placing it by the frame's top-left at the frame's size
   drew an unrotated 2590-wide slab across the hero and buried the tagline.

   translate/rotate/scale as INDIVIDUAL properties, never one `transform`: the
   browser applies them translate -> rotate -> scale, which is the order Figma
   composed them in, and it leaves `transform` free for the reveal.

   RE-CUT 21 Sep 2026 — she saw both waves soft. They were 1024 x 768 files
   stretched to 2544 x 582, a 2.5x upscale. Both nodes now fill from ONE
   4096 x 3072 picture (hash 1abd01a2…, the first of download_assets'
   rawImages) with scaleMode CROP, so each webp is that picture cut to its
   node's own imageTransform rows — ribbon 0.3178 + 0.3050 of the height
   (4096 x 937), About 0.3672 + 0.2635 (4096 x 810) — with Figma's image
   adjustments baked in by hand (exposure -0.08, saturation -0.53, tint
   +0.25, highlights -0.44). Old files: __scratch/waves-hi/old-*.webp.
   ------------------------------------------------------------------------ */
.wave-ribbon {
  left: calc(1052.99 * var(--u));
  top: calc(980.081 * var(--u));
  width: calc(2544.045 * var(--u));
  height: calc(581.927 * var(--u));
  translate: -50% -50%;
  rotate: -19.94deg;
  scale: 1 -1;
  object-fit: fill;
}

/* --- the wave behind About  (3444:1277) ----------------------------------
   Frame (-531, 3937) 2730.1 x 1341.809 -> centre (834.05, 4607.9045); the
   picture is 2697.531 x 533.156 rotated -161.97deg. Re-cut at 4096 wide on
   21 Sep, see the ribbon.
   ------------------------------------------------------------------------ */
.wave-about {
  left: calc(834.05 * var(--u));
  top: calc(4487.9045 * var(--u));  /* frame centre 4607.9, less the 120 after About; sits on the jagged edge */
  width: calc(2697.531 * var(--u));
  height: calc(533.156 * var(--u));
  translate: -50% -50%;
  rotate: -161.97deg;
  object-fit: fill;
}


/* ==========================================================================
   GRID LINES AND RAINDROPS
   --------------------------------------------------------------------------
   THE CLASS IS .grid-rail, NOT .grid-lines__band, AND THAT IS DELIBERATE.
   js/marquee.js carries its own raindrop generator that finds bands with
   `.grid-lines__band`; it is tuned for index.html and would paint a second
   drop on every line here. The name is what keeps it out.

   Figma calls this group "פסים הירו" (3444:1207): x 175, y 0.5, 1570 wide,
   ten lines on a 175 pitch. The node is 7407.5 tall — left over from the
   taller frame — so it is clipped to the 7019 page here.

   The lines and drops are IDENTICAL on all three pages, at her request ("it
   is the same site, it must be uniform"). 1 CSS px at 0.07, snapped to whole
   CSS px by js/mentoring.js; drops 1 x 12 with the comet gradient at peak
   0.75. ANY CHANGE HERE MUST ALSO BE MADE IN css/style.css AND css/home.css.
   ========================================================================== */
.grid-rail {
  position: absolute;
  left: calc(175 * var(--u));
  width: calc(1570 * var(--u));
  overflow: hidden;      /* clips the drops to the band */
  pointer-events: none;
  z-index: 1;
}

/* THREE BANDS, ONE PER GROUND — her rule, and the same one home.html follows:
   a drop on a LIGHT ground is dark ink, a drop on a DARK ground is white.
   Same size, same alpha, same pace; only the colour changes.

   The LINE does not change. Figma draws all ten of them #9F93FF at 0.2 across
   the whole 7407.5 (node 3444:1207) — one uniform colour, light ground and
   dark alike — so --line is the project's usual lilac on every band.

   The boundaries are where the dark shape is dark ACROSS THE RAIL'S WIDTH
   (x 175 -> 1745), not where its box starts. Its edges are jagged: the top
   runs y 758 at x1671 down to 1240.5 at x0, and within the rail's own span
   the lowest point is 1102. The bottom runs 4471 at x0 to 4874 at x1920, and
   within the rail the highest point is 4471. Anything outside 1102 -> 4471
   would put a white drop on the pale page. If the dark shape ever moves,
   these two numbers move with it.
   21 Sep 2026: the bottom edge was raised 120 to close the gap after About,
   so every bottom figure in these notes now reads 120 less (4471 -> 4351). */
/* THE HERO KEEPS ITS LINES AND LOSES ITS RAIN — her call, 20 Sep 2026.
   --no-rain is read by js/mentoring.js, which then hangs no drops on this
   band. The ten lines are untouched. */
.grid-rail--top {
  top: calc(0.5 * var(--u));
  height: calc(1101.5 * var(--u));
  --band-h: calc(1101.5 * var(--u));
  --line: rgba(159, 147, 255, 0.07);
  --drop: #0D0914;
  --drop-peak: 0.75;
  --drop-ref: 1633.3;
  --no-rain: 1;
}

.grid-rail--dark {
  top: calc(1102 * var(--u));
  height: calc(3249 * var(--u));
  --band-h: calc(3249 * var(--u));
  --line: rgba(159, 147, 255, 0.07);
  --drop: #FFFFFF;
  --drop-peak: 0.75;
  --drop-ref: 2784.2;
}

.grid-rail--foot {
  top: calc(4351 * var(--u));
  height: calc(2295 * var(--u));
  --band-h: calc(2295 * var(--u));
  --line: rgba(159, 147, 255, 0.07);
  --drop: #0D0914;
  --drop-peak: 0.75;
  --drop-ref: 1633.3;
}

.grid-rail span {
  position: absolute;
  top: 0;
  bottom: 0;
  /* ONE CSS PIXEL, never calc(N * --u). A hairline that scales down lands on
     a fraction of a pixel, and the browser fades a 0.32px line instead of
     drawing it — at 7% alpha that is nothing at all. */
  width: 1px;
  background: var(--line, rgba(159, 147, 255, 0.07));
}

.grid-rail span:nth-child(1)  { left: 0; }
.grid-rail span:nth-child(2)  { left: calc(175  * var(--u)); }
.grid-rail span:nth-child(3)  { left: calc(350  * var(--u)); }
.grid-rail span:nth-child(4)  { left: calc(523  * var(--u)); }
.grid-rail span:nth-child(5)  { left: calc(698  * var(--u)); }
.grid-rail span:nth-child(6)  { left: calc(873  * var(--u)); }
.grid-rail span:nth-child(7)  { left: calc(1047 * var(--u)); }
.grid-rail span:nth-child(8)  { left: calc(1220 * var(--u)); }
.grid-rail span:nth-child(9)  { left: calc(1396 * var(--u)); }
.grid-rail span:nth-child(10) { left: calc(1570 * var(--u)); }

/* The streak. 1 x 12, FLAT — never calc(N * --u), which at --u 0.72 would
   draw it 8.6 tall and reintroduce the sub-pixel problem the lines have.
   A comet: long tail above, bright low, short fade at the leading edge.
   NO blur — blur(1px) on a 1px mark spreads it into ~4px of haze, which on a
   hairline reads as a smudge sliding down the line, and she said so. */
.raindrop {
  position: absolute;
  top: 0;
  width: 1px;
  height: 12px;
  background: linear-gradient(to bottom,
              transparent 0%,
              var(--drop, #FFFFFF) 62%,
              var(--drop, #FFFFFF) 84%,
              transparent 100%);
  opacity: 0;
  animation: raindrop-fall var(--fall, 10s) linear var(--wait, 0s) infinite;
  will-change: transform, opacity;
}

/* The same keyframes as css/style.css and css/home.css, stop for stop. */
@keyframes raindrop-fall {
  0%   { transform: translateY(-100%); opacity: 0; }
  3%   { opacity: var(--drop-peak, 0.75); }
  38%  { opacity: var(--drop-peak, 0.75); }
  50%  { transform: translateY(var(--band-h, 900px)); opacity: 0; }
  100% { transform: translateY(var(--band-h, 900px)); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .raindrop { display: none; }
}


/* ==========================================================================
   FALLING ICONS
   --------------------------------------------------------------------------
   She pointed at the SERVICES section of muizzwebstudio.com. Read off their
   page rather than guessed: a `position: relative; overflow: hidden`
   container, 9–12 absolutely positioned 30–42px icons drawn from a set of
   three, each at a random rotation. Following ONE of them for two seconds
   gave the motion exactly — x CONSTANT (it falls straight, no drift),
   y linear at about 250px/s with NO acceleration, and a continuous rotation
   of roughly 73 degrees per second. Gentle, which is what she asked for.

   THREE DELIBERATE DEPARTURES.
   Their icons are `mix-blend-mode: difference`, which is how they get
   contrast on any ground for free. Hers follow the site's own rule instead —
   deep purple on a light ground, white on a dark one, the same rule as the
   raindrops — so the colour is a per-band variable.
   And they drive it from a rAF loop; this is CSS animation with negative
   delays, exactly like the raindrops. It costs nothing per frame, it survives
   a throttled tab, and it is measurable in a browser that paints no frames.

   And their icons fall out of the bottom of the container for ever. Hers
   STOP: the field ends on the bottom edge of the cards and each icon lands
   there — two damped bounces, a rest, a fade, and round again. She asked for
   a boundary and for the stop to be worth watching.

   The icons are drawn as MASKS, not images, so one file serves both grounds
   and `--icon` alone recolours the set.
   ========================================================================== */
.icon-fall {
  position: absolute;
  left: 0;
  width: calc(1920 * var(--u));
  overflow: hidden;
  pointer-events: none;
}

/* The field is the CARDS' OWN AREA and nothing around it: card 03's left
   edge (174) to card 01's right edge (1745), down to the line all three now
   share (2090). It starts BELOW the heading and its capsule — the capsule's
   box runs 1242.3 to 1344.9 and she does not want icons crossing either — so
   the top is 1350, not the section's own 1158. 1571 x 740. */
.icon-fall--services {
  left: calc(174 * var(--u));
  width: calc(1571 * var(--u));
  /* 21 Sep 2026, her call: the icons fall from HIGHER, from the wave. 1110 is
     as high as the field can start and still be on the dark ground across all
     three cards' columns (the band's jagged top reaches 1102 at x 174). They
     do cross the heading on the way down now; she asked for the height. */
  top: calc(1110 * var(--u));
  height: calc(990 * var(--u));   /* down to the cards' bottom, 2100 */
}

/* --- the two inks -------------------------------------------------------
   The rule on this site is deep purple on a light ground, white on a dark
   one. An icon is a moving object, so no single colour is right for it: the
   GROUND decides, and here the ground is the CARDS.

   01 and 03 have no background at all — they are outlines on the dark shape
   — so the white ink simply shows through them. 02 is solid #F7F7F7, which
   is why she saw the icons die there. So the field is drawn TWICE:

     --dark   white, left where it is, UNDER the cards. The white card hides
              it; the two transparent ones do not.
     --card   purple, lifted ABOVE the cards and clipped to 02's rounded
              rectangle, so it appears exactly where the white one is lost.

   Both carry identical icons, built once and cloned, attached in the same
   frame so the two animations share a start time. An icon crossing 02's
   top edge changes colour ON the edge instead of vanishing behind it.

   The card's own text is raised over both (`.card > *`), so the icons read
   as something falling INSIDE the card rather than across its words.

   Card 02 inside the field: x 531..1040 of 1571 (33.800% each side),
   top 81 of 740 (10.946%). Those three numbers and `--r-card` are the
   whole geometry; they move only if the cards do.
   ---------------------------------------------------------------------- */
.icon-fall__ink { position: absolute; inset: 0; }

.icon-fall--services .icon-fall__ink--dark {
  --icon: #FFFFFF;
  --icon-o: 1;
}

.icon-fall--services .icon-fall__ink--card {
  z-index: 2;
  --icon: var(--c-purple);
  --icon-o: 1;
  clip-path: inset(calc(321 * var(--u)) 33.800% 0% 33.800% round var(--r-card));   /* card top 1431 - field top 1110 */
}

.icon-fall i {
  position: absolute;
  top: 0;
  display: block;
  background: var(--icon, #FFFFFF);
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  -webkit-mask-position: center;
          mask-position: center;
  -webkit-mask-size: contain;
          mask-size: contain;
  opacity: 0;
  will-change: translate, rotate;
  /* THE ONE FREE PROPERTY. The fall owns translate, rotate and scale, which
     are separate properties that compose with transform — so the pointer
     lean can have transform to itself. --px/--py are set once on the FIELD
     and inherit; --d is the icon's own depth, from its size. The transition
     is what makes it read as weight: the field arrives a beat late. */
  transform: translate(calc(var(--px, 0px) * var(--d, 1)),
                       calc(var(--py, 0px) * var(--d, 1)));
  transition: transform 0.65s var(--ease-rise);
  /* The band fills from EMPTY over one fall, so it waits until she is
     looking at it. js/mentoring.js puts .is-in on. */
  animation-play-state: paused;
}
.icon-fall.is-in i { animation-play-state: running; }

/* Since 21 Sep the icons are a small physics pile (js/mentoring.js): they
   fall once, heap on the card's shelf and stay; the pointer nudges them.
   The script writes translate/rotate/opacity inline and turns off the
   keyframes and the lean transform below. */

/* The keyframes are GENERATED, one rule per ICON, in js/mentoring.js. They
   have to be: no two icons share a fall length, a bounce height or a moment,
   and a keyframe percentage is the ratio between a distance over a speed and
   a count of seconds — only the page knows both. */

/* reduced motion: the script skips the fall and draws the settled pile */


/* ==========================================================================
   SHARED PIECES
   ========================================================================== */

/* --- pill buttons ------------------------------------------------------
   THE SAME RECIPE AS index.html AND home.html, copied stop for stop — she
   asked for the buttons to behave and colour identically across the site.

   `background: transparent` on purpose: the colour lives on ::before so the
   hover can MASK IT AWAY and expose whatever is genuinely behind the pill,
   rather than painting a flat disc of page colour over the artwork. Measuring
   backgroundColor and finding it transparent is not a missing colour.
   docs/traps.md.

   --fill has to be a registered property or it cannot be transitioned — an
   unregistered custom property snaps from 0% to 105% with no animation.
   ------------------------------------------------------------------------ */
@property --fill {
  syntax: "<percentage>";
  initial-value: 0%;
  inherits: false;
}

.btn {
  position: relative;
  display: inline-flex;
  direction: rtl;
  align-items: center;
  justify-content: center;
  gap: calc(8 * var(--u));
  border-radius: var(--r-pill);
  font-family: var(--f-body);
  font-weight: var(--fw-light);
  line-height: 1.591;
  white-space: nowrap;
  color: var(--c-white);
  --mx: 50%;
  --my: 50%;
  isolation: isolate;
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease-soft),
              border-color var(--dur-base) var(--ease-soft);
}

.btn::before {
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  background: var(--btn-fill, var(--c-purple-light));
  z-index: -1;
  transition: --fill var(--dur-base) var(--ease-soft);
}

.btn--solid {
  background: transparent;
  border: 1px solid transparent;
}

.btn--solid::before {
  --fill: 0%;
  -webkit-mask-image: radial-gradient(circle at var(--mx) var(--my),
                        #0000 var(--fill), #000 calc(var(--fill) + 0.5%));
          mask-image: radial-gradient(circle at var(--mx) var(--my),
                        #0000 var(--fill), #000 calc(var(--fill) + 0.5%));
}

.btn--solid:hover::before,
.btn--solid:focus-visible::before { --fill: 105%; }

.btn--solid:hover,
.btn--solid:focus-visible {
  border-color: var(--btn-fill, var(--c-purple-light));
  color: var(--btn-fill, var(--c-purple-light));
}

/* the two fills this frame uses */
/* THE MIRROR OF --solid, for the frame's outlined plan card. Solid rests
   with --fill at 0% (painted) and hovers to 105% (masked away, leaving the
   ground); ghost rests at 105% and hovers to 0%, so the colour grows out of
   the pointer into an outline that was empty. Same property, same duration,
   same easing — one gesture read in both directions. */
.btn--ghost {
  background: transparent;
  border: max(1px, calc(1 * var(--u))) solid var(--btn-fill, var(--c-purple));
  color: var(--btn-fill, var(--c-purple));
}
.btn--ghost::before {
  --fill: 105%;
  -webkit-mask-image: radial-gradient(circle at var(--mx) var(--my),
                        #0000 var(--fill), #000 calc(var(--fill) + 0.5%));
          mask-image: radial-gradient(circle at var(--mx) var(--my),
                        #0000 var(--fill), #000 calc(var(--fill) + 0.5%));
}
.btn--ghost:hover::before,
.btn--ghost:focus-visible::before { --fill: 0%; }
.btn--ghost:hover,
.btn--ghost:focus-visible { color: #F7F7F7; }

.btn--light { --btn-fill: var(--c-purple-light); }   /* #9F93FF */
.btn--deep  { --btn-fill: var(--c-purple); }         /* #695EBE */

/* the arrow slides toward the reading direction on hover, as on both other
   pages. RTL, so it travels LEFT. */
.btn__arrow {
  display: inline-block;
  transition: transform var(--dur-fast) var(--ease-out);
}
.btn:hover .btn__arrow,
.btn:focus-visible .btn__arrow { transform: translateX(calc(-6 * var(--u))); }

/* THE SITE'S BUTTON ARROW (her call, 4 Oct 2026): the home page's long arrow
   (56.5 x 11, the Figma vector) replaces the "←" glyph on every button, 19.45
   from the words as there. The label keeps the reading order; the arrow is on
   its left and steps further left on hover, as before. */
.btn { gap: calc(19.453 * var(--u)); }
.btn__label { direction: rtl; }
.btn__arrow {
  display: block;
  flex: none;
  width: calc(56.5 * var(--u));
  height: calc(11.046 * var(--u));
  margin-inline: calc(-0.75 * var(--u));
}
@media (max-width: 899px) {
  /* the phone's unit is the 393 frame's: a 36-long arrow, 12 from the words */
  .btn { gap: calc(12 * var(--u)); }
  .btn__arrow { width: calc(36 * var(--u)); height: calc(7.04 * var(--u)); }
}



/* --- the outlined capsules  (3444:1253 / 1258 / 1262 / 1266) -------------
   All four are the same object at different angles: a 68.937-tall pill, 1.436
   border, 143.619 radius, on a near-opaque #F7F7F7. Each is ROTATED, so each
   is placed by the CENTRE of its Figma bounding frame.
   ------------------------------------------------------------------------ */
.capsule {
  position: absolute;
  display: inline-flex;
  align-items: center;
  height: calc(68.937 * var(--u));
  border-radius: calc(143.619 * var(--u));
  /* Figma says 1.436. Floored at one whole pixel: below that the browser
     fades the stroke instead of drawing it, and a faded border on a
     69%-opaque capsule disappears entirely. */
  border: max(1px, calc(1.436 * var(--u))) solid var(--c-purple-light);
  color: var(--c-purple);
  font-weight: var(--fw-light-on-white);
  line-height: 1.591;
  white-space: nowrap;
  translate: -50% -50%;
}
.capsule--tag {
  left: calc(519.7515 * var(--u));
  /* 3444:1253's centre, exactly as the frame has it — and she confirmed that
     is the place (21 Sep 2026) after a try at 70 lower, over the letters.
     z-index keeps it above the wordmark wherever the two touch. */
  top: calc(243.952 * var(--u));
  z-index: 4;
  rotate: -5.35deg;
  padding: calc(11.489 * var(--u)) calc(32 * var(--u));
  background: rgba(247, 247, 247, 0.69);
  font-size: calc(24 * var(--u));
}
.capsule--note {
  gap: calc(24 * var(--u));
  padding: calc(11.489 * var(--u)) calc(64 * var(--u)) calc(11 * var(--u));
  background: rgba(247, 247, 247, 0.8);
  font-size: calc(32 * var(--u));
}
.capsule--note img { width: calc(33 * var(--u)); height: calc(33 * var(--u)); }

.capsule--services { left: calc(1486.8765 * var(--u)); top: calc(1293.658 * var(--u));  rotate: 4.06deg; }
.capsule--audience { left: calc(959.93 * var(--u));    top: calc(2545.678 * var(--u));  rotate: 1.74deg; }
.capsule--plans    { left: calc(959.9325 * var(--u));   top: calc(4934.6273 * var(--u)); rotate: 1.74deg;   /* 3444:1266 centre; was 120 high, on the title */
                     border-color: var(--c-purple); }

/* --- the display wordmarks ----------------------------------------------
   Figma's literal size and tracking on all three, and ALL THREE ARE
   UNVERIFIED. The other page's WEBSITES needed -42.385 where Figma said
   -36.67, while ABOUT ME on frame 3342 was exact — a correction is never
   carried across. Measure each with __scratch/measure.html before calling
   them done. The canvas warp the other pages put on their wordmarks comes in
   the animation pass.
   ------------------------------------------------------------------------ */
.display {
  position: absolute;
  font-family: var(--f-display);
  line-height: 0.96;
  text-align: center;
  white-space: nowrap;
  translate: -50% 0;
  -webkit-background-clip: text;
          background-clip: text;
  color: transparent;
}

/* --- the Figma-UI props: selection frames, handles, cursors --------------
   These are DRAWN IN THE FRAME, not interaction. The design's whole
   conceit is a Figma canvas, so the selection rectangle around BETTER, the
   corner handles and the "You" cursor are static artwork. The Codex build
   made them draggable; the frame does not.
   ------------------------------------------------------------------------ */
.prop { position: absolute; pointer-events: none; }

.handle {
  position: absolute;
  width: calc(17 * var(--u));
  height: calc(17 * var(--u));
  background: #F7F7F7;
  border: max(1px, calc(3 * var(--u))) solid var(--c-purple);
  rotate: 0.2deg;
  translate: -50% -50%;
}

.cursor-badge {
  position: absolute;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: calc(8.166 * var(--u));
  background: var(--c-purple);
  color: #F7F7F7;
  font-size: calc(20 * var(--u));
  line-height: 1.2;
  white-space: nowrap;
}
.cursor-arrow {
  /* max-width: none, and it is not optional. The global `img { max-width:
     100% }` resolves against the containing block, and .hero__you has BOTH
     its children absolutely positioned — so it has no in-flow content, its
     shrink-to-fit width is 0, and the arrow's max-width became 0. It rendered
     as a zero-width sliver: still there, still rotated, completely invisible.
     The badge survived because a padded <span> is not an <img>. */
  max-width: none;
  position: absolute;
  width: calc(24.471 * var(--u));
  height: calc(24.538 * var(--u));
  translate: -50% -50%;
  rotate: -38.57deg;
}


/* ==========================================================================
   HEADER  (3444:1220)
   --------------------------------------------------------------------------
   ONE state, not the three index.html has: this page's hero is the light
   band, so the frame draws the bar solid from the first pixel. Its
   backdrop-blur is deliberately NOT implemented — see .wave-top.
   ========================================================================== */
.site-head {
  position: absolute;
  left: 50%;
  translate: -50% 0;
  top: 0;
  width: calc(1920 * var(--u));
  height: calc(103 * var(--u));
  padding: calc(10 * var(--u)) calc(175 * var(--u)) calc(10 * var(--u)) calc(174 * var(--u));
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: rgba(255, 255, 255, 0.5);
  z-index: 10;
}

/* static, not absolute — it is a flex child of the bar */
.site-head__cta {
  /* relative, NOT static: .btn paints its fill on ::before { inset: 0 }, and a
     static element is not a containing block — the inset resolved against
     .site-head instead and flooded the whole bar purple. relative takes the
     button out of .btn's absolute positioning just as well and keeps the
     pseudo-elements anchored to the button. */
  position: relative;
  width: calc(163 * var(--u));
  padding: calc(8 * var(--u)) 0;
  font-size: calc(20 * var(--u));
}

.site-head__nav {
  display: flex;
  align-items: center;
  gap: calc(100 * var(--u));
  font-size: calc(20 * var(--u));
  line-height: 1.3;
  color: var(--c-dark);
  white-space: nowrap;
}

.site-head__logo-wrap {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  width: calc(147 * var(--u));
  height: calc(34 * var(--u));
}
.site-head__logo { width: calc(92.601 * var(--u)); height: calc(30.672 * var(--u)); }


/* ==========================================================================
   HERO
   ========================================================================== */
.hero__title {
  left: calc(699 * var(--u));          /* 50% - 261 */
  top: calc(229.14 * var(--u));
  font-size: calc(380.399 * var(--u));
  letter-spacing: calc(-19.0199 * var(--u));
  background-image: linear-gradient(to bottom, #695EBE 0%, #3F387B 40.38%, #201B49 85.704%);
}

.hero__better {
  position: absolute;
  left: calc(1326.4 * var(--u));       /* 50% + 366.4 */
  top: calc(369.32 * var(--u));
  translate: -50% 0;
  font-size: calc(128 * var(--u));
  line-height: 0.96;
  letter-spacing: calc(-6.4 * var(--u));
  color: var(--c-purple);
  text-align: center;
  white-space: nowrap;
}

/* the selection rectangle around BETTER (3444:1243) */
/* Draggable WITH the BETTER text — see js/mentoring-hero.js. It has to be
   hit-testable for that, so it does not inherit .prop's pointer-events. */
.hero__select {
  pointer-events: auto;
  cursor: none;
  position: absolute;
  left: calc(1324.0125 * var(--u));    /* 1077.32 + 493.385/2 */
  top: calc(428.0875 * var(--u));      /* 354.2 + 147.775/2 */
  width: calc(493.385 * var(--u));
  height: calc(147.775 * var(--u));
  translate: -50% -50%;
  rotate: 0.2deg;
  border: max(1px, calc(4 * var(--u))) solid var(--c-purple);
}
.hero__handle--tr { left: calc(1568.03 * var(--u)); top: calc(359.38 * var(--u)); }
.hero__handle--tl { left: calc(1079.53 * var(--u)); top: calc(355.67 * var(--u)); }
.hero__handle--br { left: calc(1568.53 * var(--u)); top: calc(500.67 * var(--u)); }
.hero__handle--bl { left: calc(1079.53 * var(--u)); top: calc(498.67 * var(--u)); }

.hero__made {
  position: absolute;
  left: calc(1167.5 * var(--u));
  top: calc(543.14 * var(--u));
  translate: -50% 0;
  font-size: calc(24 * var(--u));
  color: var(--c-purple);
  text-align: center;
  white-space: nowrap;
}

.hero__lede {
  position: absolute;
  left: calc(960.5 * var(--u));
  top: calc(653 * var(--u));
  translate: -50% 0;
  font-size: calc(48 * var(--u));
  line-height: 1.1;
  letter-spacing: calc(2.4 * var(--u));
  color: var(--c-purple);
  text-align: center;
  white-space: nowrap;
}
.hero__lede b {
  font-weight: var(--fw-bold);
  letter-spacing: calc(0.8 * var(--u));
}

/* 3453:1483 — right-aligned at x 1401, so its RIGHT edge is the anchor */
.hero__sub {
  position: absolute;
  left: calc(950 * var(--u));          /* 1401 - 451 */
  top: calc(731 * var(--u));
  width: calc(451 * var(--u));
  font-size: calc(20 * var(--u));
  line-height: 1.3;
  color: var(--c-dark);
  text-align: right;
}

.hero__cta {
  position: absolute;
  left: calc(637.5 * var(--u));        /* 50% - 322.5 */
  /* Centred on the paragraph's LAST line (785.4 + 20.8/2 = 795.8) — "מיושר
     לסוף של הטקסט, לשורה האחרונה", her call 21 Sep 2026. The pill is 41.8
     tall at 20px type, so its top is 795.8 - 20.9. */
  top: calc(767.2 * var(--u));        /* 5 Oct: the site button (12 / 36, 57 tall), still centred on 795.8 */
  translate: -50% 0;
  padding: calc(12 * var(--u)) calc(36 * var(--u));
  /* Figma says 32. Her calls: 24 on 20 Sep (too heavy against the hero),
     20 on 21 Sep ("תקטין קצת"). */
  font-size: calc(20 * var(--u));
}

/* On hover the pill empties and the words turn purple on the pale hero —
   and at the dark-ground weight (240) they went thin (her note, 21 Sep 2026).
   Regular (400) on hover. Swapping weight nudges
   the width by a pixel or two; the pill is centred, so it grows evenly. */
.hero__cta:hover,
.hero__cta:focus-visible { font-weight: var(--fw-reg); }

.hero__star {
  position: absolute;
  left: calc(1280.06 * var(--u));
  top: calc(473.08 * var(--u));
  width: calc(91 * var(--u));
  height: calc(91 * var(--u));
}
.hero__mark {
  position: absolute;
  width: calc(33 * var(--u));
  height: calc(33 * var(--u));
}
.hero__mark--a { left: calc(158 * var(--u));  top: calc(606 * var(--u)); }
.hero__mark--b { left: calc(1728 * var(--u)); top: calc(182 * var(--u)); }

/* --- the "You" cursor (3444:1179) ---------------------------------------
   The frame draws it once, parked at (1737.2, 393.36). It is not decoration
   plus a separate cursor: THIS element becomes the pointer. While the mouse
   is in the hero's live zone it goes `position: fixed` and follows; when the
   mouse leaves it returns to the spot Figma gave it. Two of them on screen at
   once would be the obvious wrong answer.

   The container's origin is the ARROW'S CENTRE, so the badge keeps its exact
   offset from the arrow in both modes: (1751.52-1737.2, 406.72-393.36).
   ------------------------------------------------------------------------ */
.hero__you {
  position: absolute;
  left: calc(1737.2 * var(--u));
  top: calc(393.36 * var(--u));
  pointer-events: none;
  z-index: 20;
}
.hero__you .cursor-arrow { left: 0; top: 0; }
.hero__you .cursor-badge {
  left: calc(14.32 * var(--u));
  top: calc(13.36 * var(--u));
  padding: calc(3.267 * var(--u)) calc(8 * var(--u));
}

/* following the pointer. left/top are written inline every frame; the nudge
   puts the arrow's TIP under the pointer rather than its centre, which is
   what makes it read as a cursor and not as a sticker. */
.hero__you.is-cursor {
  position: fixed;
  z-index: 10000;
  /* the arrow's TIP exactly on the pointer, so where it points is where it
     clicks (her note, 5 Oct): the tip sits (-7.65, -9.59) from the arrow's
     centre once turned -38.57deg */
  translate: calc(7.65 * var(--u)) calc(9.59 * var(--u));
}
.hero__you.is-grabbing { scale: 0.92; }
.hero__you { transition: scale var(--dur-fast) var(--ease-out); }

/* the real pointer gets out of the way inside the zone */
body.hero-live,
body.hero-live * { cursor: none; }


/* --- Figma's selection rectangle ----------------------------------------
   Fixed, because it tracks a live getBoundingClientRect — the thing it frames
   may have been dragged. Colours are Figma's own, by node type: Text blue,
   Frame purple, Vector green, Star orange.
   ------------------------------------------------------------------------ */
.is-movable { cursor: none; touch-action: none; }
.is-movable:focus { outline: none; }

.hero-sel {
  position: absolute;      /* in .page's coordinates — see js/mentoring-hero.js */
  z-index: 50;
  direction: ltr;
  pointer-events: none;
  box-sizing: border-box;
  /* EVERYTHING HERE SCALES WITH --u. Flat 12px/7px/1.5px chrome is Figma's
     own size at 100% zoom, but this page draws at whatever --u is, and
     against a composition scaled to 0.7 the label read as a shout. */
  border: max(1px, calc(1.5 * var(--u))) solid var(--sel, #0D99FF);
}
.hero-sel[hidden] { display: none; }

.hero-sel__label {
  position: absolute;
  bottom: calc(100% + 6 * var(--u));
  left: calc(-1.5 * var(--u));
  padding: calc(2 * var(--u)) calc(6 * var(--u));
  border-radius: calc(4 * var(--u));
  background: var(--sel, #0D99FF);
  color: #FFFFFF;
  font-family: Arial, Helvetica, sans-serif;
  font-size: calc(11 * var(--u));
  line-height: 1.2;
  letter-spacing: calc(0.2 * var(--u));
  white-space: nowrap;
}

/* eight handles, clockwise from the top-left */
.hero-sel i {
  position: absolute;
  width: calc(7 * var(--u));
  height: calc(7 * var(--u));
  background: #F7F7F7;
  border: max(1px, calc(1 * var(--u))) solid var(--sel, #0D99FF);
  transform: translate(-50%, -50%);
}
.hero-sel i:nth-of-type(1) { top: 0;    left: 0; }
.hero-sel i:nth-of-type(2) { top: 0;    left: 50%; }
.hero-sel i:nth-of-type(3) { top: 0;    left: 100%; }
.hero-sel i:nth-of-type(4) { top: 50%;  left: 100%; }
.hero-sel i:nth-of-type(5) { top: 100%; left: 100%; }
.hero-sel i:nth-of-type(6) { top: 100%; left: 50%; }
.hero-sel i:nth-of-type(7) { top: 100%; left: 0; }
.hero-sel i:nth-of-type(8) { top: 50%;  left: 0; }

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

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


/* ==========================================================================
   SERVICES — 1158
   ========================================================================== */
.services__title {
  left: calc(1575.5 * var(--u));
  top: calc(1158 * var(--u));
  font-size: calc(124 * var(--u));
  line-height: 0.98;
  background-image: none;
  -webkit-background-clip: border-box;
          background-clip: border-box;
  color: var(--c-purple-light);
}

.card {
  position: absolute;
  width: calc(509 * var(--u));
  /* 659 in Figma. +110 on 21 Sep: she asked for the cards to grow DOWN so
     the falling icons have somewhere to settle — the extra is a shelf under
     the link (padding-bottom), not more room between the words. */
  /* 769 -> 739 (shelf 110 -> 80) -> 669: the last 70 came out of the gap
     between the number and the title, her call 21 Sep 2026. */
  height: calc(669 * var(--u));
  padding: calc(48 * var(--u));
  padding-bottom: calc(128 * var(--u));
  border: max(1px, calc(1 * var(--u))) solid #F7F7F7;
  border-radius: var(--r-card);
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: space-between;
}
/* Reading order is RTL, so 01 is the first card on screen. A tenth of a
   second apart is enough to read as a cascade rather than a block. */
.card--02 { transition-delay: 0.1s; }
.card--03 { transition-delay: 0.2s; }

/* Above .icon-fall__ink--card, which is above the cards. NOTHING on .card
   itself may set z-index: the moment it does it becomes a stacking context
   and its children can no longer rise over an element outside it. */
.card > * { position: relative; z-index: 3; }

.card__num {
  /* COOPERATIVE, not SdAtletico.
     The frame still assigns SdAtletico:Regular to the five numbers (nodes
     3444:1159 / 1166 / 1173 / 1185 / 1188), but she says that font is not
     part of the designs and is not wanted — and the project never had its
     Regular cut anyway: assets/fonts/ carries only SdAtletico-Bold, so the
     400 face 404'd on every load and fell back. Cooperative is this page's
     display face and the one tokens.css already names as the intended
     replacement ("the Figma file has not moved over to Cooperative yet").
     index.html and home.html still use --f-display-legacy for their own
     numbers; changing those is a separate decision, see docs/mentoring.md. */
  font-family: var(--f-display);
  font-weight: var(--fw-reg);
  font-size: calc(48 * var(--u));
  line-height: 0.98;
  text-align: center;
}
.card__body { display: flex; flex-direction: column; gap: calc(36 * var(--u)); width: 100%; }
.card__head { display: flex; flex-direction: column; gap: calc(48 * var(--u)); align-items: flex-end; width: 100%; text-align: right; }
.card__title { width: calc(337 * var(--u)); font-size: calc(48 * var(--u)); line-height: 0.9; }
.card__text  { width: 100%; font-size: calc(20 * var(--u)); line-height: 1.3; }
.card__link  { width: 100%; font-size: calc(20 * var(--u)); line-height: 1.3; text-decoration: underline; }

/* 01 and 03 sit ON the dark band, so they take the light-on-dark tuning and
   a spread shadow; 02 is a light card and Figma gives it a drop-shadow. */
.card--dark {
  color: #F7F7F7;
  font-weight: var(--fw-light);
  /* No shadow: she wants the stroke alone, nothing that reads as blur. */
}
.card--dark .card__num,
.card--dark .card__link { color: var(--c-purple-light); }

.card--light {
  background: #F7F7F7;
  color: var(--c-dark);
  font-weight: var(--fw-light-on-white);
  /* box-shadow, not drop-shadow: a filter forces a GPU texture, and the rule
     on this project is that mobile carries none. docs/traps.md. */
  /* No shadow (21 Sep 2026) — the stroke only. */
}
.card--light .card__num,
.card--light .card__link { color: var(--c-purple); }

.card--01 { left: calc(1236 * var(--u)); top: calc(1431 * var(--u)); }
.card--03 { left: calc(174 * var(--u));  top: calc(1431 * var(--u)); }
/* Figma staggers 02 down by 87 (top 1518). She asked for the three levelled,
   so the row now shares one top and one bottom — which is also the line the
   falling icons land on. A deliberate departure from the frame. */
.card--02 { left: calc(705 * var(--u));  top: calc(1431 * var(--u)); }


/* ==========================================================================
   AUDIENCE — 2407
   ========================================================================== */
.audience__title {
  left: 50%;
  top: calc(2407 * var(--u));
  font-size: calc(124 * var(--u));
  line-height: 0.98;
  background-image: none;
  -webkit-background-clip: border-box;
          background-clip: border-box;
  color: var(--c-purple-light);
}

/* --- the rows are a STACK, and the white one is the HOVER state ----------
   Her reading of the frame (20 Sep 2026): rows 01 and 03 are the resting
   state and row 02 is what a row looks like under the pointer. So all three
   rest collapsed, and the hovered one expands into the white treatment, grows
   the purple box around its title, brings in its brackets and the
   "בואו נתחיל!" cursor, and links to WhatsApp.

   They are a FLOW STACK inside one positioned container, not three absolute
   rows: the frame already stacks them contiguously — 2667 + 137.2 = 2804.2,
   2804 + 284.4 = 3088.4 ~ 3089 — so an expanding row has to push the ones
   under it down, and only flow does that for free.

   ONE LAYOUT IN BOTH STATES. flex-direction cannot be transitioned, so the
   row is a column throughout and the number is taken out of flow: that way
   the title's right edge stays on 1572 in both states (collapsed 578..1572
   with the number at 1716, expanded 882.5..1573) and nothing jumps.
   ------------------------------------------------------------------------ */
.audience__list {
  position: absolute;
  left: 0;
  top: calc(2667 * var(--u));
  width: calc(1921 * var(--u));
}

/* A QUIET CROSS-FADE, not a wipe. The first pass gave this the buttons'
   masked circle growing out of the pointer; she asked for something more
   delicate, so the white simply arrives — half a second, soft ease, and a
   beat slower than the row's own opening so the colour settles after the
   row has finished moving rather than racing it. */
.arow::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: #FFFFFF;
  opacity: 0;
  transition: opacity 0.5s var(--ease-soft);
}
.arow:hover::before,
.arow:focus-visible::before { opacity: 1; }

.arow {
  position: relative;
  isolation: isolate;
  --mx: 50%;
  --my: 50%;
  display: flex;
  direction: ltr;
  flex-direction: column;
  align-items: flex-end;
  /* TOP-ALIGNED, not centred. Centring measures the whole stack, so a row
     whose note happens to wrap to one line instead of two centres a shorter
     column and its title drops 15.6 — row 01's copy is one line where 02 and
     03 take two, and the three stopped matching. Anchored to the padding
     edge, the title lands on 48 and the note on 172.8 in EVERY row whatever
     its length, which is what "בול כמו 2" means and is also Figma's own
     48.2 / 173. */
  justify-content: flex-start;
  /* NO FLEX GAP. A gap applies between items whatever their size, so a
     collapsed row would still reserve 32 between its title and its
     zero-height note and the title would sit 16 high — which is exactly how
     row 02 stopped matching rows 01 and 03 at rest. The spacing lives on the
     note's own margin instead, and collapses with it. */
  gap: 0;
  height: calc(137.2 * var(--u));
  padding: calc(48 * var(--u)) calc(348 * var(--u)) calc(48 * var(--u)) calc(48 * var(--u));
  border-bottom: max(1px, calc(1 * var(--u))) solid rgba(247, 247, 247, 0.5);
  color: #F7F7F7;
  font-weight: var(--fw-light);
  cursor: pointer;
  overflow: hidden;
  transition: height var(--dur-base) var(--ease-rise),
              background-color var(--dur-base) var(--ease-soft),
              color var(--dur-base) var(--ease-soft),
              border-color var(--dur-base) var(--ease-soft);
}

.arow__text {
  direction: rtl;
  font-size: calc(48 * var(--u));
  line-height: 0.9;
  text-align: right;
  white-space: nowrap;
  /* the purple box is always here, just transparent and unpadded, so the
     border and the padding can both animate in */
  border: max(1px, calc(3 * var(--u))) solid transparent;
  padding: 0;
  transition: border-color var(--dur-base) var(--ease-soft),
              padding var(--dur-base) var(--ease-rise),
              color var(--dur-base) var(--ease-soft);
}

/* out of flow, so collapsing it moves nothing */
.arow__num {
  position: absolute;
  right: calc(175 * var(--u));
  top: 50%;
  translate: 0 -50%;
  font-family: var(--f-display);
  font-weight: var(--fw-reg);
  font-size: calc(48 * var(--u));
  line-height: 0.98;
  text-align: center;
  color: var(--c-purple-light);
  transition: opacity var(--dur-fast) var(--ease-soft),
              transform var(--dur-base) var(--ease-out);
}

/* The note takes NO SPACE while the row rests — otherwise it centres the
   title against a box that includes it and row 02 sits higher than 01 and 03.
   A 0fr -> 1fr grid row is the one way to animate from nothing to
   content-height; `height: auto` cannot be transitioned. */
.arow__noteWrap {
  display: grid;
  grid-template-rows: 0fr;
  width: 100%;
  margin-top: 0;
  transition: grid-template-rows var(--dur-base) var(--ease-rise),
              margin-top var(--dur-base) var(--ease-rise);
}
.arow__note {
  direction: rtl;
  overflow: hidden;
  min-height: 0;
  font-size: calc(24 * var(--u));
  line-height: 1.3;
  text-align: right;
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-soft);
}

/* the bullet Figma draws beside rows 01 and 03 — now on every row, so the
   three are identical at rest. Row-relative, so it travels with its row as
   the stack opens and closes. */
/* ANCHORED TO THE TOP, not centred. Centred, it slid 73 down the moment a
   row expanded and ended up beside the note instead of the title. Measured
   off the frame: row 03 starts at 3085.9 and its bullet's ink at 3126.3, so
   40.4 from the row's own top — which is 7.7 above where centring put it
   even at rest.

   AND IT IS A MASK, not an <img>. The frame only draws it on 01 and 03 and
   she asked for it on all three; as a white PNG it then vanished on the white
   hover row. Painted with currentColor it follows the row into and out of
   the white state for free. */
.arow__bullet {
  position: absolute;
  left: calc(175 * var(--u));
  top: calc(39 * var(--u));
  transition: opacity var(--dur-fast) var(--ease-soft);
  width: calc(41 * var(--u));
  height: calc(41 * var(--u));
  background: currentColor;
  -webkit-mask: url("../assets/svg/mentoring/bullet.svg") no-repeat center / contain;
          mask: url("../assets/svg/mentoring/bullet.svg") no-repeat center / contain;
}

/* The title sits in its own box so the brackets and the cursor can be pinned
   to ITS edges rather than to a Figma x. The frame puts the brackets at 872
   and 1564 against a 882.5..1573 title — straddling its two corners — and the
   cursor at 389.52. Those are right for row 02's width only; row 03's title
   is 1189 wide and the cursor would land inside it. Anchored to the box, all
   three rows are correct at any length. */
.arow__titlewrap {
  position: relative;
  direction: ltr;
  display: inline-block;
}

.arow__bracket {
  position: absolute;
  top: 50%;
  width: calc(17.092 * var(--u));
  height: calc(109.059 * var(--u));
  translate: -50% -50%;
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-soft);
}
.arow__bracket--l { left: 0; }
.arow__bracket--r { left: 100%; }

.arow__you {
  position: absolute;
  right: 100%;
  margin-right: calc(24 * var(--u));
  top: 50%;
  display: flex;
  align-items: flex-start;
  gap: calc(6 * var(--u));
  opacity: 0;
  transform: translateY(calc(10 * var(--u)));
  transition: opacity var(--dur-fast) var(--ease-soft),
              transform var(--dur-base) var(--ease-out);
}
.arow__you .cursor-arrow { position: static; translate: none; }
.arow__you .cursor-badge {
  position: static;
  padding: calc(6 * var(--u)) calc(10 * var(--u));
}

/* ---- the hover state: row 02 as the frame draws it ---------------------- */
.arow:hover .arow__bullet,
.arow:focus-visible .arow__bullet { opacity: 0; }

.arow:hover,
.arow:focus-visible {
  height: calc(284.4 * var(--u));
  color: var(--c-dark);
  font-weight: var(--fw-light-on-white);
}
.arow:hover .arow__text,
.arow:focus-visible .arow__text {
  border-color: var(--c-purple);
  padding: calc(26 * var(--u)) calc(28 * var(--u));
  color: var(--c-purple);
}
.arow:hover .arow__num,
.arow:focus-visible .arow__num {
  opacity: 0;
  transform: translateX(calc(20 * var(--u)));
}
.arow:hover .arow__noteWrap,
.arow:focus-visible .arow__noteWrap {
  grid-template-rows: 1fr;
  margin-top: calc(32 * var(--u));
}
.arow:hover .arow__note,
.arow:focus-visible .arow__note { opacity: 1; }
.arow:hover .arow__bracket,
.arow:focus-visible .arow__bracket { opacity: 1; }
.arow:hover .arow__you,
.arow:focus-visible .arow__you { opacity: 1; transform: translateY(0); }

/* ...and while a mouse is actually over the row it stops being a label beside
   the title and becomes the POINTER, moving with her. left/top are written
   inline every frame by js/mentoring.js; the 9/9 nudge puts the arrow's tip
   under the pointer rather than its centre, exactly as the hero's does. */
.arow.is-cursor-live .arow__you {
  position: fixed;
  right: auto;
  margin-right: 0;
  top: 0;
  left: 0;
  z-index: 10000;
  translate: calc(9 * var(--u)) calc(9 * var(--u));
}
/* While it is the pointer it takes the hero cursor's exact arrangement —
   the arrow CENTRED on the container's origin and the badge at its measured
   offset — so the tip lands 9/9 from the pointer here too. Left as a flex
   row it hung 21 right and 31 below, because a static flex item starts at the
   container's corner instead of on it. */
.arow.is-cursor-live .arow__you .cursor-arrow {
  position: absolute;
  left: 0;
  top: 0;
  translate: -50% -50%;
}
.arow.is-cursor-live .arow__you .cursor-badge {
  position: absolute;
  left: calc(14.32 * var(--u));
  top: calc(13.36 * var(--u));
}

/* the real pointer gets out of the way for as long as it is live */
body.row-live,
body.row-live * { cursor: none; }

@media (prefers-reduced-motion: reduce) {
  .arow, .arow__text, .arow__num, .arow__note, .arow__noteWrap, .arow__bracket, .arow__you {
    transition-duration: 0.01ms;
  }
}



/* ==========================================================================
   ABOUT — 3413
   ========================================================================== */

/* The ghost "ABOUT ME" wordmark (3444:1156) is GONE — removed 21 Sep 2026 at
   her request ("זה מעמיס לי מדי"). Do not bring it back from Figma. */

/* THE WHOLE ABOUT BLOCK SITS 60 ABOVE THE FRAME — photo, name, tag, bio, CTA
   and spark alike. Her call after seeing it 1:1, 21 Sep 2026 ("תעלה טיפה").
   The Figma numbers below are the frame's; the `top`s are frame - 60. */

/* 3444:1157, AS SHE RE-CUT IT IN FIGMA 21 Sep 2026: frame (1239, 3375)
   770 x 974, so centred on 1624. The picture inside is cropped by the fill's
   imageTransform [[1.04168, 0, -0.05737], [0, 1.12685, 0]]: 1/1.04168 = 96.0%
   wide starting 0.05737/1.04168 = 5.507% in, 1/1.12685 = 88.74% tall. */
.about__photo {
  position: absolute;
  left: calc(1624 * var(--u));
  top: calc(3315 * var(--u));
  width: calc(770 * var(--u));
  height: calc(974 * var(--u));
  translate: -50% 0;
  overflow: hidden;
  /* 0.8, the frame's value. It never showed: the reveal's `[data-anim].is-in`
     outranks this class and set opacity back to 1, so the photo was fully
     opaque until 21 Sep 2026, when she asked for it lighter. --o-rest is what
     the reveal restores to. */
  opacity: 0.8;
  --o-rest: 0.8;
}
.about__photo img {
  position: absolute;
  left: 5.507%;
  top: 0;
  width: 96%;
  height: 88.743%;
  max-width: none;
}

/* 3444:1272 — a 1006-wide box at x 216 whose text is right-aligned */
.about__name {
  position: absolute;
  left: calc(216 * var(--u));
  top: calc(3487 * var(--u));
  width: calc(1006 * var(--u));
  font-family: var(--f-display);
  font-size: calc(124.496 * var(--u));
  line-height: 0.98;
  color: var(--c-purple-light);
  text-align: right;
}

/* 3444:1274 — right edge pinned to 1222, 1048 wide */
.about__bio {
  position: absolute;
  left: calc(174 * var(--u));          /* 1222 - 1048 */
  top: calc(3742 * var(--u));
  width: calc(1048 * var(--u));
  font-size: calc(24 * var(--u));      /* 28 -> 24 (her call, 5 Oct: one scale across the site) */
  line-height: 1.3;
  color: #F7F7F7;
  font-weight: var(--fw-light);
  text-align: right;
}
.about__bio b { font-weight: var(--fw-bold); }

.about__cta {
  position: absolute;
  left: calc(173 * var(--u));
  top: calc(var(--about-cta-top, 4075) * var(--u));
  width: calc(423 * var(--u));         /* 494 at 28; the same proportion at 24 */
  padding: calc(12 * var(--u)) calc(36 * var(--u));
  font-size: calc(24 * var(--u));      /* as the text above it (5 Oct) */
}

/* the "Web Designer" badge (3482:424) */
.about__tag {
  position: absolute;
  left: calc(518 * var(--u));
  top: calc(3586 * var(--u));
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: calc(26 * var(--u)) calc(48 * var(--u));
  border: max(1px, calc(3 * var(--u))) solid #F7F7F7;
  background: rgba(255, 255, 255, 0.1);
  color: var(--c-purple-light);
  font-size: calc(32 * var(--u));
  line-height: 0.9;
  white-space: nowrap;
  /* Figma puts a 4.35px backdrop-blur here. NOT implemented, on the same
     rule as everything else on this page — and at 4.35px over a 10% white
     wash there is nothing to see. */
}
.about__tag-bracket {
  position: absolute;
  top: calc(3579 * var(--u));
  width: calc(17.092 * var(--u));
  height: calc(101.059 * var(--u));
}
.about__tag-bracket--r { left: calc(797 * var(--u)); }
.about__tag-bracket--l { left: calc(509 * var(--u)); }

/* 3482:429 — frame (639, 4053) 93.296 x 93.362 -> centre (685.648, 4099.681),
   the mark inside 75.158 x 75.255 rotated 16.34deg */
.about__spark {
  position: absolute;
  /* smaller (5 Oct), and kept where it was against the button: 18.6 past
     its end, 35.3 above its top */
  left: calc((173 + 423 + 18.6) * var(--u));
  top: calc((var(--about-cta-top, 4075) - 35.3) * var(--u));
  width: calc(52 * var(--u));
  height: calc(52.07 * var(--u));
  translate: -50% -50%;
  rotate: 16.34deg;
}


/* ==========================================================================
   PLANS — 4915.54
   --------------------------------------------------------------------------
   FINISHED IN FIGMA 20 Sep 2026 (3506:478) and rebuilt from it. A 1223 row
   centred on the artboard at 5173, two cards sharing a 48 gap — `flex: 1`
   each, so 587.5 — and inside each a head block, a 295 rule, a checked list
   and a CTA.

   `align-items: stretch`, where the frame says `center`. In Figma both cards
   are 698 because Figma's own text metrics make them so; ours are set in
   fallback faces until the licence clears, so their natural heights will not
   agree to the pixel. Stretched they always share a top and a bottom, which
   is what the eight corner handles — and the frame — actually promise.
   ========================================================================== */
.plans__title {
  left: calc(960.5 * var(--u));
  top: calc(4795.54 * var(--u));
  font-size: calc(124 * var(--u));
  line-height: 0.98;
  background-image: none;
  -webkit-background-clip: border-box;
          background-clip: border-box;
  color: var(--c-purple);
}

.plans__row {
  position: absolute;
  left: calc(50% - 0.5 * var(--u));
  top: calc(5053 * var(--u));
  translate: -50% 0;
  width: calc(1223 * var(--u));
  display: flex;
  align-items: stretch;
  gap: calc(48 * var(--u));
}

.plan {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(47 * var(--u));
  padding: calc(64 * var(--u));
  border: max(1px, calc(1 * var(--u))) solid var(--c-purple);
  /* HER CALL, and not in the frame: the frame leaves these cards unfilled.
     The dot texture showing through them was the muddle, so they take the
     page's own ground as a fill and the dots simply stop at the border. */
  background: #F7F7F7;
}

/* the corner handles are 21.93 here, not the hero's 17 */
.plan__handle {
  position: absolute;
  width: calc(21.93 * var(--u));
  height: calc(21.93 * var(--u));
  background: #F7F7F7;
  border: max(1px, calc(1 * var(--u))) solid var(--c-purple);
  rotate: 0.2deg;
  translate: -50% -50%;
}
/* On the card's own corners rather than on frame coordinates, so they hold
   whatever the card's height turns out to be. */
.plan__handle--tl { left: 0;    top: 0; }
.plan__handle--tr { left: 100%; top: 0; }
.plan__handle--bl { left: 0;    top: 100%; }
.plan__handle--br { left: 100%; top: 100%; }

.plan__head {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(43 * var(--u));
  width: calc(381 * var(--u));
  color: var(--c-dark);
  text-align: center;
}
/* The frame gives the three-session card a wider head than the single one. */
.plan__head--wide { width: calc(437 * var(--u)); }

.plan__intro {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(18 * var(--u));
  width: 100%;
}
.plan__title {
  font-family: var(--f-display);
  font-weight: var(--fw-reg);
  font-size: calc(64 * var(--u));
  line-height: 0.98;
  width: 100%;
}
.plan__desc {
  font-weight: var(--fw-light-on-white);
  font-size: calc(20 * var(--u));
  line-height: 1.3;
  width: 100%;
}

.plan__price {
  display: flex;
  align-items: flex-end;
  gap: calc(10 * var(--u));
  padding: calc(12 * var(--u)) calc(64 * var(--u));
  border-radius: calc(12 * var(--u));
  background: rgba(105, 94, 190, 0.1);
  white-space: nowrap;
}
.plan__unit {
  font-weight: var(--fw-reg);
  font-size: calc(24 * var(--u));
  line-height: 0.98;
}
.plan__sum {
  font-family: var(--f-display);
  font-weight: var(--fw-reg);
  font-size: calc(48 * var(--u));
  line-height: 0.98;
}

/* Vector 34: 295 x 0.5, #9F93FF. Floored at a whole pixel — below that the
   browser fades the line instead of drawing it. */
.plan__rule {
  width: calc(295 * var(--u));
  height: max(1px, calc(0.5 * var(--u)));
  background: var(--c-purple-light);
}

.plan__foot {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(64 * var(--u));
}
.plan__list {
  display: flex;
  align-items: center;
  gap: calc(9 * var(--u));
}
.plan__lines {
  font-weight: var(--fw-light-on-white);
  font-size: calc(20 * var(--u));
  line-height: 1.3;
  color: var(--c-dark);
  text-align: right;
  white-space: nowrap;
}
.plan__lines p { margin: 0; }

/* The checks are a COLUMN beside the block, not one per line: the frame
   stacks four 18s on an 8 gap (96) against four 26-tall lines (104) and
   centres the two against each other. Reproduced as drawn. */
.plan__checks {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: calc(8 * var(--u));
  width: calc(18 * var(--u));
}
.plan__checks span {
  width: calc(18 * var(--u));
  height: calc(18 * var(--u));
  background: var(--c-purple);
  -webkit-mask: url("../assets/svg/mentoring/check-circle.svg") no-repeat center / contain;
          mask: url("../assets/svg/mentoring/check-circle.svg") no-repeat center / contain;
}

.plan__cta {
  width: calc(382 * var(--u));
  padding: calc(12 * var(--u)) calc(36 * var(--u));
  border-radius: calc(100 * var(--u));
  font-size: calc(24 * var(--u));      /* 28 -> 24 (5 Oct) */
  line-height: 1.591;
  font-weight: var(--fw-light-on-white);
}
/* The two plan CTAs are the site button, not a local one: the solid card
   takes btn--solid btn--deep, exactly the hero's, and the outlined card takes
   btn--ghost, which is its exact mirror — see the button block. */


/* ==========================================================================
   CONTACT AND FOOTER
   ========================================================================== */

.contact__mark {
  left: 50%;
  top: calc(6010.46 * var(--u));
  font-size: calc(647 * var(--u));
  /* MEASURED, not Figma's literal. Figma says -12.94; at that value Chrome
     paints the ink 1948 wide against Figma's own 1920 render — 28 over, which
     on a wordmark that bleeds to both artboard edges is visible. -16.1111
     reproduces the frame exactly. The same disagreement home.html's WEBSITES
     has (-36.67 -> -42.385).
     DESIGN and ABOUT ME were measured the same way and need NO correction:
     both land on Figma's ink to the pixel at the literal tracking. Which is
     the whole reason each wordmark is measured on its own. */
  letter-spacing: calc(-16.1111 * var(--u));
  /* Figma's angle is 0.0000024deg, i.e. 0 — a CSS 0deg gradient runs BOTTOM
     to TOP, which is the order these stops are written in. */
  background-image: linear-gradient(0deg,
      rgba(105, 94, 190, 0) 8.225%,
      rgba(88, 78, 162, 0.414) 20.63%,
      rgb(63, 56, 123) 47.799%,
      rgb(32, 27, 73) 91.063%);
}

/* 141 tall in the frame, but the artboard ends at 7019 and clips it to
   101.54. The other two pages made the same trim. */
.foot {
  position: absolute;
  left: 0;
  top: calc(6544.46 * var(--u));
  width: calc(1919 * var(--u));
  height: calc(101.54 * var(--u));
  border-top: max(1px, calc(1 * var(--u))) solid var(--c-purple);
  background: rgba(247, 247, 247, 0.59);
  z-index: 3;
}

.foot__copy {
  position: absolute;
  left: calc(955.5 * var(--u));
  top: calc(6581.46 * var(--u));
  translate: -50% 0;
  font-size: calc(16 * var(--u));
  line-height: 1.3;
  color: var(--c-purple);
  text-align: center;
  white-space: nowrap;
  z-index: 4;
}

.foot__social {
  position: absolute;
  left: calc(166 * var(--u));
  top: calc(6584.46 * var(--u));
  display: flex;
  align-items: center;
  gap: calc(20 * var(--u));
  z-index: 4;
}
.foot__social img { width: calc(23.667 * var(--u)); height: calc(23.667 * var(--u)); }

/* Right-aligned in the frame (translate-x-full), so the given x is the RIGHT
   edge. Pinned by `right` against the artboard rather than by a negative
   `left`: in RTL a negative left is real scrollable space, which is what shoved
   index.html's footer off screen. */
.foot__legal {
  position: absolute;
  top: calc(6579.46 * var(--u));
  font-size: calc(16 * var(--u));
  line-height: 2.16;
  color: var(--c-purple);
  text-decoration: underline;
  white-space: nowrap;
  z-index: 4;
}
.foot__legal--privacy { right: calc(434 * var(--u)); }   /* 1920 - 1486 */
.foot__legal--terms   { right: calc(293 * var(--u)); }   /* 1920 - 1627 */
.foot__legal--a11y    { right: calc(175 * var(--u)); }   /* 1920 - 1745 */

/* The four corner handles sit on the card's own corners, so their offsets are
   relative to .plan and come out the same for both cards (within 0.01). */

/* The bio's blank lines are Figma's own empty paragraphs (a zero-width space
   each), so they are real boxes and carry the 1.3 line-height. */
.about__bio p { margin: 0; }

/* ==========================================================================
   DIRECTION — why these containers are ltr inside an rtl document
   --------------------------------------------------------------------------
   Figma lays every auto-layout out in ITS OWN left-to-right model: "items-end"
   means the RIGHT edge and "justify-end" means packed RIGHT, whatever the
   language of the text inside. This document is dir="rtl", where flex-end is
   the LEFT — so every one of those frames came out mirrored: the header pill
   on the right instead of the left, the card numbers on the left instead of
   the right, the capsule tick after the words instead of before them.

   The fix is to give the LAYOUT BOX Figma's direction and give the TEXT its
   own. Flipping the keywords instead (flex-end -> flex-start) also works but
   has to be re-derived per box and silently breaks whenever a child is added.
   ========================================================================== */
.site-head,
.site-head__nav,
.capsule--note,
.foot__social,
.card,
.card__body,
.card__head,
.plans__row,
.plan,
.plan__head,
.plan__intro,
.plan__price,
.plan__foot,
.plan__list,
.plan__checks,
.arow { direction: ltr; }

/* ...and the text inside keeps the document's own direction, so Hebrew runs,
   the "←" arrows and mixed Latin/Hebrew strings all order correctly. */
.site-head__cta,
.site-head__nav a,
.card__title,
.card__text,
.card__link,
.card__num,
.arow__text,
.arow__boxed,
.arow__note,
.capsule--tag,
.cursor-badge,
.plan__title,
.plan__desc,
.plan__lines,
.plan__cta,
.capsule--note span { direction: rtl; }

/* ==========================================================================
   WIDTH ON CENTRED, ABSOLUTELY-POSITIONED BOXES
   --------------------------------------------------------------------------
   `translate: -50%` is a TRANSFORM: it moves the painted box and changes
   nothing about layout. So an absolutely-positioned shrink-to-fit element
   with `left: 1486.88` is still laid out from that x, and its available width
   is only what is left to the containing block's right edge — 433px here.
   The services capsule was being squeezed to 445 against a natural 479, its
   tick icon pushed out of the box entirely, and the whole capsule sat 15 off.

   `width: max-content` opts out of that fitting and lets the box be its own
   natural width, which is what Figma measured. Every centred nowrap element
   on this page needs it; LET'S TALK at 647px would otherwise be capped at
   half the artboard.
   ========================================================================== */
.display,
.capsule,
.hero__better,
.hero__made,
.hero__lede,
.plans__name,
.cursor-badge,
.about__tag { width: max-content; }

/* ==========================================================================
   GSAP CHARACTER REVEAL — js/mentoring-headings.js
   --------------------------------------------------------------------------
   The four Hebrew headings. Each character becomes its own inline-block so it
   can turn in 3D; the perspective lives on the heading.

   `perspective` makes the heading a containing block for absolutely
   positioned descendants. These four have none — they are leaves — but if a
   heading ever gains one, that is where it will have gone wrong.
   ========================================================================== */
[data-gsap-chars] { perspective: 600px; }
[data-gsap-chars] .gch {
  display: inline-block;
  transform-origin: 50% 100%;
  backface-visibility: hidden;
}

/* ==========================================================================
   THE ABOUT COPY IS WRITTEN BY THE SCROLL — js/about-reveal.js
   --------------------------------------------------------------------------
   The shared module, the same one index.html and home.html use. It wraps
   every word, numbers it, and puts ONE progress value --p on the container;
   each word then works out its own opacity from --p and its own index. One
   custom property changes per frame however long the text is.

   The + 8 / ÷ 8 is the width of the wet edge: eight words are part-way
   written at any moment, so it reads as a hand moving along the line rather
   than a row of switches.
   ========================================================================== */
.about__bio.is-writing .w {
  opacity: calc((var(--p, 0) * (var(--n) + 8) - var(--i)) / 8);
  will-change: opacity;
}
.about__bio.is-written .w { opacity: 1; }

/* ==========================================================================
   NO RAIN OVER THE CARDS
   --------------------------------------------------------------------------
   The dark rail runs 1102 → 4471 and its drops fall straight through the
   services band, which is now the icons' band and hers to keep clear. The
   drops live in their own layer (js/mentoring.js) so the hole can be punched
   without taking the grid LINES out with them — the lines run the whole
   height on every band and always have.

   Rail-local: the field is 1158 - 1102 = 56 to 2090 - 1102 = 988. The ramps
   are inside the band rather than hard stops, so a drop thins out as it
   reaches the cards instead of being cut off mid-streak.
   ========================================================================== */
.grid-rail__rain { position: absolute; inset: 0; }

.grid-rail--dark .grid-rail__rain {
  -webkit-mask-image: linear-gradient(to bottom,
      #000 0,
      transparent calc(56 * var(--u)),
      transparent calc(998 * var(--u)),
      #000 calc(1078 * var(--u)));
          mask-image: linear-gradient(to bottom,
      #000 0,
      transparent calc(56 * var(--u)),
      transparent calc(998 * var(--u)),
      #000 calc(1078 * var(--u)));
}

/* ==========================================================================
   THE ENTRANCE — everything rises into place as it is scrolled to
   --------------------------------------------------------------------------
   Her standing rule for the whole site, named against noab.co.il: as you
   scroll, each thing fades in and up, so the page reads as being built in
   front of you. index.html and home.html have carried this since they were
   built; this page was the one without it.

   Read off that site rather than guessed — every widget on it sits at
   `opacity: 0; transform: translateY(50px) scale(0.98) skewY(-0.5deg)` until
   a `.show` class arrives, with a 0.3s transition. Ours is the same gesture
   at the site's own tokens: 46 design px of travel and --dur-rise, which is
   1.15s. Slower than theirs on purpose — a short quick lift reads as a
   glitch, a long one as intent.

   THE TRANSFORM IS THE ONE FREE PROPERTY. Nearly everything on this page is
   placed with `translate:` and turned with `rotate:`, which are separate
   properties that apply AFTER transform — so this never fights an element's
   position, and `transform: none` at rest gives the element back untouched.
   Anything that drives its own `transform` (the hero's draggable items, the
   row cursor, the button arrow) must NOT carry data-anim.

   `will-change` lives only on the not-yet-revealed state. Once a thing has
   arrived it releases its compositing layer, which is what keeps fifty of
   these off the GPU at once. docs/traps.md.
   ========================================================================== */
[data-anim] {
  opacity: 0;
  transform: translateY(calc(46 * var(--u)));
  transition: opacity var(--dur-rise) var(--ease-rise),
              transform var(--dur-rise) var(--ease-rise);
  will-change: opacity, transform;
}

/* Restores to --o-rest rather than a hard 1, so an element meant to sit
   below full opacity keeps its value after revealing. */
[data-anim].is-in {
  opacity: var(--o-rest, 1);
  transform: none;
  will-change: auto;
}

/* The wordmarks are the largest things that move, so they travel further and
   take longer — at the shared speed they read as brisk. */
[data-anim="mark"] {
  transform: translateY(calc(64 * var(--u))) scale(0.985);
  transition-duration: var(--dur-slow);
}

@media (prefers-reduced-motion: reduce) {
  [data-anim],
  [data-anim].is-in {
    opacity: var(--o-rest, 1);
    transform: none;   /* safe: centring lives on the translate property */
    transition: none;
  }
}

/* ==========================================================================
   THE TWO BACKGROUND PLATES — her own exports, 20 Sep 2026
   --------------------------------------------------------------------------
   She sent “הירו ליווי” and “פוטר ליווי” because the built version did not
   look right. Each is the whole background group flattened: the frosted
   columns, the wash and every bloom in one 2267 x 1404 picture. Between them
   they replace, at each end of the page, a wave image, five glow gradients
   and a stripe gradient — nine elements down to one, and the hard line she
   reported through the plans goes with them.

   WHY THERE IS NO SEAM NOW. Both plates are fully opaque, and both fade to
   #F7F7F7 at their far end — which is the page's own ground. An opaque edge
   against the identical colour is not an edge. The old `.stripes--footer`
   began at `100% - 1293` (5473 on today's artboard) with an opaque white
   gradient and cut straight across the glow underneath it; that is the line
   in her screenshot.

   LEFT: 0, MEASURED. The column seams in the file land on 349, 524, 699,
   873, 1047, 1222, 1396 and 1569 — the page's own grid-line positions to the
   pixel, so the picture's x IS the design x.

   3.3MB of PNG re-encoded to 41KB of WebP. There is no image encoder on this
   machine, so it was done in the browser's own canvas and posted back to
   __scratch/server.js — see its `/__save` route.
   ========================================================================== */
.bg-plate {
  position: absolute;
  left: 0;
  width: calc(2267 * var(--u));
  height: calc(1404 * var(--u));
}
.bg-plate--hero { top: calc(-75.34 * var(--u)); }
/* Mirrored about the page, as the picture is mirrored: the hero hangs 75.34
   above the top, so this hangs 75.34 below the bottom. Bottom-anchored, never
   a page y — a page y is wrong the moment anything above it changes height. */
.bg-plate--footer { top: calc(100% - 1328.66 * var(--u)); }

/* ==========================================================================
   THE DOT FIELD ON THE PLANS BAND — js/dot-field.js
   --------------------------------------------------------------------------
   The texture index.html carries on its white bands, asked for here. Purple,
   because this band is white. It fades out at every edge: a grid of dots with
   a hard boundary reads as a box, not as a texture.

   z-index 0 and first in the section, so the two cards — which are
   positioned — paint over it.
   ========================================================================== */
.dot-field {
  position: absolute;
  pointer-events: none;
  z-index: 0;
}
.dot-field canvas { display: block; }

/* UP TO THE JAG, NOT TO A STRAIGHT LINE.
   A vertical gradient gave the dots a horizontal top edge sitting well below
   the dark shape — “שלא יפסקו בשורה”. The dark shape's bottom edge is a
   POLYLINE, so the mask is that polyline: shape-plans.svg is dark-band.svg's
   own bottom run, offset 8 down for clearance and closed into a solid below
   itself. The dots now rise to the jag and stop on it, which is the same
   thing index.html does with shape-rect112.svg.

   Field 4400 -> 5960, so the shape's 1560 viewBox IS its box, 1:1, and the
   polyline lands where the dark does. Its points, page coordinates:
       (0,4471) (247.5,4471) (595.5,4769.5) (771.5,4769.5)
       (1096.5,4672) (1488,4610.5) (1920,4874)
   Three masks intersected: the shape for the top, a vertical fade for the
   bottom into LET'S TALK, and a horizontal one so the grid never ends on a
   hard vertical. */
.dot-field--plans {
  left: 0;
  top: calc(4280 * var(--u));
  width: calc(1920 * var(--u));
  height: calc(1560 * var(--u));
  -webkit-mask-image: url("../assets/svg/mentoring/shape-plans.svg"),
                      linear-gradient(#000 0%, #000 90%, #0000 100%),
                      linear-gradient(to right, #0000 0%, #000 4%, #000 96%, #0000 100%);
          mask-image: url("../assets/svg/mentoring/shape-plans.svg"),
                      linear-gradient(#000 0%, #000 90%, #0000 100%),
                      linear-gradient(to right, #0000 0%, #000 4%, #000 96%, #0000 100%);
  -webkit-mask-size: 100% 100%;
          mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  -webkit-mask-composite: source-in;
          mask-composite: intersect;
}

/* ==========================================================================
   LET'S TALK — the canvas warp, js/warp-text-gradient.js
   --------------------------------------------------------------------------
   The same effect home.html gives its own LET'S TALK, and the same module:
   that fork exists because of the INK, not the page. A purple-gradient
   wordmark cannot take js/warp-text.js's chromatic split — it multiplies
   every fringe by 0.41 of red or 0.75 of blue and the split turns to muddy
   noise — so the fringe is built from coverage instead. index.html keeps the
   original, because its wordmark is white.

   `data-tracking="0"` on the element and NOT a repeat of the CSS value: the
   module ADDS its tracking to whatever the stylesheet already has.
   ========================================================================== */
.display.is-warped {
  background-image: none !important;
  color: transparent;
}

.warp-text {
  --warp-bleed: 16%;
  position: absolute;
  inset: calc(-1 * var(--warp-bleed));
  display: block;
  pointer-events: none;
}

.warp-text canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}

/* ==========================================================================
   THE HEADER — two of them, and she is choosing
   --------------------------------------------------------------------------
   "העמוד הזה הוא חלק מהאתר" — so the menu is the site's menu, and the links
   point at home.html's sections rather than at nothing. Only אודות exists on
   this page and keeps its in-page anchor.

   She is deciding between this page's flat bar and home.html's floating
   capsule, so BOTH are here and one attribute switches them:

       <body data-head="round">   home.html's capsule  (the default)
       <body data-head="flat">    this page's own bar

   The markup is identical for both — same children, same order, same logo
   box — because the two headers only ever differed in the bar itself. What
   follows is the whole of that difference, ten declarations.
   ========================================================================== */
[data-head="round"] .site-head {
  position: fixed;
  /* THE FLAT BAR IS CENTRED WITH `translate: -50%`; the capsule is not — it
     carries its own offset in `left`. Leaving the translate on shoved it 785
     off the page, which is a whole header sitting at x -612. */
  translate: none;
  top: calc(49 * var(--u));
  /* 174 into a centred 1920 artboard. The capsule is position:fixed and
     cannot see .page, so it repeats that centring itself. */
  left: calc(50% - 786 * var(--u));
  width: calc(1571 * var(--u));
  /* 63 -> 71, 21 Sep 2026: she wanted more air round the button. The CTA
     keeps its 49 and the capsule grows round it. */
  height: calc(71 * var(--u));
  /* The CTA pill sits in the capsule with ONE inset on its three free sides
     — 10 top, bottom and left — so it reads as a pill nested in a pill. It
     used to touch 7 / 7 / 12 and looked jammed into the corner (her note,
     21 Sep 2026). */
  padding: calc(10 * var(--u)) calc(36 * var(--u)) calc(10 * var(--u)) calc(10 * var(--u));
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, 0.8);
  border: 1px solid rgba(13, 9, 20, 0.06);
  z-index: 150;                      /* over the page, under the FAB (200) */
}

/* The capsule is 63 where the bar is 103, so the links close up to fit. */
[data-head="round"] .site-head__nav { gap: calc(64 * var(--u)); }   /* 48 -> 64, 21 Sep: she asked for air */
[data-head="round"] .site-head__cta {
  align-self: stretch;          /* the capsule's height less the inset, top and bottom */
  height: auto;
  padding: 0 calc(28 * var(--u));
  width: auto;
}


/* ==========================================================================
   IN-PAGE LINKS (22 Sep 2026)
   --------------------------------------------------------------------------
   The menu is this page's own now: four links to its headings. They glide
   rather than jump, and stop with the heading clear of the floating header
   (49 + 71 + air). The headings, not the sections: on the desktop every
   section is a 0-tall box, since everything in it is placed on the artboard.
   ========================================================================== */
html { scroll-behavior: smooth; }
#services-title,
#audience-title,
#about-name,
#plans-title { scroll-margin-top: calc(170 * var(--u)); }

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

/* LET'S TALK — EXACTLY the home page's (her call, 4 Oct): Degolan 794.447,
   tracking 0, line-height 0.96, centred, Chrome's 0.0903em ink lift, the
   home page's warp settings. The colour stays this page's purple gradient: the home
   page's white one would vanish on this light ground. */
@media (min-width: 900px) {
  .display.contact__mark {
    font-family: "Degolan", "Cooperative", "Arial Narrow", sans-serif;
    font-size: calc(794.447 * var(--u));
    letter-spacing: 0;
    line-height: 0.96;
    margin-top: -0.0903em;
    left: 50%;
    translate: -50% 0;
    width: max-content;
  }
}

/* THE HERO, raised 90 (her call, 4 Oct): with DESIGN in Degolan (taller at
   the same width) its foot ran into the lede "1:1 איתי בזום"; the whole
   group — tag, DESIGN, BETTER and its selection, "Made for designers", the
   badge — goes up together. DESIGN's own margin is site-degolan's ink lift,
   so it moves by its top. */
@media (min-width: 900px) {
  .hero .hero__title { top: calc((229.14 - 60) * var(--u)); }   /* and the whole hero 25 up again (her sixth look) */   /* -90, 25 back down, then the whole hero 30 down (her fourth look) */
  .hero .hero__better,
  .hero .hero__select,
  .hero .handle,                 /* the four corner squares carry .handle, not .hero__handle */
  .hero .hero__made,
  .hero .hero__star,
  .hero .hero__you { margin-top: calc(-60 * var(--u)); }
  /* her second look: the tag a little higher again, and the lede, the line
     under it and the button up a little */
  .hero .capsule--tag { margin-top: calc(-100 * var(--u)); }
  /* her fifth look: a touch more air between the group above and the lede */
  .hero .hero__lede,
  .hero .hero__sub,
  .hero .hero__cta { margin-top: 0; }
  .hero .hero__mark { margin-top: calc(5 * var(--u)); }   /* the two corner marks ride along */
}

/* THE SITE'S LOGO + MENU on this page's light grounds: back to the site's ink,
   as on every other page (her call, 7 Oct — the deep purple #4E4596 of 4 Oct is gone) */

/* BIGGER GRAB AREAS for the hero's small draggable things (her call, 4 Oct:
   "Made for designers" and the little ones were hard to catch). The visible
   things do not change: text and the corner squares get an invisible
   ::after around them; the pictures (the badge, the two stars) get a
   transparent padding ring — js/mentoring-hero.js takes the padding off
   again when it draws the selection, so the frame still hugs the picture. */
.hero__made::after {
  content: "";
  position: absolute;
  inset: calc(-14 * var(--u)) calc(-18 * var(--u));
}
.hero .handle::after {
  content: "";
  position: absolute;
  inset: calc(-12 * var(--u));
}
.hero__star,
.hero__mark {
  box-sizing: content-box;
  padding: calc(14 * var(--u));
  translate: calc(-14 * var(--u)) calc(-14 * var(--u));
}

/* THE HERO ENTRANCE (5 Oct): until DESIGN has dropped, the rest waits —
   js/mentoring.js lifts html.hero-wait and fades each in out of a blur */
html.hero-wait .hero :is(.capsule--tag, .hero__better, .hero__select, .handle, .hero__made,
  .hero__mark, .hero__star, .hero__lede, .hero__sub, .hero__cta, .hero__you) {
  opacity: 0;
  filter: blur(8px);
}

/* 5 Oct: the bio at 24 ends at 3960; the button keeps its 78 under it */
.about { --about-cta-top: 4038; }

/* THE ARROW IS THE POINTER (5 Oct, her note "nothing happens"): the hero's
   -60 lift (.hero .hero__you margin-top) also moved the following arrow 60
   above the real pointer, so it pointed at the button while the click landed
   under it. Following the pointer, no offset but the tip's own. */
.hero .hero__you.is-cursor { margin-top: 0 !important; }
