/* ==========================================================================
   Lumi Libra — style.css
   Fonts:  Fraunces (headings, tagline, pull-quotes — stands in for Recoleta)
           Satoshi (body, labels, buttons, nav — Regular / Medium)
   ========================================================================== */

/* ==========================================================================
   Palette — sampled from `colored background mock.png` with Pillow, not eyeballed.

   This replaces the pale watercolour set. Three things changed:
     · Colour commits. The illustration colours are saturated blocks now, not
       tints — Lauren's note was that the old palette was "too pale and washy".
     · Display headings go NAVY. Teal drops to an accent role: eyebrows, rules,
       small labels. It used to carry every heading on the site.
     · The paper stays COOL. The mock's ground is a warm cream (#FBF5EB) and
       Lauren explicitly kept the cooler off-white instead, so every colour below
       is sampled from a cream ground but has to sit on a neutral one. Watch the
       warm greens and golds for muddiness because of that mismatch.
   ========================================================================== */
:root {
  /* ---- Primary ---- */
  --navy: #212E39;        /* display headings. Mock Who-panel heading #212E39 */
  --teal: #3E8C8A;        /* accent + buttons, darkened off the blob teal for contrast */
  --teal-deep: #2E6E6D;   /* hover / pressed */
  --teal-dark: #2E6E6D;   /* legacy alias */
  --teal-label: #3D6F71;  /* small caps labels. Mock eyebrow #417779 */
  /* Text set ON --panel-teal. --teal-deep is only 4.18:1 there, which fails AA
     at body size; this is the same hue and saturation dropped in lightness
     until it clears, 4.8:1. Used for the email fields' placeholder. */
  --teal-ink: #2A6362;
  /* The blue Lauren picked out of the "Who Lumi Libra Is For" panel — a cool
     slate rather than the near-black the body copy used to be. */
  --ink: #40494E;         /* body. Mock Who-panel list text #40494E */
  --script-blue: #4E6D79; /* script lines. Mock Who-panel closing script #4E6D79 */
  --bullet-blue: #7D929F; /* list marks. Mock Who-panel hearts #7D929F */
  --soft-white: #FDFDFD;  /* the page ground — cool, per Lauren, NOT the mock's cream */

  /* ---- Hero wash ---- */
  /* Lauren, 2026-08-06: "make the hero teal the darker shade — the darker ones
     we already have throughout the site. match it to that." So the ramp is no
     longer sampled off the mock (it averaged #8FBFBB there); it is built out of
     the two brand teals the rest of the site already uses, with one interpolated
     step between them. Nothing new was invented:
       0%   --teal-deep  #2E6E6D
       46%  midpoint     #35807E
       100% --teal       #3E8C8A
     This is the "reads as a solid brand header" direction the mock-matched ramp
     was written to avoid — it is now what was asked for, so don't revert it back
     toward the mock without checking with her.

     The band is dark enough that the hero type had to invert: the wordmark,
     script and lead were navy on the pale ramp and measure ~3:1 here. See
     `.hero h1` / `.hero .script` / `.hero .lead` below, which are white now. */
  --hero-teal-deep: #2E6E6D;
  --hero-teal-mid: #35807E;
  --hero-teal-light: #3E8C8A;

  /* ---- Illustration set (saturated blocks) ---- */
  /* Pillar title colours. Each is its own patch's colour, which is what now
     tells you which title belongs to which icon — the marker rule that used to
     do that job is gone.

     Sampled from the imported art (modal colour, excluding the white line
     drawing) and then darkened along the same hue until it clears 4:1 on the
     paper. The patch colours themselves are far too light to set type in: at
     full strength the gold measures 1.5:1. Same hue and saturation, lower
     lightness, so they still read as the icon's colour.

     Re-derive these if the patch art changes — the comment records what each was
     taken from. */
  --blob-teal: #498887;    /* patch #7AB8B7 */
  --blob-purple: #8B71B7;  /* patch #B5A5D1 */
  --blob-green: #778257;   /* patch #98A477 */
  --blob-gold: #987A1D;    /* patch #E4C972 */
  --blob-pink: #BE6176;    /* patch #E3BBC4 */

  /* The Self-Love Club's six patch titles, derived the same way — each is its own
     patch's median colour with the hue and the HSL saturation held, and only the
     LIGHTNESS dropped until it clears contrast.
     HSL is the part that matters: holding saturation in HSV instead turns every
     one of these into a muddy grey, because the patches are pale. The pillar
     colours above were derived this way too, whatever their comment says.

     RE-DERIVED 2026-08-05 from the re-toned club icons, after Lauren asked for
     the club row to match the home row. Now that each club patch measures within
     1-2 saturation points of its pillar twin, these carry the same hue and
     saturation as the --blob-* values above.

     They are NOT the same values, and must not be replaced by them. The pillars
     stop at 4.0:1 because .pillar h3 is 22px/600 — large text, where AA is 3:1.
     These are .receive7 h4 at 15px bold, which is small text, where AA is 4.5:1;
     4.0 would fail. The half-step of extra darkness is the only difference
     between the two rows, and it is load-bearing. */
  /* DARKENED 2026-08-25, the whole family plus --teal-label. These six colour
     nothing but the six `h4` labels under the Club's icons, and they had been
     tuned to sit right ON the 4.5 line — measured 4.49, 4.49, 4.49, 4.51, 4.52,
     4.53 on bare white at 15px/700. Three of them were already under it. Any
     ground colour at all tips the whole family, which is what the all-over wash
     exposed. Each was darkened in HLS lightness ONLY, so hue and saturation are
     untouched and each still matches its icon; they now measure ~5.5 on white
     and ~4.8 through the wash. The old values are one line up in git if a
     specific one ever needs to go back. */
  --club-welcome: #416F6F;      /* patch #8ABBBA, cf --blob-teal   */
  --club-experiences: #7D651A;  /* patch #E4CA7B, cf --blob-gold   */
  --club-movement: #606C46;     /* patch #AAB78F, cf --blob-green  */
  --club-creative: #7958A3;     /* patch #BBAAD1, cf --blob-purple */
  --club-reflection: #A74955;   /* patch #DEB4B9, cf --blob-pink   */
  --club-playlist: #4E6A88;     /* patch #98AEC4, no pillar twin   */

  /* A BLUE THAT POPS, 2026-08-26. Lauren, of the Sunday Spark heart in the
     closing band: "make it a shade of blue that pops more." --club-playlist,
     which it had, is a slate — it is the blue that reads as a LABEL, tuned for
     15px text, and at heart size it goes grey against the paper.

     Derived the way every ink in this file is derived, from a patch rather than
     invented: --periwinkle #9EC8F7 carried to ink weight at its own hue (212) —
     lightness to 45%, saturation held near the patch's — which is what makes it
     read as this palette's blue rather than a stock one. 4.9:1 on the page
     ground against --club-playlist's 4.4, and far more saturated, which is where
     the pop actually comes from at this size.

     It colours ONE mark. Anything that needs a blue for TEXT should still take
     --club-playlist, which was measured for that. */
  --spark-blue: #2F7CC0;        /* patch #9EC8F7 (--periwinkle), ink twin */


  /* ---- Panels ---- */
  /* The Believe panel. Was the sage #D1D3B7 — Lauren, 2026-08-04: "i dont love
     how that current green looks", asking for a lighter teal than the hero.
     This is Halo Aqua, already in the palette as the hero halo, so the panel
     borrows a colour the page owns rather than inventing one.

     It is genuinely lighter than the hero: L 80 against the hero's three teals
     at 56 / 64 / 73, and hue 178 sits inside their 171-177 range, so it reads
     as the same colour family rather than a second teal. 9.7:1 on the navy
     label, up from the sage's 9.05.

     The risk here is the blue panel next to it — only 23 degrees of hue apart.
     What separates them is saturation, 36 against the blue's 70. Don't
     saturate this one up without re-checking that the two still read apart. */
  --panel-teal: #BBDFDE;
  /* Hover step for every button that fills with --panel-teal. Same hue (178) and
     same HSL saturation (0.36), lightness only, 80 -> 70 — so hover reads as the
     button darkening rather than as a second colour. 7.9:1 on the navy label. */
  --panel-teal-deep: #97CECD;
  /* Was #D2DFE0, sampled off the mock — a blue-grey that read as no colour at
     all once the panel sat between sage and lavender. (That sage neighbour is
     --panel-teal now; this note is the history, not the current row.) Lauren asked for a blue
     from the palette, so this started as Butterfly Blue (#B8E2FA) itself. That
     read too bright beside its neighbours, so it is now that colour at 80%
     saturation and darkened to sit level with them: luminance 0.634 against
     sage's 0.636 and lavender's 0.571. Still unmistakably blue, 6.0:1 on body
     ink. Raise the lightness back toward #B8E2FA if it ever wants more lift. */
  /* DEEPENED 2026-08-23, from #AAD7F0. Lauren liked the dark blue of the 1:1
     page's interest card and asked whether the pale panels could go that way
     too. They cannot: `.who-for` on the home page is one of a PAIR with
     `.believe`, two pale washes at different heights reading as one gesture,
     and taking one of them dark makes it the dominant object on the screen and
     the other look like a mistake. The site also runs exactly two dark moments
     per page — the hero band and the CTA card — which is what makes them read
     as punctuation; a third mid-page spends it.

     So the panel goes DEEPER RATHER THAN DARK: same hue (201) and same HSL
     saturation (0.70), lightness 0.80 -> 0.72. That is a clear step down while
     the panel stays a pale wash carrying dark text — navy measures 7.43:1 on it
     and the body ink 4.94:1, both clear of AA, where 0.70 would put the ink at
     4.71 and 0.68 at 4.49, under it. 0.72 is the deepest this can go without
     reversing the type out, which is the change she did not want. */
  --panel-blue: #86C6EA;
  --panel-lav: #D1C2D8;

  /* ---- Legacy aliases (other pages still reference these) ---- */
  --aqua-mist: #DDF4F4;
  --butterfly-blue: #B8E2FA;
  --lavender: #C9B6D8;
  --purple: #977FB2;      /* Mock secondary button #977FB2 */
  --periwinkle: #9EC8F7;
  --sage: #B5BE98;
  --butter: #EFC780;
  --pink: #EFBBBB;
  --aqua: #A2C8C3;

  /* ---- Surfaces ---- */
  --white: #FDFDFD;
  --cream: #FAFAF8;
  --cream-accent: #F6F1E6;
  --teal-wash: #EFF7F6;
  --seafoam: #D6F0F0;

  /* ---- Text ---- */
  --forest: #212E39;      /* headings are navy-slate now, not teal */
  --charcoal: #40494E;    /* body copy */
  --gold: #EFC780;

  /* Wash channels (r,g,b for rgba()) */
  /* The all-over watercolour ground — see .claude/make-ground-wash.py.
     ON <body>, NOT ON <main>, and that is the whole point of where it lives:
     the footer is masked with wave-top.svg, so its dark colour is clipped away
     along a torn edge and what shows THROUGH the tear is whatever is behind the
     footer — which is the body, not main. With the wash on main that strip came
     out flat soft-white while everything above it was washed, and the same bare
     white appeared under any page shorter than the viewport. Lauren: "the water
     color splashes need to be in the white space with the footer".

     Because it is painted once, on the element behind everything, there is no
     seam to align and no doubling where main overlaps. main deliberately no
     longer paints an opaque --soft-white base, or it would hide this. */
  --pool: 2;
  --wash-tile: 1500px;
  --wash-veil: 0.35;

  --c-teal: 62, 140, 138;
  --c-navy: 24, 46, 69;
  --c-blue: 158, 200, 247;
  --c-lav: 201, 182, 216;
  --c-sage: 181, 190, 152;
  --c-aqua: 162, 200, 195;
  --c-pink: 239, 187, 187;
  --c-gold: 239, 199, 128;

  /* ---- Type stack, 2026-08-04 ----
     Lauren's "Modern Botanical" direction: Recoleta Bold headings + Satoshi
     body. Recoleta is a commercial Latinotype face and has to be bought and
     self-hosted, so headings run on FRAUNCES as a stand-in — it is the closest
     free equivalent because of its SOFT axis, which rounds the terminals the
     same way Recoleta's are drawn. To swap in the real thing later: buy the web
     licence, self-host the woff2, and change --font-heading only. The sizes
     below should carry over roughly as-is; re-measure x-height before trusting
     that.

     CAVEAT IS GONE, at Lauren's instruction — "remove caveat completely". It is
     not in the font links, not in a fallback stack, and nothing on the site
     should reintroduce a handwritten face without her asking.

     Every display size in this file was originally stepped UP to compensate for
     Caveat rendering small for its point size. Measured on canvas, Caveat's
     x-height is 0.826 of Fraunces's and it sets 0.805 as wide, so all of them
     were multiplied by 0.81 when the face changed. Don't "fix" them upward. */
  /* CALISTOGA, chosen 2026-08-19 after eight rounds of comparison. It beat
     Yeseva One, Atma, Bree Serif, Averia Serif Libre, Laila, Crete Round,
     Solway, Podkova, Kurale, Merienda, Baloo 2, Grandstander, Trocchi, Bespoke
     Slab, Gambetta, Mitr, Gluten, Sansita Swashed, Lemonada, Zodiak, Erode,
     Bricolage Grotesque, Caprasimo, Agbalumo, Zen Antique Soft, Kiwi Maru, Zen
     Maru Gothic, Rowan, Gabarito, Kreon, Aleo, Enriqueta, Sanchez, Martel,
     Kaisei Decol, Shrikhand, Gotu, Panchang, Poetsen One, Bakbak One, Tanker
     and Coustard, the last of which it was judged against side by side on a
     live copy of the home page.

     SINGLE WEIGHT: Calistoga ships 400 and nothing else. The weights this file
     sets for Fraunces (h1 700, h2/h3 600, and a dozen section rules) are
     therefore pinned back to 400 at the foot of the file, so no browser invents
     a fake bold. Calistoga is drawn at display weight already; 400 IS its bold.

     AVERIA SERIF LIBRE, standing in its place from 2026-08-23, ships 300, 400
     and 700 — three real weights, so the dial at the foot of this file can move
     again. It sits at 400. Delius before it had one weight and no dial; Sour
     Gummy before that had a full axis.

     IT IS A SERIF AGAIN, which puts the fallback back to Georgia and ends the
     run of rounded and handwritten faces. It was also on the 2026-08-19
     shortlist that chose Calistoga — see the list further up this comment.

     FRAUNCES STAYS LOADED, and not by oversight: the hero tagline
     (--font-serif) and the script pull-quotes (--font-script) still run on it,
     and Calistoga has no italic. Do not remove it from the font links.

     The comparison pages that produced this decision are site/font-compare.html
     and site/font-in-context.html, both noindex working files that must stay out
     of the upload zip. */
  /* ---- BUBBLEGUM SANS, a font test — 2026-08-23 ----
     Lauren asked to try Averia Serif Libre as the display face site-wide, with
     nothing else changed: no layout, spacing, colour, size, copy or body-font
     move, so the face can be judged on its own. This one line and the
     `family=` parameter in each page's Google Fonts link are the whole change.

     TO REVERT: put `"Calistoga", Georgia, serif` back here, swap the
     `family=` value in the nine page <head>s, and UNCOMMENT the weight-pin
     block at the foot of this file — see the note there. That last step is new
     with Sour Gummy and matters; the two faces before it did not need it.

     THE FALLBACK STACK CHANGED WITH IT, and that is part of the same swap
     rather than a second decision: Calistoga is a serif and fell back to
     Georgia, Bubblegum Sans is a rounded sans and falling back to a serif would
     show a different kind of face entirely on the first paint or on a failed
     load.

     WHAT THIS IS NOT: Lauren's brief named the outgoing face as Coustard. That
     was the runner-up — the face this site actually ships is Calistoga, and
     Coustard is one of the forty-odd it was compared against on
     site/font-in-context.html. The swap below is Calistoga's. */
  --font-heading: "Averia Serif Libre", Georgia, serif;
  /* The hero tagline was Cormorant Garamond. Two different serifs on one page
     read as a mistake, so it folds into Fraunces too. Cormorant's x-height is
     0.881 of Fraunces's at the same nominal size while setting the same width,
     so the tagline scaled by 0.90 — it has to stay on two lines. */
  --font-serif: "Fraunces", Georgia, serif;
  /* Pull-quotes were Caveat. They keep a distinct voice via Fraunces italic
     rather than a fourth family — see .script. */
  --font-script: "Fraunces", Georgia, serif;

  /* ---- COURGETTE, an accent face — 2026-08-23, face swapped 2026-08-24 ----
     Lauren: "I want it to feel like a small handwritten layer within the
     existing design, not like a new primary typeface... keep its use sparse and
     intentional. There should generally only be one or two [handwritten]
     moments visible within a section or screen, and many sections may not need
     it at all."

     IT WAS DANCING SCRIPT FOR ONE DAY, and the swap is the whole reason the
     x-height table further down this file exists. Lauren asked for the script
     to be larger FIVE times — 1.15, 1.34, 1.46, 1.2, 1.5 — and the last of
     those was still only ~14% past the apparent size of the Fraunces it had
     replaced. Dancing Script's x-height is 0.332 of its em; measured across 30
     Google script faces it ranked 26th, so it was close to the worst available
     choice for reading size. Courgette is 0.505 and lays down 6292 ink pixels
     against 3000, which matters because these lines sit on pale watercolour
     washes where a thin stroke spends contrast the panel cannot spare.

     THE PROOF THAT THE FACE WAS THE PROBLEM: --accent-scale went from 1.5 to 1.
     The clamps already authored on `.script`, `.oto-joy-title` and the rest now
     simply work, which is what a correctly-sized face looks like.

     The comparison harness is `site/script-compare.html` — a working file, like
     font-compare.html and font-in-context.html, linked from nothing and kept
     out of the upload zip. It shows six candidates at MATCHED x-height, which
     is the only honest way to compare scripts.

     WHERE IT MAY GO: short emotional or tagline-style phrases, small accent
     headings where the wording is personal, brand phrases like "Joy is a
     compass.", and very short lines that read as a handwritten note.

     WHERE IT MAY NOT: page titles (Lumi Libra, About Lauren, Sunday Spark,
     Self-Love Club, 1:1 Sessions), navigation, buttons, body copy, long
     sentences or paragraphs, functional section headings like "What to
     Expect", small uppercase labels like "COMING TO LUMI LIBRA", and the logo.

     IT DOES NOT REPLACE --font-script. Fraunces italic still carries every
     pull-quote and hero tagline on the site; this is applied by hand to a
     named, counted set of lines through `.accent`, which is the only selector
     that reaches it. Adding it to `.script` wholesale would put a handwriting
     face on some quite long sentences — the home hero's tagline runs three
     lines — and that is the thing the brief rules out.

     400 ONLY, AND THE URL ASKS FOR NO WEIGHT AT ALL because Courgette ships a
     single one. `.accent` therefore sets `font-weight: 400`, not the 500 it
     carried under Dancing Script — a weight a font does not have is an
     invitation for Safari to draw a fake bold, which is the same failure the
     DISPLAY HEADING WEIGHTS block at the foot of this file exists to prevent.

     SATISFY CAME OUT OF THE FONT URL in the same edit. It had been requested on
     all nine pages since the earlier script exploration and was referenced by
     nothing — a whole font file downloaded per page load for no rendered glyph.

     CAVEAT WAS REMOVED FROM THIS SITE at Lauren's instruction, with a note that
     nothing should reintroduce a handwritten face without her asking. She
     asked. That rule is satisfied, not broken. Caveat Brush appears in the
     comparison harness as a candidate and is flagged there for the same reason;
     it was not chosen. */
  --font-accent: "Courgette", "Segoe Script", cursive;

  /* HOW MUCH BIGGER the accent face runs than the line's OWN designed size.
     See the `.accent` block at the very bottom of this file for why this is a
     multiplier of the host's size rather than a size of its own, and for the
     x-height measurement that sets the floor under these numbers.

     1 UNDER COURGETTE, and that is the point of the face swap rather than a
     coincidence: the sizes authored on the host classes are correct as written,
     so this multiplier has nothing left to correct. It stays because the next
     face swap will need it again — under Dancing Script it read 1.5.

     TWO VALUES, because the hosts are not all the same kind of line.
     --accent-scale-display is for hosts whose clamp is ALREADY display-sized,
     currently just `.oto-joy-title` at 2.7rem. Under Dancing Script it existed
     because 2.7rem x 1.5 drew a cap-height taller than the page's own h1.
     Courgette does not have that problem — at scale 1 the Joy heading's
     cap-height is 32.8 against the h1's 43.9 — so 0.89 is now doing a smaller
     job: it holds the Joy-to-body-script proportion at the 1.30 Lauren signed
     off on, where a flat 1 would quietly grow that heading by 12%. */
  --accent-scale: 1;
  --accent-scale-display: 0.89;

  /* Satoshi (Fontshare, free) replaces Manrope, which replaced Nunito Sans
     earlier today. Watch out: Satoshi's x-height is 0.896 of Manrope's, so at
     equal nominal sizes it reads ~11% SMALLER. Every body size was multiplied
     by 1.11 to hold the apparent size won this morning. The nominal rem values
     therefore look large — that is correct, not a bug. */
  --font-body: "Satoshi", "Segoe UI", system-ui, sans-serif;
  /* Satoshi Regular is the body weight per her spec; buttons, nav and the
     letterspaced uppercase labels take Medium. */
  --fw-ui: 500;

  /* Rounds Fraunces's terminals toward Recoleta's. WONK stays off — its
     alternate forms are a quirk Recoleta doesn't have. Applied via
     font-variation-settings on the display rules; naming only SOFT/WONK leaves
     font-weight free to drive the wght axis. */
  --display-vars: "SOFT" 80, "WONK" 0;

  /* ---- Type scale ----
     One ladder for the whole site, so body copy stops drifting between
     0.88 / 0.9 / 0.95 / 0.98rem section by section.

     Raised 2026-08-04 — Lauren: "the super small sans is hard to read, i want
     something larger and more clear." The previous ladder was stepped ~6% BELOW
     the serif's to compensate for Nunito Sans's taller x-height, and matching
     the mock's own body size held it there. Both were reasoned, and both were
     wrong in practice: the mock is a flat artboard viewed whole, the site is
     read at arm's length. Legibility wins over fidelity to the mock here.

     --t-sm is now a caption size only. It used to carry real prose (the
     Remember columns, the pillar copy, the note, the reminders) at 14px, which
     is where "hard to read" was actually coming from — those all sit on
     --t-base now. Don't put paragraphs back on --t-sm.

     Scaled again by 1.11 when the face went Manrope -> Satoshi, to hold the
     same apparent size against Satoshi's smaller x-height. See --font-body. */
  --t-xs: 0.94rem;     /* eyebrows, small print */
  --t-sm: 1.05rem;     /* captions, dense grids — NOT paragraphs */
  --t-base: 1.19rem;   /* body */
  --t-md: 1.33rem;     /* lead-in paragraphs, section intros */

  /* ---- Spacing rhythm ---- */
  --space-xs: 0.5rem;
  --space-sm: 1rem;
  --space-md: 2rem;
  --space-lg: 3.25rem;
  --space-xl: 3.5rem;
  /* The mock is a tight editorial page, not a slideshow: sections sit close
     enough that you read two of them at once. These were 6.5/8rem, which pushed
     the homepage past 5000px and left a screen of dead space under every band. */
  --section: 4.5rem;
  --section-airy: 5.5rem;

  --radius: 12px;
  --shadow-soft: 0 10px 34px rgba(31, 94, 92, 0.10);
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  font-family: var(--font-body);
  font-size: var(--t-base);
  line-height: 1.75;
  color: var(--charcoal);
  background-color: var(--soft-white);
  /* The veil is the wash's dial and has to sit ABOVE it: --wash-veil 0 shows the
     file at full strength, 1 hides it. A background layer cannot carry an
     opacity of its own, so a flat sheet of --soft-white over it does the job. */
  /* THE WHOLE GROUND, one element, covering the entire document — every page,
     including behind the footer's torn edge and below any page shorter than the
     viewport. Two things stacked, and they do different jobs:

     THE POOLS drift. Placed by percentage of the page, they stretch to whatever
     length it happens to be, so colour moves as you scroll — a repeating tile
     cannot do that. Edge-anchored at 0-2% / 98-100% so each licks in from the
     margin and none sits under the centred text column.

     THE WASH is the all-over watercolour paper underneath them, a seamless tile
     — see .claude/make-ground-wash.py. Between the two sits the veil, which is
     the wash's dial: a background layer cannot carry an opacity of its own, so a
     flat sheet of --soft-white over it does the job. --wash-veil 0 shows the
     file at full strength, 1 hides it. It is BELOW the pools in this list, so it
     veils the wash and nothing else.

     Nothing between here and the reader may paint an opaque base or this
     disappears — `main` deliberately no longer does. */
  background-image:
    radial-gradient(ellipse 28% 9%  at 0% 5%,    rgba(var(--c-blue), calc(0.25 * var(--pool))), transparent 72%),
    radial-gradient(ellipse 25% 8%  at 99% 11%,  rgba(var(--c-teal), calc(0.13 * var(--pool))), transparent 72%),
    radial-gradient(ellipse 23% 8%  at 1% 16%,   rgba(var(--c-lav),  calc(0.34 * var(--pool))), transparent 74%),
    radial-gradient(ellipse 26% 8%  at 100% 25%, rgba(var(--c-blue), calc(0.25 * var(--pool))), transparent 72%),
    radial-gradient(ellipse 27% 9%  at 1% 34%,   rgba(var(--c-teal), calc(0.13 * var(--pool))), transparent 72%),
    radial-gradient(ellipse 24% 8%  at 100% 40%, rgba(var(--c-lav),  calc(0.34 * var(--pool))), transparent 73%),
    radial-gradient(ellipse 24% 7%  at 98% 45%,  rgba(var(--c-blue), calc(0.15 * var(--pool))), transparent 74%),
    radial-gradient(ellipse 28% 10% at 0% 55%,   rgba(var(--c-teal), calc(0.13 * var(--pool))), transparent 72%),
    radial-gradient(ellipse 26% 8%  at 100% 66%, rgba(var(--c-lav),  calc(0.34 * var(--pool))), transparent 72%),
    radial-gradient(ellipse 27% 9%  at 2% 78%,   rgba(var(--c-blue), calc(0.25 * var(--pool))), transparent 72%),
    radial-gradient(ellipse 26% 8%  at 99% 88%,  rgba(var(--c-teal), calc(0.13 * var(--pool))), transparent 72%),
    radial-gradient(ellipse 24% 8%  at 1% 95%,   rgba(var(--c-lav),  calc(0.34 * var(--pool))), transparent 73%),
    linear-gradient(rgba(253, 253, 253, var(--wash-veil)), rgba(253, 253, 253, var(--wash-veil))),
    url("../images/art/ground-wash.webp");
  background-size: auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, auto, var(--wash-tile) var(--wash-tile);
  background-position: 0 0;
  background-repeat: repeat;
  overflow-x: hidden;
}

img { max-width: 100%; display: block; }

main { overflow-x: clip; }

/* ==========================================================================
   Continuous ground
   The homepage used to be a stack of bands, each painting its own background,
   so every section boundary was a visible seam. Instead the whole of <main>
   carries one sheet of watercolour paper and the sections sit on it with no
   background of their own — there are no edges left to see. Colour still pools
   as you scroll, but it pools ACROSS the boundaries rather than stopping at them.

   Extended to the About and Club pages 2026-08-05. Those two were still built
   the old way — every section painting its own radial-gradient ground, which is
   what put a visible ruled line under each one. The pools are placed by
   percentage of the page, so one rule serves all three despite their very
   different lengths.

   THESE WERE DELIBERATELY FAINT, AND WERE RAISED ANYWAY on 2026-08-07. Lauren:
   "in the white spaces where we have some light watercolour splashes already, can
   we make those more apparent or add more pops of colour without taking away from
   anything." Read the paragraph below before lowering them again — the old note
   warned that at their previous strength they "compounded with the washes above
   until no soft white was left anywhere on the page", and that is still the
   failure mode to watch for.

   Three things changed, and only the first is a strength increase:

   1. ALPHAS x1.7. Legibility was never the limit here and it is worth knowing by
      how much: body ink on the strongest pool measures 7.7:1 after the rise,
      against the 4.5 that AA asks for. Even at x2.2 it was still 7.2. What
      constrains these is the look, not contrast, so x1.7 is a judgement — it is
      the point where the colour reads as intentional from a normal viewing
      distance without the paper stopping being white.

   2. THE POOLS GOT ROUNDER, 4-6% tall -> 8-10%. This is what actually makes them
      read as "splashes" rather than "more colour". At 5% of page height they were
      thin horizontal licks along the edge; the same alpha in a fuller ellipse
      reads as paint pooling rather than as a gradient band, and it does it
      without pushing further into the text column.

   3. THREE NEW POOLS, at 16%, 40% and 95%, filling the largest vertical gaps.
      They also bring in --c-aqua, which this stack never used, and give --c-pink
      a second appearance — it was the one colour here that showed up once, at the
      lowest alpha on the page, and so never really registered.

   Still edge-anchored (0-2% and 98-100%), so every pool licks in from the margin
   and none of them sits under the centred text column. Still the BOTTOM layer:
   the colour panels above are opaque, so nothing here shows through .believe,
   .who-for or the club card, and the compounding the old note feared can only
   happen on bare paper.
   ========================================================================== */
/* ---------- TEAL, BLUE AND LAVENDER ONLY — 2026-08-25 ----------
   Lauren: "i want to lean into more of using the teal, blue, and lavender shades
   only" and "more pronounced but not making things so they are hard to read".
   Sage, pink and aqua are out of this stack entirely; they held seven of the
   twelve pools.

   TWO THINGS ARE SEPARATED HERE ON PURPOSE, because they used to be one number
   and that is what made the last strength pass hard to reason about:

   1. THE PER-COLOUR ALPHAS ARE PERCEPTUALLY MATCHED, NOT EQUAL. The brand teal
      (62,140,138) is roughly 2.6x stronger per unit of alpha than the lavender
      (201,182,216) — it is a saturated mid-tone where the others are pale tints.
      Swapping sage -> teal at sage's own 0.29 would move the paper 57 levels off
      white where sage moved it 29, and it stops reading as a splash and starts
      reading as a teal panel. Measured over --soft-white, these three bases all
      move the paper the same ~24 levels: teal 0.13, blue 0.25, lav 0.34. Keep
      that ratio if you ever add a fourth colour — match the DISTANCE off white,
      never the alpha.

   2. `--pool` IS THE DIAL. One number scales the whole stack, so "more" or
      "less" is a single edit and the balance between the twelve cannot drift.
      Shipped at 2 — Lauren picked it from a 1.0 / 1.5 / 2.0 render of the same
      stretch of the home page. 1.0 is the strength the sage-and-pink stack had,
      so this is genuinely double, and the recolour is not doing the work on its
      own.

   READABILITY IS NOT WHAT LIMITS THIS, and it is worth knowing by how much so
   nobody trims it out of caution: body ink on the strongest pool measures about
   7:1 even well above the strength shipped here, against the 4.5 AA asks. What
   actually breaks first is the paper ceasing to read as paper. That is a
   judgement, not a threshold — so it was made by looking, not by measuring.

   Twelve pools, alternating colour AND side so no two neighbours match, still
   edge-anchored at 0-2% / 98-100% so every one licks in from the margin and none
   sits under the centred text column. Still the BOTTOM layer: the colour panels
   above are opaque, so this can only compound on bare paper.

   The 45% pool keeps a lighter weight (x0.6) — it sits only 5% below its
   neighbour on the same side, and at full strength the two merge into one long
   lick down the right margin instead of reading as two. */
/* THE GROUND MOVED TO <body> ON 2026-08-25. It used to live here, on the five
   page mains, and the pools stopped dead at main's bottom edge — which is the
   footer's top edge. The footer is masked with wave-top.svg, so its dark colour
   is clipped along a torn edge and the paper showing THROUGH that tear belongs
   to the body, not to main: it came out flat white while everything above it was
   coloured. Lauren: "the water color splashes need to be in the white space with
   the footer". Percentages now run over the whole document instead of stopping
   short of the last 450px of it. See `body` above. */

/* Sections carry no background of their own — except the hero, which is now a
   saturated teal band, and the three colour panels further down.

   .who-for used to be listed here, from when it was a plain section on white.
   As a colour panel it isn't: at 0,2,0 this rule outranked `.who-for` and was
   silently stripping the panel's background, which is why the middle panel had
   been rendering as bare paper. */
.page-home .remember,
.page-home .pillars { background: none; }

/* ---------- Wavy band edges ----------
   A colour band ends on a torn watercolour edge rather than a ruled line.

   This used to be an overlay: a wave-shaped block painted in the colour of the
   band BELOW, laid over the bottom of the band above. That can never be
   seamless. It only disappears if its colour exactly matches whatever is behind
   it at that point, and `.page-home main` carries a faint tinted ground that
   varies all the way down the page. Worse, .hero is overflow:hidden and its box
   ends on a fractional pixel, so the overlay was clipped a hair short and left a
   visible teal hairline under the hero — the line Lauren spotted.

   The wave is a MASK on the band itself now. The band's own colour ends in the
   wave and whatever is behind shows straight through, so there is no colour to
   match and no seam is possible. It also means one wave can run across a whole
   grid row: .believe-for is masked as a container, not panel by panel.

   Composed as several mask layers, which composite with `add` by default: a
   plain rectangle for the body of the band, plus a wave tile at whichever edges
   are torn. The tile REPEATS at a fixed width rather than stretching to 100%, so
   the wavelength stays the same whether the band is 1280px or 300px wide — a
   stretched wave gives every band a different frequency and stops reading as the
   same torn paper. Each tile's two ends sit at the same height so it repeats
   without a kink.

   The layers must OVERLAP generously along the join, and this is the detail that
   bites: at a 1px overlap the join showed as a faint straight line right across
   every coloured band. 1px means the only shared row is the antialiased edge row
   of BOTH layers, and two ~0.5 alphas composited with `add` land just short of
   1.0 — enough to read against a flat colour. Element heights here are
   fractional (the hero is 787.13px tall), so those edges never fall on whole
   device pixels.

   --wave-overlap is set so the solid rectangle's soft edge sits well inside the
   wave tile's fully-opaque headroom, where the tile alone already contributes
   alpha 1. The tiles are opaque for their first/last 15/80 of height — 5.6px at
   the 30px minimum wave height — so 4px is within budget at every size. */
:root {
  --wave-h: clamp(30px, 3.4vw, 52px);
  --wave-overlap: 4px;
  /* Under three repeats across a 1280px band. Six octaves of detail still read
     as a pattern once a tile repeats five or six times. */
  --wave-tile: 480px;

  /* Seamless torn-edge tiles, generated by .claude/make-waves.py — hand-drawn
     beziers come out a smooth sine, which reads as a scallop, not torn paper. */
  --wave-bottom: url("../images/art/wave-bottom.svg");  /* opaque ABOVE the line */
  --wave-top: url("../images/art/wave-top.svg");        /* opaque BELOW the line */
  /* The EXACT complement of --wave-bottom: same generator seed, so the same
     curve, closed downward. NOT interchangeable with --wave-top, which is a
     different seed and therefore a different curve — that is precisely why the
     colour-changing sprigs could not simply reuse .torn-top. Used to crop the
     lower half of a crossover along the same edge the band above is torn on. */
  --wave-bottom-inv: url("../images/art/wave-bottom-inverse.svg"); /* opaque BELOW the line */
}

.torn-top,
.torn-bottom {
  position: relative;
  -webkit-mask-repeat: repeat-x;
          mask-repeat: repeat-x;
}

/* A scrap of paper torn on all four sides, for the floating colour panels.
   One stretched mask layer, not a composition — see the note in
   .claude/make-waves.py for why that trade is deliberate. Three variants so no
   two panels carry the same tear.

   The variant used to be picked by `.torn-paper:nth-of-type(N)`, and that is a
   trap: nth-of-type counts EVERY sibling of the same tag, decoration and
   scaffolding included, so a panel's tear depended on how many other divs
   happened to sit beside it. Adding .believe-seam-anchor between .believe and
   .who-for pushed .who-for from the 3rd div to the 4th — past the last rule —
   and the blue panel silently lost its mask and rendered as a plain rectangle
   on every screen size. It is per-element now: each panel names its own tear.

   The property is --panel-tear, not --tear: the chalk mounts on the About page
   already own --tear, and custom properties inherit, so sharing the name would
   let one system reach into the other. */
.torn-paper {
  position: relative;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-size: 100% 100%;   mask-size: 100% 100%;
  -webkit-mask-image: var(--panel-tear, url("../images/art/torn-paper-a.svg"));
          mask-image: var(--panel-tear, url("../images/art/torn-paper-a.svg"));
}

/* Home: sage, blue, lavender. Three different tears so no two panels on the
   page carry the same edge — the club card takes the default `a`. */
.believe { --panel-tear: url("../images/art/torn-paper-b.svg"); }
.who-for { --panel-tear: url("../images/art/torn-paper-c.svg"); }

/* About: the two panels sit side by side, so they must not match. */
.about-col-right { --panel-tear: url("../images/art/torn-paper-c.svg"); }

.torn-bottom {
  -webkit-mask-image: linear-gradient(#000, #000), var(--wave-bottom);
          mask-image: linear-gradient(#000, #000), var(--wave-bottom);
  -webkit-mask-size: 100% calc(100% - var(--wave-h) + var(--wave-overlap)), var(--wave-tile) var(--wave-h);
          mask-size: 100% calc(100% - var(--wave-h) + var(--wave-overlap)), var(--wave-tile) var(--wave-h);
  -webkit-mask-position: 0 0, 0 100%;
          mask-position: 0 0, 0 100%;
}

.torn-top {
  -webkit-mask-image: var(--wave-top), linear-gradient(#000, #000);
          mask-image: var(--wave-top), linear-gradient(#000, #000);
  -webkit-mask-size: var(--wave-tile) var(--wave-h), 100% calc(100% - var(--wave-h) + var(--wave-overlap));
          mask-size: var(--wave-tile) var(--wave-h), 100% calc(100% - var(--wave-h) + var(--wave-overlap));
  -webkit-mask-position: 0 0, 0 100%;
          mask-position: 0 0, 0 100%;
}

.torn-top.torn-bottom {
  -webkit-mask-image: var(--wave-top), linear-gradient(#000, #000), var(--wave-bottom);
          mask-image: var(--wave-top), linear-gradient(#000, #000), var(--wave-bottom);
  -webkit-mask-size: var(--wave-tile) var(--wave-h), 100% calc(100% - var(--wave-h) * 2 + var(--wave-overlap) * 2), var(--wave-tile) var(--wave-h);
          mask-size: var(--wave-tile) var(--wave-h), 100% calc(100% - var(--wave-h) * 2 + var(--wave-overlap) * 2), var(--wave-tile) var(--wave-h);
  -webkit-mask-position: 0 0, 0 calc(var(--wave-h) - var(--wave-overlap)), 0 100%;
          mask-position: 0 0, 0 calc(var(--wave-h) - var(--wave-overlap)), 0 100%;
}

a { color: var(--teal); }

/* ---------- Every clickable thing answers the cursor, 2026-08-17 ----------
   Lauren: "make sure whenever you hover over a section, it chnages a color that
   makes it distinct for the page visitor... on each page", scoped to clickable
   things. Audited all eight pages first by matching every <a>, <button> and
   <summary> against every :hover rule in the stylesheet: buttons, nav links,
   footer links, social icons, the club's icon patches and the FAQ questions all
   already responded. Only the three below did not, so this adds those rather
   than restyling what works.

   1. A fallback for body-copy links. There was no plain `a:hover` anywhere, so
      any link in prose relied on inheriting from a more specific rule and a new
      one would have had no hover at all.

   `:not(.btn)` is load-bearing, not tidiness. `a:hover` is one element plus one
   pseudo-class, which outranks `.btn`'s own single class — so without the
   exclusion this rule would repaint white button text teal on hover. Scoped to
   `main` as well, so footer and header keep their own gold and white hovers. */
main a:not(.btn):not(.nav-song):hover {
  color: var(--teal-deep);
}

.wrap {
  width: min(1160px, 92%);
  margin-inline: auto;
}

/* ---------- Typography ---------- */

h1, h2, h3 {
  font-family: var(--font-heading);
  font-variation-settings: var(--display-vars);
  font-weight: 500;
  color: var(--forest);
  line-height: 1.15;
}

/* Caveat needed positive tracking to stop the script running together. Fraunces
   is a serif at display size and wants the opposite — it sets tight by default
   and looked gappy at Caveat's 0.01em. */
h1 { font-size: clamp(2.916rem, 5.67vw, 4.698rem); letter-spacing: -0.015em; font-weight: 700; }
h2 { font-size: clamp(1.863rem, 3.159vw, 2.592rem); font-weight: 600; }
h3 { font-size: 1.499rem; font-weight: 600; }

/* Pull-quotes. These were the handwritten voice; with Caveat gone they stay
   distinct from body copy through italic + the softened terminals, not a
   separate family. */
.script {
  font-family: var(--font-script);
  font-variation-settings: var(--display-vars);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(1.417rem, 2.592vw, 1.863rem);
  line-height: 1.4;
  color: var(--script-blue);
}

/* The kicker above a display heading ("JOIN THE", "WELCOME TO"). Larger and
   bold from 2026-08-04 per Lauren, but held a step under the panel labels above
   — unlike those, this one has a real heading directly beneath it and shouldn't
   compete with it. */
.eyebrow {
  font-family: var(--font-body);
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--teal);
  margin-bottom: 0.9rem;
}

.lead { font-size: var(--t-md); line-height: 1.8; }

/* Section labels — the small uppercase Lora headings ("What I Believe",
   "A Note From Me"). They sit below the display headings in the hierarchy,
   so they read as labels rather than competing with h2s. */
.section-label {
  font-family: var(--font-body);
  font-size: 1.166rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--teal);
}

/* ---------- Painted wash band ----------
   A brush-stroke of colour laid behind a block of content: irregular corners,
   feathered edges, sitting under the text rather than boxing it in. Lives on a
   pseudo-element at z-index -1 so it can never clip or cover what's on top of
   it — including form controls. Tune the bleed with --paint-x / --paint-y. */
.painted {
  position: relative;
  --paint-x: -2.5%;
  --paint-y: 0px;
}

.painted::before {
  content: "";
  position: absolute;
  inset: var(--paint-y) var(--paint-x);
  z-index: -1;
  border-radius: 86px 38px 74px 46px / 40px 30px 36px 34px;
  /* Aqua at the left running out to bare paper at the right, as the Sunday Spark
     band does in the mock (#D9EBF0 -> #DAE5F5 -> #FEFEFE). It used to carry a
     lavender tint the whole way across, which left the signup sitting on colour
     instead of on the page. */
  background: linear-gradient(96deg,
    rgba(var(--c-aqua), 0.62) 0%,
    rgba(var(--c-blue), 0.34) 48%,
    rgba(var(--c-lav), 0.20) 76%,
    rgba(var(--c-lav), 0) 100%);
  -webkit-mask-image: radial-gradient(ellipse 98% 94% at 50% 50%, #000 70%, transparent 100%);
          mask-image: radial-gradient(ellipse 98% 94% at 50% 50%, #000 70%, transparent 100%);
  pointer-events: none;
}

/* A wash pooling out from behind one side of an image, instead of a drop shadow —
   colour bleeding onto the paper rather than the photo casting a shadow.

   Built exactly like .remember-figure::before: one radial pool, no mask, no
   second gradient layer, heavy blur. That construction reads as paint soaking
   into the page; the two-layer masked version this replaced read as a glow ring
   hugging the photo. Mirrored, because the hero photo sits on the right of the
   page and pools outward to the right, where the Remember polaroid pools left.

   In teal rather than the Remember wash's periwinkle. The alphas are lower to
   compensate: the brand teal is a dark colour, and at the 0.78 the blue carries
   it would go black-green and turn back into a drop shadow. At 0.38 it lands
   around #B3CDD0 — the same lightness as the Remember pool, still clearly teal. */
.painted-halo::before {
  inset: -16% -38% -14% -6%;
  border-radius: 48% 52% 44% 56% / 46% 42% 58% 54%;
  background: radial-gradient(ellipse 64% 64% at 62% 48%,
    rgba(var(--c-teal), 0.5) 0%,
    rgba(var(--c-teal), 0.27) 54%,
    transparent 78%);
  filter: blur(30px);
  -webkit-mask-image: none;
          mask-image: none;
}

/* On narrow screens the figure already spans most of the viewport, so a bleed
   this wide runs into the section's overflow and gets sheared off in a hard
   line. Pull it in and let the blur alone do the work. */
@media (max-width: 900px) {
  .painted-halo::before {
    inset: -10% -14% -10% -10%;
    filter: blur(22px);
  }
}

/* ---------- Panel washes ----------
   A brush-loaded wash laid on paper, not a tinted panel.

   These were CSS gradients under a 38px blur, and that could never look right:
   blur a shape hard enough to lose its edge and it fills its whole box evenly, so
   the text sits on a slab of colour with no paper left behind it. Blur it less and
   you just get a visible ellipse. Layering several soft radial pools instead gets
   closer but still merges into one field, because every gradient stop is smooth by
   definition — there is no roughness anywhere in the primitive to survive.

   So the edge is drawn where roughness is actually available: in SVG. Each wash is
   a soft rectangle pushed around by fractal noise via feDisplacementMap, with a
   second noise pass laying granulation inside it — see wash-sage.svg. That gives
   the torn, run-dry rim and the uneven density of a real wash. Size and place the
   file here; don't reach for blur() again. */
.painted-sage::before,
.painted-lav::before {
  border-radius: 0;
  background-repeat: no-repeat;
  background-size: 100% 100%;
  /* The files are painted at full strength so they can also be used on their own.
     Behind body copy they want far less — this value is set so the rendered band
     measures the mock's #E3F0EB (sage) and #F4ECF8 (lavender) over white paper.
     This is the dial to turn if a band ever reads as too much colour. */
  opacity: 0.42;
  filter: none;
  -webkit-mask-image: none;
          mask-image: none;
}

/* Wider than its panel and shorter, so the wash reads as a broad slab laid across
   the column the way the mock's does, rather than a tall shape standing in it. */
.painted-sage::before {
  inset: 5% -1% 9% -10%;
  background-image: url("../images/art/wash-sage.svg");
}

/* Counterweight to .painted-sage, in lavender, so the two halves of that band
   balance. Insets stay positive on the right: .who-for is overflow:hidden, so a
   wash bleeding outward would be sheared into a hard vertical line. */
.painted-lav::before {
  inset: 4% 0% 10% 2%;
  background-image: url("../images/art/wash-lavender.svg");
}


/* Lavender into blush — for quieter, smaller moments like a pulled quote. */
.painted-lilac::before {
  border-radius: 62px 30px 54px 34px / 34px 26px 30px 28px;
  background: linear-gradient(94deg,
    rgba(var(--c-lav), 0.5) 0%,
    rgba(var(--c-blue), 0.34) 58%,
    rgba(var(--c-pink), 0.26) 100%);
}

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

.btn {
  display: inline-block;
  font-family: var(--font-body);
  font-size: 0.977rem;
  font-weight: var(--fw-ui);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  text-decoration: none;
  padding: 0.95rem 1.9rem;
  /* Full pill, Lauren 2026-08-06: "match all buttons to be the same shape as the
     hero ones". The hero pair was the only place on the site using 999px; the
     rest took the site's 12px --radius, and the two shapes read as two different
     button systems. --radius still governs cards and inputs, so this is a button
     decision only. Several rules below already restated 999px to escape the old
     default; those are redundant now but harmless. */
  border-radius: 999px;
  border: 1.5px solid var(--teal);
  transition: background-color 0.25s ease, color 0.25s ease, transform 0.25s ease;
  cursor: pointer;
}

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

.btn-primary { background-color: var(--teal); color: var(--white); }
.btn-primary:hover { background-color: var(--teal-dark); border-color: var(--teal-dark); }

.btn-secondary { background-color: var(--white); color: var(--teal); }
.btn-secondary:hover { background-color: var(--teal-wash); }

/* On the teal hero the pair inverts, per the mock: a white pill and a purple
   one, both borderless and fully rounded rather than the site's soft rectangle. */
/* The pair has to sit on one row: at the larger type they measured 601px of
   button in a 612px column and wrapped. The tracking pays for it rather than
   the size — these are the page's primary CTAs and shrinking them again would
   undo the point of today's pass. */
.hero .btn {
  border-radius: 999px;
  border-color: transparent;
  padding: 0.9rem 1.3rem;
  font-size: 0.91rem;
  letter-spacing: 0.1em;
  white-space: nowrap;
}

.hero .btn-primary {
  background-color: var(--white);
  color: var(--navy);
}
/* #F2F7F6 was a 2%-off-white and the hover was invisible against the white pill.
   Same hue, a real step down, so it reads as pressing. */
.hero .btn-primary:hover { background-color: #E4EEEC; }

/* Teal since 2026-08-05 — Lauren asked for every Self-Love Club CTA to be teal,
   so the four that were purple (here, the home club card, the club hero and the
   join card) all moved. This one is "Discover Self-Love Club". */
/* Was a --teal fill, which stopped working the moment the band went to the brand
   teals — --teal IS the ramp's light stop now, so the button was painted in its
   own background. Lauren asked for "a super light teal" instead, 2026-08-06.

   --panel-teal rather than the paler --aqua-mist: this pill sits beside the
   white "Explore the Journey", and at #DDF4F4 the two read as the same button.
   At #BBDFDE it is unmistakably the tinted one of the pair and still lifts hard
   off the dark band. Navy label, 9.7:1.

   Still teal, so Lauren's "every Self-Love Club CTA is teal" rule holds. */
.hero .btn-secondary {
  background-color: var(--panel-teal);
  color: var(--navy);
}
/* Darkens on hover, per Lauren 2026-08-06. This briefly went the other way
   (--aqua-mist, lighter) and that was wrong. */
.hero .btn-secondary:hover { background-color: var(--panel-teal-deep); }

/* The mock sets a small heart after each hero button label. FILLED since
   2026-08-26 — "all hearts on theh site i want filled in". It takes the button
   label's own colour rather than a --heart tint: a differently-coloured mark
   inside a filled button reads as a rendering fault, not a flourish. */
.hero .btn::after {
  content: " \2665";
  font-size: 1.05em;
  line-height: 0;
  margin-left: 0.55em;
}

/* ---------- Header / Nav ---------- */

.site-header {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 50;
  padding: 1.4rem 0;
}

.site-header .wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
}

/* 44 -> 36px on 2026-08-20, and the drop is smaller than it looks. The old
   asset carried a transparent border that ate 22% of whatever height it was
   given, so a 44px box drew a 34px wordmark. The new file is trimmed to the
   painted alpha, so the height you set is the height you see — 44 would have
   drawn the mark noticeably BIGGER than it ever was. 36 lands just under the
   old visible size, which is what Lauren asked for: "a little smaller, it
   doesnt have to be so big". */
/* 36px -> 32px, 2026-08-23. Lauren, on the rebuilt Averia wordmark: "we can
   make it a little smaller on the site though."

   32 IS NOT A ROUND-DOWN, it is the number that restores the mark's optical
   footprint. Averia Serif Libre sets wider than Calistoga — the lockup's aspect
   went 5.24:1 to 5.91:1 — so at the old 36px the logo drew 213px across where
   Calistoga drew 188. At 32px it draws 189, within a pixel of what the header
   row was measured for.

   That matters beyond taste: the note at the 1100px burger breakpoint records
   the full nav needing 979px of a wrap that runs out around 1043, chosen to
   leave 62px of slack. The wider mark had eaten half of that. */
.logo-link img { height: 32px; width: auto; }

/* 2. The wordmark. It was the one interactive element on the whole site with no
      hover of any kind, on all eight pages — it links home from every header.
      Opacity rather than a colour, because the logo is artwork in four different
      colourways across the page grounds (dark teal on paper, white on the teal
      band, and the filtered navy on the club page); a single colour could not
      serve all of them, and tinting art reads as a rendering fault anyway. */
.logo-link { transition: opacity 0.2s ease; }
.logo-link:hover { opacity: 0.72; }

.main-nav {
  display: flex;
  align-items: center;
  gap: 2rem;
}


.main-nav a {
  font-family: var(--font-body);
  font-size: 1.132rem;
  font-weight: var(--fw-ui);
  color: var(--forest);
  text-decoration: none;
  transition: color 0.2s ease;
}

.main-nav a:hover { color: var(--teal-deep); }

.nav-song {
  border: 1.5px solid var(--teal);
  border-radius: 999px;
  padding: 0.45rem 1.15rem !important;
  font-size: 0.932rem !important;
  font-weight: var(--fw-ui);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--teal) !important;
  transition: background-color 0.2s ease;
}

.nav-song:hover { background-color: var(--teal-wash); }


/* The home header sits on the teal band, so the whole chrome inverts: white
   links, a white logo, and the Sunday Spark pill as a solid white capsule.
   Scoped to the pages that OPEN ON THE TEAL BAND — home and, since 2026-08-13,
   the Sunday Spark page, whose .spark-hero uses the same ramp. The rest still
   open on light grounds and keep the dark chrome. */
.page-home .main-nav a,
.page-spark .main-nav a { color: rgba(255, 255, 255, 0.94); }
/* ---------- The teal-band nav needed a real hover, 2026-08-17 ----------
   Lauren: "the home page i dont see the hover color change". She was right and
   it was measurable: these links rest at rgba(255,255,255,0.94) and hovered to
   #FFF, a 6% lift on white. Measured against everything else on the page, whose
   hovers shift 43 to 95 in RGB distance, this one shifted 0.

   A veil rather than a tint. The obvious move is to hover to the gold the
   footer uses, but the footer sits on the deep teal and this band is the light
   end of the ramp: --gold measures 2.47:1 there against white's 3.95:1, so
   colouring the text would have made the hover harder to read than the resting
   state. Lightening the ground behind it instead raises contrast rather than
   spending it.

   `box-shadow` supplies the padding, not `padding`. A spread ring paints
   outside the box without joining layout, so the veil looks like a pill with
   room around the word and the nav does not reflow by a single pixel on hover
   — which real padding here would do, at six items across a row already
   measured to the pixel for the 1100px burger. */
.page-home .main-nav a:hover,
.page-spark .main-nav a:hover {
  color: #FFF;
  background: rgba(255, 255, 255, 0.2);
  box-shadow: 0 0 0 0.42rem rgba(255, 255, 255, 0.2);
  border-radius: 3px;
}

/* Underlines whichever nav item is the page you are on. Only the pages that
   HAVE a nav item can appear here — 1:1 got one on 2026-08-23 and joined. */
.page-home .main-nav a[href="index.html"],
.page-spark .main-nav a[href="sunday-spark.html"],
.page-oto .main-nav a[href="one-on-one.html"] {
  text-decoration: underline;
  text-underline-offset: 6px;
  text-decoration-thickness: 2px;
}

/* Solid white capsule on the teal band. It briefly became an outline on
   2026-08-17, when a Sunday Spark pill sat beside it and two solid capsules
   would have had no hierarchy; that pill was dropped the same day and this went
   back to what it was. */
.page-home .nav-song,
.page-spark .nav-song {
  background: var(--white);
  border-color: var(--white);
  color: var(--navy) !important;
}

/* The logo art is dark teal; on the teal band it needs the white version. */
.page-home .logo-link img,
.page-spark .logo-link img { filter: brightness(0) invert(1); }

.nav-song-mobile { display: none; }

.nav-toggle { display: none; }

.nav-toggle-label {
  display: none;
  cursor: pointer;
  width: 30px;
  height: 22px;
  position: relative;
  z-index: 60;
}

.nav-toggle-label span,
.nav-toggle-label span::before,
.nav-toggle-label span::after {
  display: block;
  position: absolute;
  height: 2px;
  width: 100%;
  background-color: var(--forest);
  border-radius: 2px;
  transition: all 0.25s ease;
  content: "";
}

.nav-toggle-label span { top: 10px; }
.nav-toggle-label span::before { top: -8px; }
.nav-toggle-label span::after { top: 8px; }

/* ---------- Hero (home) ---------- */

/* Washes are small pools anchored to the edges — the page reads as soft white
   watercolor paper with colour bleeding in from the margins, not as a tinted
   panel with a blob floating in the middle of it. */
/* ---------- Decorative art ----------
   Every butterfly, leaf and dotted path on the page is a .deco: absolutely
   positioned against the nearest positioned ancestor, never interactive, and
   always behind the writing. Placement is per-instance below; this rule only
   establishes that decoration can't get in the way of reading. */
.deco {
  position: absolute;
  z-index: 0;
  pointer-events: none;
  user-select: none;
}

/* The hero is a saturated teal band now, not white paper with tints licking in
   at the corners. The uneven radial pools on top of the base sweep are what keep
   a full-bleed colour field reading as watercolour rather than as a flat brand
   header — a plain linear-gradient at this size looks printed. */
.hero {
  position: relative;
  padding: 8.5rem 0 7rem;
  background:
    /* Baked fractal-noise paper, blended rather than drawn: it carries only
       lightness, so the hue stays in the gradients below and can be retuned
       without regenerating the file. Without it the band is smooth everywhere,
       and a smooth full-bleed colour field reads as a printed brand header no
       matter how many radial pools are layered on it — the mock's band is
       visibly pigment on a sheet. See .claude/make-texture.py. */
    url("../images/art/paper-wash.png"),
    radial-gradient(ellipse 46% 52% at 12% 8%,  rgba(255, 255, 255, 0.34), transparent 66%),
    radial-gradient(ellipse 40% 44% at 88% 78%, rgba(255, 255, 255, 0.26), transparent 68%),
    /* The two darkening pools were #2E6E6D, which is the ramp's own deep stop
       now — they would pool into nothing. Dropped a step further down the same
       hue so the band still has depth in its corners. */
    radial-gradient(ellipse 36% 40% at 72% 6%,  rgba(26, 62, 61, 0.30), transparent 70%),
    radial-gradient(ellipse 34% 38% at 4% 88%,  rgba(26, 62, 61, 0.22), transparent 72%),
    linear-gradient(158deg,
      var(--hero-teal-deep) 0%,
      var(--hero-teal-mid) 46%,
      var(--hero-teal-light) 100%);
  background-size: cover, auto, auto, auto, auto, auto;
  background-position: center, 0 0, 0 0, 0 0, 0 0, 0 0;
  /* soft-light, so mid-grey in the texture is a no-op and only its departures
     from mid tint the band. overlay and multiply both drive the darks far enough
     to read as dirt on the page. */
  background-blend-mode: soft-light, normal, normal, normal, normal, normal;
  overflow: hidden;
}

/* On teal, the writing and the chrome invert. */
/* BREATHING ROOM, 2026-08-26 — "move welcome to higher... just give some
   breathing room to this hero section". margin-bottom goes 0.9rem (the site
   default) to 2rem.

   Raising THIS is what moves "WELCOME TO" up, which is not obvious: the copy
   block is vertically centred in the band now, so growing the gap below the
   eyebrow makes the block taller and centring pushes its top up. The eyebrow
   rides that up; the wordmark takes the other half downward. A `margin-top`
   would have done nothing at all — it would grow the block from the same edge
   and centring would cancel it.

   THE BUTTERFLY COMES WITH IT for free, which is what she asked for. `.hero-flight`
   is absolutely positioned at `top: -64px` against `.hero-copy`, so it is pinned
   to the block's top edge, not to the band — the two keep their exact
   relationship (it overlaps the eyebrow by 9px, deliberately) and travel
   together. Nothing here needs to know about it. */
.hero .eyebrow { color: rgba(255, 255, 255, 0.92); letter-spacing: 0.22em; font-size: 0.999rem; margin-bottom: 2rem; }

/* The wordmark is the loudest thing in the mock by a wide margin — it runs about
   a third of the page width, where the site's h1 scale gave it under a fifth.
   Measured off the mock rather than judged: "Lumi Libra" spans 31% of the sheet
   there against 19% here, so the size goes up by the same 1.6x. Scoped to the
   hero; the other pages' h1s keep the site scale. */
.hero h1 {
  /* White since the band went to the brand teals. Navy measures 3.0:1 on the
     new mid stop — technically legal for text this size and visibly muddy. The
     site's "display headings go NAVY" rule still holds everywhere else; the
     hero is the one place the ground is dark enough to force the inversion. */
  color: #FFF;
  font-size: clamp(3.402rem, 9.072vw, 7.29rem);
  line-height: 1.0;
  /* The -0.04em pull that used to sit here compensated for Caveat's wide left
     side bearing on the L. Fraunces doesn't have it, so the wordmark would sit
     off the grid. */
  /* A GAP BEFORE THE LEAD — 2026-08-26, "add a space under Lumi Libra before
     starting the blurb". There was none: measured, the distance from the
     wordmark's box to the lead's was 0px, because the h1 carries no bottom
     margin and the lead no top one. `line-height: 1.0` above is what made it
     read as tighter still — at that value the text box hugs the glyphs, so
     there is not even the usual half-leading between them.

     In `em`, so it tracks the wordmark rather than the root: this h1 is a clamp
     from 3.4rem to 7.29rem and a fixed rem gap would look generous at the small
     end and mean at the large one. 0.22em is ~26px at the 116px it sets on a
     1280 window. */
  margin-bottom: 0.28em;
}

/* Sized so line 2 measures the mock's 535px at 1280 — it has to stay on two
   lines, and at the 3rem this was first set to it broke to three. */
.hero .script {
  font-family: var(--font-serif);
  font-size: clamp(1.575rem, 2.61vw, 2.07rem);
  font-weight: 500;
  line-height: 1.2;
  color: #FFF;
}
/* Full white rather than the eyebrow's 0.92 — this is body-size text, and the
   alpha costs it about half a point of contrast it can't spare. */
.hero .lead { color: #FFF; }

.hero .wrap {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  gap: 3rem;
  align-items: center;
}

/* Three big washed-out butterflies used to drift across the left column at 18%
   opacity. At that size and that alpha they stopped reading as butterflies and
   became grey smudges behind the copy. The mock instead places a small number
   of crisp pieces at the edges, so each one is legible as a drawing. */

.hero-copy { position: relative; }

/* Butterfly plus its full dotted heart-loop, flying in beside the headline.
   Used whole — a cropped trail reads as a mistake rather than as motion.

   Dropped level with the eyebrow on 2026-08-04 so the trail's far end starts
   just past "to" in "Welcome to". Note which end that is: the transform mirrors
   the drawing, so the BUTTERFLY is at the right and the loose end of the dotted
   line at the left — and the two ends sit at different heights within the box
   (the tail ~40px lower than the butterfly), so aligning it to the eyebrow means
   measuring the painted tail, not the box's top-left corner.

   It used to sit in the band between the nav and the wordmark. Beside the
   headline it landed exactly on the sparkle marks at the end of "Libra" and
   buried them — keep it left of the wordmark. */
.hero-flight {
  top: -64px;
  left: 154px;
  width: min(280px, 46%);
  opacity: 0.9;
  transform: scaleX(-1);
}

/* The mock leaves a clear band of empty teal between the wordmark and the
   tagline — the two are separate statements there, where cramming them together
   made the tagline read as a subtitle of the logo. */
.hero-copy .script { margin: 2.5rem 0 1.9rem; }

/* The mock runs the lead the full width of the copy column, right up to the
   photo — 48% of the sheet, against the 31rem this was held to. */
/* margin-bottom was 2.2rem and is now 0: that space existed to separate the lead
   from the hero's button, and the button came out on 2026-08-26. Left in, it was
   35px of nothing at the foot of a copy block that is now vertically centred —
   which quietly pushed the whole block 17px above true centre. */
.hero-copy p.lead { max-width: 38rem; margin-bottom: 0; font-size: var(--t-base); line-height: 1.72; }

.hero-actions { display: flex; flex-wrap: wrap; gap: 1rem; }

.hero-figure { position: relative; }

/* Leaf line-art layered over the photo's left edge, so the photo sits *in* the
   illustration rather than beside it. */
/* The illustration files are drawn in teal and lavender, which vanish against
   the teal band. The mock draws its botanicals in white line-art over the
   colour, so anything sitting on the hero gets knocked out to white. */
.hero .deco,
.hero .flight {
  filter: brightness(0) invert(1);
}

.hero-flight { opacity: 0.7; }

/* White sprig curving around the hero photo's right edge.

   MIRRORED. As drawn the leaves fan up and to the RIGHT off a stem at the
   bottom-left, so left alone they open away from the photo; scaleX(-1) turns the
   fan inward so the sprig cups the photo instead of turning its back on it.

   A child of .hero-figure, so its insets are read off the photo's own box and it
   stays against that edge when the figure resizes — anchored to .hero it would
   drift as the band's width changed.

   It laps onto the photo, which is the point, and it survives there: this is
   line art with clear gaps, not a wash, so the forest reads through it. The
   .hero .deco knockout paints it white for free. Watch the right-hand end
   though — .hero is overflow:hidden, so anything past the page edge is cropped;
   keep most of the drawing inside x 1280. */
/* Side-view teal/purple butterfly on the photo's bottom-right corner, straddling
   the picture and the teal beyond it.

   z-index 2 for the same reason as the sprig above: .hero-photo is z-index 1, so
   a .deco's default 0 hides everything that crosses the picture.

   Exempt from the .hero .deco knockout. That rule paints hero decoration white
   because teal-and-lavender line art vanishes against the band — but this is a
   PAINTED piece whose whole point is its two colours, and white would erase it.
   The old .hero-bfly-photo carried the same exemption for the same reason.

   Kept small on Lauren's call ("not super big"). It is an accent on a corner,
   sitting next to a 500px photo and a sprig — at any size worth calling large it
   competes with both. */
.hero .deco.hero-corner-bfly { filter: none; }

.hero-corner-bfly {
  right: 5%;
  /* Positive, so its base sits ABOVE the photo's bottom edge. At -7% it hung
     below the corner where the blob has already curved away, so it read as
     floating on the teal rather than resting on the picture. */
  bottom: 4%;
  width: 21%;
  /* Deliberately NO opacity — full strength. Briefly set to 0.85 on 2026-08-06
     by mistake (Lauren meant the white butterfly on the other corner) and put
     back. It should stay at full strength anyway: these are PAINTED teal and
     purple washes, not line work, and washes go grey as they fade rather than
     getting quieter, the same reason .receive-title-bfly on the club page is
     never faded. Quieten this one with SIZE if it is ever needed. */
  z-index: 2;
  /* Facing left; the drawing faces right as exported. */
  transform: scaleX(-1);
}

/* The phone's stand-in for the butterfly above, which on a small screen crosses
   the hero's torn edge instead of sitting on the photo. Declared off here and
   switched on in the phone block, where it is placed and the reasoning lives —
   it must never appear at desktop widths, where its partner is already there. */
.hero-seam-bfly { display: none; }

/* Open-winged WHITE butterfly on the photo's opposite corner, top-left,
   straddling the picture and the teal. It was the painted teal-and-purple
   drawing until 2026-08-06, when Lauren swapped it for bfly-white-open-2 — so
   the two corners are now a painted piece and a line one rather than two
   painted ones.

   That swap is why this no longer carries `filter: none`. The exemption existed
   only to protect a two-colour painted drawing from the hero's
   `brightness(0) invert(1)` knockout; white line art wants that knockout, the
   same as every other piece in this band.

   Sized by eye against .hero-corner-bfly rather than by the percentage: this
   drawing is wide and shallow where its partner is tall, so equal widths would
   not read as equal butterflies.

   No mirror — the drawing is symmetric, so only the tilt gives it direction.

   z-index 2 stays: .hero-photo carries z-index 1, so at the default 0 whatever
   crosses the picture would simply disappear. */
.hero-corner-bfly-top {
  /* Well IN from the corner on both axes, at Lauren's call — it used to straddle
     the edge and she wanted it inside the picture. The insets are bigger than
     they look like they need to be because the photo is BLOB-MASKED: the visible
     picture pulls away from its own box at the corners, so a butterfly measuring
     as "inside the figure" up there is really floating on teal. At 14%/16% the
     painted drawing sits 61px in from the box's left and 81px down from its top,
     which clears the curve. */
  left: 14%;
  top: 16%;
  /* 26% -> 21% -> 17%. "A little smaller", twice; Lauren again on 2026-08-06:
     "make that a little faded and smaller." 105px -> 85px at 1280.

     Anchored by left/top, so unlike its partner on the opposite corner this one
     shrinks AWAY from the picture's edge — its top-left stays put and the drawing
     pulls in toward it. That is the safe direction here: the insets above exist
     to clear the blob mask's curve, and shrinking only increases that clearance.
     Re-check those insets if it is ever made BIGGER. */
  width: 17%;
  /* 0.8, from full strength. This one CAN be faded, where the painted butterfly
     on the other corner cannot: it is white line art over a knockout filter, so
     it has no colour to lose — it just gets thinner against the trees. The
     "white cannot be quietened with opacity" rule recorded elsewhere is about
     white on PALE grounds, where there is no contrast to spend; this sits on a
     dark forest photograph, which is the opposite case and where opacity is
     exactly the right lever. */
  opacity: 0.8;
  z-index: 2;
  transform: rotate(-12deg);
}

@media (max-width: 860px) {
  /* Kept on mobile at Lauren's request. The flight path is a wide, shallow
     trail — at this width it ran straight through "Welcome to" and the top of
     the wordmark, so it shrinks and tucks into the clear band above the
     eyebrow, still sweeping in toward the headline. */
  /* Dropped ~10px on 2026-08-04. At -3.6rem the trail crossed the bottom of the
     logo and the Weekly Song pill; at -3rem it clears both and sits in the band
     between the header and "Welcome to". That band is all there is — at 375 the
     header ends at y 60 and the eyebrow starts at 116, so this is about as low
     as it goes before the trail lands on the copy. */
  .hero-flight { width: 45%; left: 40%; top: -3rem; opacity: 0.6; }
}

/* The hero photograph, 2026-08-12 onward. It is a TORN EDGE at every width now
   — half the band on desktop, the full width of it on a phone — so the framed
   treatment this figure used to carry is gone rather than switched off: the
   blob mask, the white deckle drawn from the same mask, and the painted halo
   behind it (the `.painted .painted-halo` classes came off the markup).

   Each breakpoint sets the figure's own geometry and its own tear. What is
   shared lives here: the picture fills its box, and the teal overlay sits over
   it so the photo reads as part of the band rather than as a cut-out laid on
   top of it. The crop is shared too — `center 20%` puts the hair in frame,
   which is the reason the photo was chosen.

   THE OVERLAY IS ON ::after AND MUST STAY THERE. It was written on ::before
   first, which is `.painted`'s own pseudo-element; the rule switching the halo
   off was more specific and silently killed the overlay for three rounds. The
   classes are gone now, but ::after is where every breakpoint expects it. */
.hero-figure img.hero-photo {
  position: relative;
  z-index: 1;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 20%;
}

.hero-figure::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  background-color: rgba(20, 86, 94, 0.30);
  -webkit-backdrop-filter: blur(1px);
          backdrop-filter: blur(1px);
  pointer-events: none;
}

/* ---------- The split hero, 901px and up -------------------------------------
   Lauren, 2026-08-12: "i want the homepage hero photo to be half on the right,
   not in the frame." So above the phone breakpoint the photograph stops being
   a framed object in the right-hand column and becomes half the band, meeting
   the teal on a torn seam that runs down the page.

   Everything here is an OVERRIDE of the framed treatment above, and the
   breakpoint is where it all switches back. That is deliberate: the phone
   layout is one Lauren has already signed off, the framed photo is what the
   decoration down there is placed against, and a stacked half-and-half band
   would be a second design to maintain. Don't hoist these rules out of the
   media query. */
@media (min-width: 901px) {
  /* The band is taller than the copy needs, and the photograph is why. It is a
     1000x1280 portrait in a box the layout makes wide and short, and `cover`
     throws away the difference: at the old height the box was 640x597 and only
     73% of the picture's height survived — Lauren, 2026-08-12, "idk if i love
     that so much of the photo is cut out".

     Height is the only lever. Widening the photo half makes it worse, not
     better: a wider box at the same height is further from portrait, so MORE
     of the height goes. At 640 wide the scale is width-driven (0.64), so rows
     shown = height / 0.64 — 737px of band shows 90% of the photo and 819 shows
     all of it. The clamp reaches for that on a tall window and gives up
     gracefully on a short one, where a hero taller than the screen would push
     everything below the fold. */
  .hero { min-height: clamp(600px, 84vh, 820px); }

  /* The copy is no longer one column of a two-column grid — the figure has left
     the flow entirely, so the grid would stretch it across the whole band. */
  .hero .wrap { grid-template-columns: 1fr; }

  /* THE COPY CENTRES IN THE BAND — 2026-08-26, "lets space out the hero now".
     It follows removing the hero's button: the band's height is set by
     `min-height` and the photo, not by the copy, so losing the button left the
     text top-heavy with 254px of empty teal under it and 136 above.

     Flex rather than a bigger `padding-top`, because a hand-tuned number would
     be right at exactly one window size — this band's height is a clamp against
     84vh, so it changes with every viewport.

     WHAT MAKES THIS LAND CORRECTLY is the padding that was already here:
     8.5rem top against 7rem bottom. Centring inside the CONTENT box therefore
     centres inside an asymmetric space, which is what the eye wants — the nav
     sits over the top ~70px of the band and the torn edge eats ~43px off the
     bottom, so the true optical centre is lower than the arithmetic one.
     Measured at 1280: the copy lands at y207 against an optical centre of ~208.
     If that padding is ever retuned, this is what it is also doing.

     Only the absolutely-positioned children are unaffected — the figure, the
     sprig and the butterflies are all out of flow, so nothing else moves.
     Desktop only; the phone layout stacks and is a composition Lauren signed
     off separately. */
  .hero {
    display: flex;
    align-items: center;
  }

  /* The photo starts at 50vw, so the copy's ceiling has to be a fraction of the
     VIEWPORT, not a fixed measure. 33rem alone holds at 1280 (copy ends x588
     against a photo at x640) but not at the bottom of this range: at 901px the
     wrap is `100vw - 64px`, so 33rem would run to x560 against a photo starting
     at x450 — 110px of copy underneath the picture. 42vw keeps a channel at
     every width and the rem cap stops the measure growing past comfortable
     reading on a wide window.

     `.hero-copy p.lead` sets 38rem on its own and would otherwise be the one
     thing that reaches under. */
  .hero-copy { max-width: min(33rem, 42vw); }

  .hero-figure {
    position: absolute;
    /* Half the WINDOW, not half the wrap — the point of moving the figure out
       of .wrap in the markup. */
    inset: 0 0 0 50%;
    margin: 0;
    /* Under .hero .wrap, which is z-index 1. */
    z-index: 0;
    /* The tear, and the same two-layer construction .torn-bottom uses one axis
       over: a tile repeating DOWN the left edge, and a solid fill for
       everything to the right of it. The +1px on the solid layer closes a
       hairline the two layers otherwise leave between them at some widths. */
    --seam-w: clamp(30px, 3.6vw, 52px);
    -webkit-mask-image: url("../images/art/seam-left.svg"), linear-gradient(#000, #000);
            mask-image: url("../images/art/seam-left.svg"), linear-gradient(#000, #000);
    -webkit-mask-size: var(--seam-w) 480px, calc(100% - var(--seam-w) + 1px) 100%;
            mask-size: var(--seam-w) 480px, calc(100% - var(--seam-w) + 1px) 100%;
    -webkit-mask-position: 0 0, 100% 0;
            mask-position: 0 0, 100% 0;
    -webkit-mask-repeat: repeat-y, no-repeat;
            mask-repeat: repeat-y, no-repeat;
  }

  /* THE PICTURE moves down, which means the crop window moves UP — Lauren,
     2026-08-12, correcting a first pass that read it the other way. `cover` on
     a 1000x1280 photo in a 640x597 box scales by width, so 222px of the
     picture's height is surplus: 347 rows of the original file, and the shared
     `object-position: center 20%` in the base rule says where in that slack the
     window sits. Centred it showed rows 173-1106; at 20% it shows 69-1002, so
     the hair and the sun through it drop into frame and the forest floor goes
     out of the bottom. Lower number = photo lower on the page.

     Nothing to override here any more: since the framed treatment came off the
     figure the base rule already fills the box and carries the crop. */

  /* Scrim over the photo half. Not decoration, and not eyeballed — the header's
     cream links sit over this photograph's brightest sky, and unscreened the
     worst 10% of that area measures 1.4:1 against them.

     The stops are solved, not chosen. Compositing the photo's own pixels under
     the nav strip (x681-1220, y23-66) against rgba(17,78,88,a) and taking the
     brightest tenth as the worst case: a=0.62 gives 3.97:1, a=0.68 gives
     4.49:1, a=0.72 gives 4.89:1. So the top holds ~0.70 through the nav band
     and then falls away fast, which is why the ramp is uneven — the picture
     gets its light back by 26% down, where nothing is written over it.

     4.5:1 is the target because these are normal-size links. Note the site's
     own white-on-teal buttons sit at 3.95:1, so this is not the page's weakest
     contrast — but a photograph varies where a flat teal does not, and the
     failure mode here is sky, not brand colour.

     RE-SOLVE THIS IF THE PHOTO CHANGES. A darker picture wants less veil, and
     carrying these numbers over would flatten it for nothing.

     The base rule already lays the flat teal over the picture; this ADDS the
     gradient on top of it, and the two composite. Re-measured against the real
     stack rather than assumed: the alpha algebra predicted 0.54 would be enough
     and it measured 4.15:1, because the flat layer is a slightly lighter teal
     than the gradient's. Swept on the composite — 0.54/4.15, 0.58/4.41,
     0.62/4.67 — and 0.62 is the first that clears 4.5:1. Change either layer
     and re-sweep; they are not independent dials.

     `background-image` alone, so the base rule's `background-color` survives
     underneath. Using the `background` shorthand here would reset it to
     transparent and take the flat teal with it. */
  .hero-figure::after {
    background-image:
      linear-gradient(180deg,
        rgba(17, 78, 88, 0.62) 0%,
        rgba(17, 78, 88, 0.54) 13%,
        rgba(17, 78, 88, 0.12) 26%,
        rgba(17, 78, 88, 0) 44%);
  }

  /* Both of the framed photo's corner butterflies come off on this layout.

     The teal one had a replacement on the seam, .hero-split-bfly, until
     2026-08-24, when Lauren asked for the seam butterfly and its dotted trail
     to come out of the hero entirely. Nothing replaces them — the split hero
     carries no butterfly at desktop widths now. */
  .hero-corner-bfly { display: none; }

  /* The white one was placed well inside a blob-masked photo, and on a
     full-bleed half there is no inside for it to be well within — it just
     floats in the picture. */
  .hero-corner-bfly-top { display: none; }
}

/* ---------- Phone and tablet: the split, turned 90 degrees -------------------
   ADOPTED 2026-08-12, after Lauren compared it against the framed photo.

   The desktop split does not survive a phone: measured at 390px it leaves the
   copy 194px (a 22-character measure, wordmark broken over two lines) and the
   photo a 172px strip with the hair flip outside it entirely. A portrait
   screen fights a vertical seam.

   So the same idea rotated: the picture takes the FULL width at the foot of
   the band, unframed, and meets the teal on a horizontal torn seam. It reuses
   --wave-top, the site's existing tile, at the photo's top edge — the same
   construction .torn-top uses, on an element rather than a section.

   The band's own .torn-bottom then tears the photo's bottom for free, so the
   picture ends in the page's torn edge instead of a straight line. That only
   works because the section's bottom padding is dropped here: with padding the
   photo stops short and the tear cuts teal below it.

   This also covers 761-900, which the split left with no layout at all — the
   figure is no longer a grid item, so without this it landed as a full-width
   block under a wrap still holding an empty second column.

   EVERY SELECTOR HERE IS PREFIXED `.page-home`, and not for scoping — for
   specificity. The phone block at the foot of this file (max-width: 760px)
   sets `.hero-figure { max-width: 420px; margin }` and `.hero { padding-bottom:
   10rem }`, and being LATER in the file it wins at equal specificity. Written
   plainly, this block silently did nothing below 760: the figure stayed 326px
   wide and 160px short of the tear. */
@media (max-width: 900px) {
  .page-home .hero { padding-bottom: 0; }
  .page-home .hero .wrap { grid-template-columns: 1fr; }

  .page-home .hero-figure {
    width: 100%;
    max-width: none;
    /* Height tracks the WIDTH, not the viewport height, and that is the whole
       point. Sized in vh it was 280-360px at every width, which is fine on a
       phone and badly wrong on a tablet: at 700px wide the band was 700x280
       against a 1000x1280 portrait, and `cover` kept just 31% of the
       picture's height. The wider the screen got, the more of the photograph
       it threw away.

       72vw holds the box near the picture's own proportions as it grows.
       Measured: 390 -> 330px box, 66% of the photo; 700 -> 504, 56%; 900 ->
       520 (the cap), 45%. The cap is there because a band that keeps growing
       eventually pushes the copy off a laptop screen entirely.

       330 floor, not 280: at 280 a phone showed less of the picture than the
       framed photo it replaced, which defeats the reason for the change. */
    height: clamp(330px, 72vw, 520px);
    margin: 2.4rem 0 0;
    -webkit-mask-image: var(--wave-top), linear-gradient(#000, #000);
            mask-image: var(--wave-top), linear-gradient(#000, #000);
    -webkit-mask-size: var(--wave-tile) var(--wave-h), 100% calc(100% - var(--wave-h) + var(--wave-overlap));
            mask-size: var(--wave-tile) var(--wave-h), 100% calc(100% - var(--wave-h) + var(--wave-overlap));
    -webkit-mask-position: 0 0, 0 100%;
            mask-position: 0 0, 0 100%;
    -webkit-mask-repeat: repeat-x, no-repeat;
            mask-repeat: repeat-x, no-repeat;
  }

  /* The teal overlay comes from the base rule and is right as it stands here.
     No nav scrim on top of it, unlike desktop: down here the header sits on the
     teal, not on the photograph, so the picture only needs the colour tie. The
     picture, the crop and the overlay are all inherited — this block sets
     geometry and the tear, nothing else. */

  /* The white butterfly was placed inside a blob-masked photo and has no inside
     to sit within here, exactly as on the desktop split. */
  .page-home .hero-corner-bfly-top { display: none; }

  /* The sprig crossing the tear: WHITE on the photograph, TEAL on the paper
     below it — Lauren, 2026-08-12.

     Nothing new is drawn for this. The crossover already exists and already
     changes colour on the real torn contour: .vine-crossover-white is a child
     of .hero, so the band's own .torn-bottom mask crops it at the tear, and
     .vine-crossover-clip in .remember carries the teal half below. What broke
     it here is PAINT ORDER, not colour. The white half sits before the figure
     in the markup and both resolved to z-index 0, so once the photo became a
     full-width layer at the foot of the band it simply covered the white
     leaves — visible as teal below the tear and nothing at all above it.

     z-index 3 puts the white half over the photo and its overlay (which is 2,
     inside the figure). It cannot spill onto the paper: the hero's mask still
     ends it at the tear, whatever its z-index. */
  .page-home .vine-crossover-white { z-index: 3; }
}

/* ---------- Flight paths ----------
   These read as one butterfly travelling down the page: it sets off in the hero,
   carries the eye into the pillars, leads to the Join button, and lands at the
   signup. Each is used WHOLE — butterfly plus its full dotted trail, flying from
   one point to another. Never crop one; a clipped trail reads as a mistake, not
   as motion. Every placement below is sized to sit entirely inside its section,
   including the sections that clip (.hero and .note-reminders are overflow:hidden). */
.flight {
  position: absolute;
  z-index: 0;
  pointer-events: none;
  opacity: 0.85;
}

/* Leads down the card toward "Learn More & Join". */
.flight-club {
  left: 8%;
  bottom: 6%;
  width: min(230px, 62%);
  opacity: 0.75;
}

/* ---------- Remember section ---------- */

/* ---------- The sprig that changes colour at the torn edge ----------
   One drawing, two copies at the same page position, each showing only on its
   own side of the hero's tear: white where it crosses the teal band, teal once
   it reaches the paper. Lauren's idea, 2026-08-03.

   The white half needs no clipping — .hero carries .torn-bottom, so its mask
   crops the sprig along the real torn edge for free.

   The teal half is clipped by .vine-crossover-clip instead. It cannot reuse the
   .torn-top mask: wave-top and wave-bottom are different curves, not
   complements, so masking with one against the other leaves a mismatched band.
   The wrapper is a plain overflow clip that starts level with the *top* of the
   tear, which means the two halves overlap by up to --wave-h rather than risking
   a gap in the stem. Teal over the band's own teal is nearly invisible; a break
   in the line would not be.

   Both halves must keep identical left/width/transform, and both resolve their
   percentages against a full-width box, or they stop reading as one drawing. */
.vine-crossover-clip {
  --crossover-h: 420px;
  position: absolute;
  left: 0;
  right: 0;
  top: calc(-1 * var(--wave-h));
  height: var(--crossover-h);
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
  /* MASKED WITH --wave-bottom-inv, not left as a plain overflow box — 2026-08-26.
     Lauren, of the sprig after it moved right: "part of the stem is in the teal."

     A plain box can only start level with the TOP of the tear, so between there
     and the real torn curve BOTH halves paint: the white one is cut by the
     hero's own .torn-bottom along the true edge, and the teal one, having no
     mask at all, keeps going up to --wave-h above the join. In the wave's peaks
     you get teal line art sitting in the teal band exactly where the white half
     was meant to be.

     THIS IS THE SAME BUG THE CLUB PAGE HIT AND FIXED, and the home page was
     explicitly written off as safe: the note in .claude/make-waves.py says the
     spill here "is teal over the band's own teal and invisible". It is not —
     leaf-vine-teal is a lighter, greener teal than the band, and at 0.55 the
     difference reads. The club's version is `.club-tear-clip`; this is the same
     four lines.

     --wave-bottom-inv is generated from wave-bottom's OWN seed, closed downward,
     so the two tile exactly. --wave-top is a different seed and a different
     curve — that is precisely why this could not simply reuse .torn-top.

     The alignment is by construction, not measurement: .hero's .torn-bottom puts
     its wave layer at `0 100%`, so the tear is the hero's last --wave-h pixels;
     this clip's top is one --wave-h above .offerings, whose top IS the hero's
     bottom, so the clip's first --wave-h pixels are that same band, and both
     tile --wave-tile from x0 of a full-bleed box. White above the curve, teal
     below, no overlap and no gap in the stem.

     `overflow: hidden` stays but is now only the BOTTOM bound; the top edge is
     the mask's job. */
  -webkit-mask-image: var(--wave-bottom-inv), linear-gradient(#000, #000);
          mask-image: var(--wave-bottom-inv), linear-gradient(#000, #000);
  -webkit-mask-size: var(--wave-tile) var(--wave-h), 100% calc(100% - var(--wave-h) + var(--wave-overlap));
          mask-size: var(--wave-tile) var(--wave-h), 100% calc(100% - var(--wave-h) + var(--wave-overlap));
  -webkit-mask-position: 0 0, 0 100%;
          mask-position: 0 0, 0 100%;
  -webkit-mask-repeat: repeat-x, no-repeat;
          mask-repeat: repeat-x, no-repeat;
}

.vine-crossover-white,
.vine-crossover-teal {
  /* How far the sprig's foot sits below the hero's bottom edge. Both halves
     derive their offset from this one value, so they cannot drift apart.

     16rem -> 18rem on 2026-08-24: "move the vine in the hero down more so the
     stem is resting at the bottom of the teal section". At 16 the bare stem end
     floated at y685 with the tear at y768-820, ~100px of empty teal under it.

     It went to 20 first and came back to 18 when the sprig was also made
     smaller in the same pass (see the width below). The two knobs are coupled:
     the piece is anchored from its BOTTOM, so shrinking it pulls the painted
     arc down as well, and 20rem at 280px left only 47px of vine above the tear
     — nearly the whole drawing had fallen into the cream. 18rem at 280px puts
     79px of it in the teal, which is what 20rem at 320px gave.

     Do not go past ~20 at any width. 22 was tried and drops the whole leafy body
     out of the teal and onto the heading below — the piece stops reading as a
     sprig in the hero and starts reading as one in the cream section. */
  --crossover-drop: 18rem;
  /* Turned 30deg off vertical and brought in off the page edge so the arc opens
     toward the empty pocket under the subhead rather than hugging the margin —
     it cups that space for a butterfly instead of running past it.

     It cannot be much larger than this here: the section heading is centred, so
     it occupies the band between the left edge and the prose columns, and every
     longer sprig tested crossed it.

     6% -> 3% on 2026-08-04. Change this on the SHARED selector only, never on
     one half: the two are pixel-identical copies and the colour change at the
     tear only works while they stay that way.

     3% -> -2% on 2026-08-24, and it was not a taste change — it paid for the drop
     above. The binding constraint then was `.remember`'s heading, which sat
     directly below: at left 3% the lowest leaves landed ON "become someone new."
     once --crossover-drop passed ~17rem.

     -2% -> 5% on 2026-08-26 — Lauren: "those leaves in the hero that overlap,
     move them more to the right." THAT OLD CONSTRAINT IS GONE: `.remember` is no
     longer the section under the hero, `.offerings` is, and its heading is
     CENTRED. What is below the sprig now is the first offering card.

     A TRAP THAT COST THE FIRST THREE SWEEPS, and it is worth knowing generally:
     measuring against `.offerings-heading`'s BOX said every value past 0% was a
     collision. That box is a full-width block running x60 to x1220 and is empty
     for the first 327px of it — the text is centred and starts at x387. Measure
     a centred heading with `Range.getClientRects()`, never its element box, or
     you will be avoiding a rectangle of nothing. With that fixed there was ~7x
     the room the box said there was.

     5% is the value that holds across the range where the drop is 18rem. The
     tightest width is ~1105, just above the breakpoint where --crossover-drop
     falls to 9.5rem; measured clearance from the sprig's lowest paint to the
     card's top edge is 28px there, 33 at 1150, 49 at 1280 and 180+ at 1920. 6%
     collides at 1105. Re-sweep if the card's top ever moves up. */
  left: 5%;
  /* min(320px, 25%) -> min(280px, 22%) on 2026-08-24: "make it a little smaller
     too it looks bigger than the other leaves on the page". She was right, and
     it was the only piece out of step — measured at 1280, every other leaf-vine
     on the page renders 205-280px (pillars-top 205, club-seam and club-white
     240, pillars-left 265, believe-cross/who-right/closing-right 280) and this
     one was 320. 280 puts it level with the largest of them rather than above
     them all; 260 was measured too and drops it below most of the page.

     Changing this REQUIRES re-checking --crossover-drop, for the bottom-anchor
     reason written there. */
  width: min(280px, 22%);
  opacity: 0.55;
  /* Mirrored and turned so the arc's concave side faces into the page. This
     transform must stay identical on both halves or they stop lining up and the
     colour change reads as two separate sprigs. */
  transform: scaleX(-1) rotate(150deg);
}

/* Both halves are anchored from their BOTTOM, and to the same page line — the
   white one 14rem below the hero's bottom edge, the teal one the same distance
   below it after cancelling the wrapper's height and its negative top. Anchoring
   from the bottom is what keeps them locked together: a `top` on the teal half
   would have to know the image's rendered height, which is derived from its
   width and so cannot be written here. */
.vine-crossover-white { bottom: calc(-1 * var(--crossover-drop)); }

.vine-crossover-teal {
  bottom: calc(var(--crossover-h) - var(--wave-h) - var(--crossover-drop));
}

/* Narrow: kept, not hidden. Lauren, 2026-08-04: "i do want the vines from the
   hero, the ones that go from white to teal, to appear on mobile", "coming from
   the top left corner and down". Both halves AND the clip used to be
   display: none here, which killed the colour change entirely — the teal half
   went with the clip, since it lives inside it.

   The override is written on the SHARED selector on purpose. Split it across the
   two halves and they drift, and the whole point of the piece is that one
   drawing changes colour at the tear. --crossover-drop is likewise shared, so
   both feet move together. */
@media (max-width: 1100px) {
  .vine-crossover-white,
  .vine-crossover-teal {
    /* 9.5rem, not the 11 first tried: at 11 the lowest leaf lands on "You're
       not here to". Swept against painted alpha with each half masked the way
       it actually paints — the white one cut at the hero's tear, the teal one
       cut to the clip — because the raw bounding boxes overlap that heading at
       every drop worth using. Below ~6rem the teal run under the tear gets too
       short to read as a crossover at all; 9.5 keeps ~1500px of it. */
    --crossover-drop: 9.5rem;
    left: -7%;
    width: min(230px, 52%);
    /* Dropping the desktop scaleX(-1) is what puts the bare stem at the left
       edge with the leaves running right and down — "flip it so the stem is
       coming from the left side". Same move as .vine-who-right's narrow rule:
       the mirror is the part that swaps stem and leaves end for end. Overridden
       on the shared selector so both halves stay one drawing. */
    transform: rotate(150deg);
  }
}

/* Open-winged teal/purple butterfly under the "You're here to remember who
   you've always been" subhead — Lauren: "have it tilted to the right".

   This is the pocket the mock always wanted decorating: the left column runs out
   of copy at the subhead's last line (y 1188) while the prose beside it carries
   on to 1553, leaving ~360px of empty paper. See the note in the markup.

   Anchored to .remember with a px `top` measured from the section's own top. The
   section's height is set by the PROSE columns, not by this side, so anchoring
   from its bottom would drift this piece whenever that copy changed. Re-derive
   if the heading or subhead gains a line.

   Clear of .vine-crossover-teal, whose foot stops at y 1153 — the two share this
   column and it is the only thing above the butterfly.

   NO rotation, on Lauren's call after seeing it at 16deg. Every other butterfly
   on the page is tilted; this one sits square, centred under a centred subhead,
   and that is the point of it. Don't "fix" it back to an angle for consistency. */
/* Brought up from 390px and down from 200px wide on 2026-08-05, Lauren's call —
   "sit closer to the copy above it… a little smaller, not too much". The gap
   under .remember-sub goes 46px -> 24px. Measured against the subhead's last
   line at y 344, so re-derive if it gains one.

   Then 178 -> 145 on 2026-08-06: "make the butterfly under 'youre here to
   remember…' smaller / and center it under."

   IT WAS NOT ACTUALLY CENTRED, and `left: 13%` could not have kept it centred at
   any size. Measured at 1280 it painted x168-342, centre 255, against the
   subhead's centre of 275 — 20px off. Worse, the error grew with the window: the
   subhead lives in .remember-intro inside `.wrap`, which is `min(1160px, 92%)`
   and therefore CAPPED, so above a ~1261px viewport the column stops moving
   outward while a percentage offset keeps going. At 1512 the old rule put the
   painted centre at 286 against a target of 391 — **105px out**.

   `calc(50% - 438px)` fixes it exactly, and the two constants are derived rather
   than tuned:
     - the intro column's centre is a constant **365px left of the page midline**
       for every viewport at or above 1261, because the wrap is a fixed 1160
       centred there;
     - this drawing's painted centre sits **73px** right of its element's left
       edge at 145px wide, sampled from its alpha rather than assumed, since the
       butterfly is not centred in its own frame.
   365 + 73 = 438. **Re-derive that 73 if the width changes** — it scales with
   the drawing (65 at 130px, 89 at 178).

   Below 1261 the wrap becomes 92% and the column's centre goes proportional
   again, so the calc drifts there; it is off by ~18px at 1200. That range is
   short-lived — the piece is hidden entirely below the breakpoint further down
   this file — and it is a far smaller error than the one being fixed. */
.remember-bfly {
  top: 368px;
  /* The `max()` is a floor, added 2026-08-12 after a width sweep: `50% - 438px`
     is a fixed distance from the window's CENTRE, so it goes NEGATIVE once the
     window is under 876px wide. At 760 it resolved to -58px and 54% of the
     butterfly was off the left edge of the page — half a drawing at the margin,
     in the one band nobody had measured (it is hidden below 700, and correct
     from 908 up).

     16px matches the gutter `.wrap` uses. Above 908 the calc is the larger
     value and wins, so desktop is untouched — verified identical at 1100, 1280,
     1440, 1600 and 1920. */
  left: max(16px, calc(50% - 438px));
  width: min(145px, 14.2%);
  opacity: 0.9;
}


/* ---------- "Find What Lights You Up" — the three offerings, 2026-08-26 ------
   Three cards directly under the hero, one per offering, the whole card a link.

   WHY THIS SECTION HAS A LARGE TOP PADDING, and it is not taste. The sprig that
   crosses the hero's torn edge changes colour halfway down: the white half is a
   child of .hero, the teal half hangs in `.vine-crossover-clip`, and that clip
   is positioned against WHATEVER SECTION FOLLOWS THE HERO — which is this one
   now. Its foot lands --crossover-drop (18rem = 288px) below the hero's bottom
   edge, out in the left margin. The padding + the heading's own height and
   margin are what put the first card past that foot; measured at 1280 the
   sprig's lowest painted pixel sits 30px clear of the left card's top edge.
   Take either number down and the leaves land on the Sunday Spark photograph.

   NOT A COLOUR BAND. The site runs exactly two dark moments per page — the hero
   and the closing card — so this sits on the paper and takes its colour from the
   three photographs and a soft wash inside each card. See the note on the washes
   below.

   THE CARDS ARE `<a>` ELEMENTS. Two consequences worth knowing:
     · `main a:not(.btn):not(.nav-song):hover` repaints every descendant that
       inherits its colour, so the paragraph carries an explicit --charcoal. The
       h3 is already covered by the global `h1,h2,h3` colour.
     · Nothing inside may be interactive — no nested link, no button — or the
       markup stops being valid and the card stops being one target. */
.offerings {
  position: relative;
  /* 6.5rem -> 8rem on 2026-08-26, and still not --section-airy's 5.5. See the
     sprig note above: this padding is what holds the cards clear of it, and the
     extra 1.5rem is what bought the sprig room to move right to left:5% with a
     28px margin at the tightest width instead of 4px. The two numbers are a
     pair — move one and re-measure the other. */
  padding: 8rem 0 var(--section);
}

.offerings-heading {
  /* LAVENDER HEART, 2026-08-26 — Lauren: "make it lavender." `.heading-heart`
     reads --heart and falls back to --blob-teal, so this one property is the
     whole change.

     --blob-purple, NOT --lavender or --panel-lav. Those two are PANEL FILLS at
     L 78-80; a heart is a small mark on pale watercolour paper and they vanish
     on it — the identical trap the Sunday Spark heart hit in the closing band a
     few hours earlier, where the pale blues had to be passed over for an ink.
     --blob-purple is the same family carried to ink weight (patch #B5A5D1 ->
     #8B71B7, hue held), so it still reads lavender rather than as a second
     purple, and it measures 3.9:1 on the ground at the ~26px this renders at.

     If it ever wants to be deeper, --club-creative (#7958A3) is the next step
     and is already the Self-Love Club card's arrow ink in the row below — so
     the two would rhyme. It reads as violet rather than lavender, which is why
     it is not the default here. */
  --heart: var(--blob-purple);
  text-align: center;
  /* 2.9rem is the other half of the sprig clearance. Both this and the padding
     above are load-bearing; re-measure the vine if either moves. */
  margin-bottom: 2.9rem;
}

.offering-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(1.5rem, 2.4vw, 2.1rem);
  /* Stretch, so the three cards are one height however long the copy runs and
     the arrow links line up across the row — see .offering-link's margin-top. */
  align-items: stretch;
}

/* THE WASH PER CARD — rebuilt 2026-08-26. Lauren: "i want the style of the
   cards themselves to match more of the site as well."

   WHAT WAS WRONG. These were a white rectangle, a soft radial tint and a drop
   shadow. That is a perfectly ordinary card and it is the one container grammar
   this site uses nowhere else: every other block that holds content on colour is
   a WASH ON PAPER — `.painted`, `.painted-sage`, `.painted-lav`, the torn band
   edges, the blob-masked photos. A white box among them reads as imported.

   WHAT THEY ARE NOW. The same primitive as the panel washes, from the same
   generator — .claude/make-washes.py, extended there rather than reinvented
   here. Each card is a torn piece of watercoloured paper: a superellipse whose
   radius is perturbed by six octaves of summed sinusoids, baked into the path so
   it costs one small blur to render, with granulation pools inside so the fill
   is uneven pigment rather than flat colour. Three different seeds, so the three
   rims are three torn edges instead of one shape repeated.

   NO BORDER, NO SHADOW, NO RADIUS. There is no box to give a radius to. The
   feathered rim IS the edge, and a shadow under a torn wash would put the paper
   back. The drawings sit ON the wash — their grounds are transparent, so the
   colour runs through them, which is the whole reason this works.

   THE GROUNDS DO NOT FOLLOW THE PICTURES, and that was tested rather than
   assumed. When the drawings became photographs Lauren asked whether the wash
   could "match it better", so all three were re-derived from their own photo by
   hue histogram — and rejected: "i dont want those colors with it. do what was
   there before." She is right, and the reason generalises. All three
   photographs are warm, so grounds derived from them came out warm too — inside
   ~75 degrees of each other — and the row lost the colour spread that lets it
   read as three separate offerings. Gold, lavender and aqua span 250 degrees.
   A hue histogram is the right tool for choosing ONE ground and the wrong tool
   for choosing a SET. The full working is in .claude/make-washes.py.

   --card-fill IS A FILL, NOT AN INK, and that is the whole answer to a problem
   three colours failed at. The pill started with its text and border in an ink
   drawn from the club family. On the gold card that ink was --club-experiences,
   the palette's gold carried to ink weight — and gold sits at hue 45 where
   darkening runs into OLIVE, so the filled state read as army green. Lauren:
   "that yellow one is really ugly."

   Two replacements were tried and both were wrong in an instructive way. A
   derived terracotta measured fine and landed at hue 26, which appears nowhere
   on this site — "that doesnt go with the color palette at all", and she was
   right: deriving a colour correctly does not make it a Lumi Libra colour. Then
   the palette's rose, which was fine but is not yellow, and the card's wash is.

   THE REAL CONSTRAINT, measured rather than argued: no yellow that still reads
   as yellow can carry text here. On this card's ground, 4.5:1 demands a relative
   luminance at or under 0.159, and every hue from 38 to 54 at every saturation
   from 0.6 to 0.9 bottoms out between #7C7007 and #996408 — the olive again.
   Yellow is inherently light; contrast forces it dark. Lauren: "not as dark?"

   So the pill inverts. The colour becomes the FILL and --forest carries the
   text, which frees the fill to be the palette's actual --gold, --lavender and
   --aqua at full lightness. Navy on them measures 8.68 / 7.37 / 7.65, and the
   hover step 7.29 / 5.26 / 6.05.

   --card-fill-deep is each fill's own hue and HSL saturation with the lightness
   dropped 10 points — the same derivation --panel-teal-deep uses, and for the
   same reason: hover should read as the button darkening, not as a second
   colour. They are literals because the palette has no deep twins for these
   three; if it ever grows them, swap these out.
   */
.offering-card:nth-child(1) { --card-wash: url("../images/art/wash-card-gold.svg"); --card-tear: url("../images/art/torn-paper-a.svg"); --card-tint: var(--c-gold); --card-fill: var(--gold);     --card-fill-deep: #E9B353; }
.offering-card:nth-child(2) { --card-wash: url("../images/art/wash-card-lav.svg");  --card-tear: url("../images/art/torn-paper-b.svg"); --card-tint: var(--c-lav);  --card-fill: var(--lavender); --card-fill-deep: #B095C6; }
.offering-card:nth-child(3) { --card-wash: url("../images/art/wash-card-aqua.svg"); --card-tear: url("../images/art/torn-paper-c.svg"); --card-tint: var(--c-aqua); --card-fill: var(--aqua);     --card-fill-deep: #82B5AE; }

/* BOTH of these urls are declared AND used inside this file, which is what makes
   the relative "../images/art/..." correct. A url() in a custom property resolves
   against the stylesheet where the property is USED, not where it is declared —
   the same three lines written into a page's inline <style> resolve against
   /css/ instead and 404 in silence, because the body's own watercolour pools
   show through an empty wash and nothing looks broken. That cost a wrong render
   on the comparison page; see the note there. */

.offering-card {
  position: relative;
  /* Its own stacking context, so the wash on ::before at z-index -1 is guaranteed
     to sit behind this card's content and nothing else. Without it the card only
     becomes one on hover, when the transform makes it a containing block, and the
     wash would change what it paints behind at that moment. */
  isolation: isolate;
  display: flex;
  flex-direction: column;
  text-decoration: none;
  color: var(--charcoal);
  transition: transform 0.3s ease;
}

/* The wash. Bled past the card on every side — a wash laid on paper runs wider
   than the words on it, and the rim needs somewhere to fray that is not the text.

   REM, NOT PERCENT, and that is worth keeping. A percentage on `top`/`bottom`
   resolves against the CARD's height, which changes with the copy, the breakpoint
   and the stacked layout — so the bleed under the arrow link would be a different
   distance on every card and every width. These are absolute.

   The numbers, and what each is paying for. The generated shape fills ~94% of its
   own box (fill=0.47 in make-washes.py), so the painted rim lands ~6% inside
   whatever this box is — subtract that from each figure to get the real clearance:
     · 1.15rem sides (18px) -> ~6px of paint past the card. The grid gap is 2.1rem,
       so ~22px of bare paper still separates neighbouring washes. Widen this and
       they start to touch, and three touching washes read as one band.
     · 1.4rem top (22px) -> ~10px above the drawing.
     · 2.1rem bottom (34px) -> ~24px under the arrow link. This is the one that
       matters: at an even inset the link sat ON the rim, which reads as the copy
       having outgrown the paint.

   `opacity` rather than baking the alpha into the SVG, exactly as .painted-sage
   does — it is the one dial to turn if this ever reads as too much colour, and
   the file stays usable at full strength somewhere else. */
.offering-card::before {
  content: "";
  position: absolute;
  inset: -1.4rem -1.15rem -2.1rem;
  z-index: -1;
  background-image: var(--card-wash);
  background-repeat: no-repeat;
  background-size: 100% 100%;
  opacity: 0.55;
  transition: opacity 0.3s ease;
  pointer-events: none;
}

/* THE FRAME, and the whole reason the pictures are interchangeable. A fixed box
   plus object-fit: cover on the image means a replacement of ANY size or ratio
   fills it edge to edge, cropped from the centre, never stretched — and the three
   cards keep one picture height, so the names and links stay on the same lines
   across the row. Change the ratio here and it changes on all three at once; that
   is the point.

   4:5 PORTRAIT, 2026-08-26. It has been 4:3 (built) then 3:2 (Lauren's drawings,
   all 1536x1024) and is now 4:5, because the pictures are her own photographs and
   every one of them is a 3024x4032 phone frame. A landscape crop of a portrait
   throws away half the picture and puts her head at the top edge.

   TORN, NOT BOXED — and this is the half that makes photographs work here at all.
   The card is a wash with no straight edge anywhere on it; a rectangular
   photograph laid on that is the one hard edge in the whole section, and it reads
   as a snapshot taped to the page. The mask is the site's own torn-paper-a/b/c,
   the same three files the About page's mounts use, one each so the three cards
   are three torn edges rather than one shape repeated.

   NO COLOURED MOUNT, unlike the club page's chalk row, which pads its photos and
   paints the padding. The wash behind these already IS the colour; a mount as
   well would be two grounds arguing.

   `overflow: hidden` stays and still earns its place: it guarantees a
   replacement picture cannot spill past the box the other two are measured by,
   whatever the mask does. */
.offering-photo {
  position: relative;          /* the tint on ::after hangs off this */
  aspect-ratio: 4 / 5;
  overflow: hidden;
  -webkit-mask: var(--card-tear) center / 100% 100% no-repeat;
          mask: var(--card-tear) center / 100% 100% no-repeat;
}

/* THE TINT, 2026-08-26 — Lauren: "what if we added slight tints to each photo".
   Each photograph takes its own card's colour, so the picture and the wash under
   it stop being two separate objects.

   IT IS A GRADIENT, NOT A FLAT WASH, and that is the whole idea: strongest along
   the BOTTOM edge, where the photo meets the card's wash, and almost gone at the
   top. It reads as the wash soaking up into the picture rather than as a colour
   filter laid over it — the same thing the torn edges and the washes are doing
   everywhere else on this page.

   PLAIN ALPHA, NO BLEND MODE. `multiply` was the obvious choice and is wrong
   here: all three channels are light colours (gold 239,199,128; lavender
   201,182,216; aqua 162,200,195), so multiply darkens the photographs — and
   these three were graded to sit bright on pale paper, which took several
   passes. A straight overlay lightens toward the tint instead, which is what
   keeps them airy. `soft-light` was also tried: it barely reads at these alphas
   and needs roughly double, at which point it starts eating the shadows.

   0.24 -> 0.06 is deliberately shy of what you would notice on its own. Pull it
   up and the three photographs stop looking like photographs; the job is to make
   the row feel like one thing, not to colourise it.

   Clipped by the torn mask above, because it is inside the masked element. */
.offering-photo::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(to top,
    rgba(var(--card-tint), 0.24) 0%,
    rgba(var(--card-tint), 0.13) 48%,
    rgba(var(--card-tint), 0.06) 100%);
  transition: opacity 0.3s ease;
}

.offering-photo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.offering-body {
  /* Column + flex:1 so the link can be pushed to the foot of the card, whatever
     the paragraph above it does. */
  display: flex;
  flex-direction: column;
  flex: 1;
  /* Inset from the wash rather than from a card edge — there is no edge. The
     side padding is deliberately light: the wash bleeds outward, so the copy
     already has that much clear paper beside it. */
  padding: 1.2rem clamp(1.1rem, 1.8vw, 1.5rem) 1.4rem;
  /* Centred at Lauren's ask, 2026-08-26 — and it is the setting that belongs
     here anyway: every other picture-and-copy tile on this site is centred
     (.pillar, .inside-card, .week-item), and each of these sits on a wash with
     no straight edge for a left margin to line up against. Ragged-right copy
     against a torn rim was the one thing making the block still read as a box.

     The h3, the paragraph and the link are flex items stretched to the body's
     full width, so this centres each one's own text rather than shrink-wrapping
     them — which is what keeps the arrow link's `margin-top: auto` working and
     the three links level across the row. */
  text-align: center;
}

.offering-body h3 { margin-bottom: 0.55rem; }

.offering-body p {
  /* Explicit, because the card is an <a> — see the note at the top. */
  color: var(--charcoal);
  font-size: var(--t-base);
  line-height: 1.65;
  margin-bottom: 1.1rem;
  /* Centred copy has no fixed left edge, so an over-long line is harder to read
     back than the same line ranged left. 22rem is under the card at every desktop
     width and only bites once the cards stack, where the card can reach 26rem —
     which is exactly where the measure was going to run long. */
  max-width: 22rem;
  margin-inline: auto;
}

/* THE LINK IS A PILL — 2026-08-26. Lauren: "could we make it a little more
   noticeable so people know its clickable."

   It was coloured uppercase text with an arrow, which reads as a link only once
   you are already reading it. The site has exactly one shape that means "this
   does something" — the bordered pill on `.btn` — so the card borrows it rather
   than inventing a third signal. That also fixes the affordance at REST: the
   lift and the wash and the arrow were all hover-only, and hover tells you
   nothing until you are already there. On a touch screen it told you nothing at
   all.

   STILL A <span>, NOT A BUTTON OR A NESTED <a>. The whole card is the target;
   an interactive element inside an interactive element is invalid and would
   split the hit area in two. This is a button that looks like one and is not
   one, which is exactly right when its parent is already the link.

   Smaller than a real .btn (0.94rem against 0.977, and roughly two-thirds the
   padding): three full-size buttons in a row would be the loudest thing on the
   page, and this row is a signpost, not the page's call to action — that is the
   hero's job.

   `align-self: center` is load-bearing. .offering-body is a flex COLUMN, so this
   span is a flex item and would otherwise stretch to the full width and lose its
   pill shape; text-align on the parent cannot centre a stretched box. And
   `margin-top: auto` still pushes it to the foot of the card, which is what
   keeps the three level across the row. */
.offering-link {
  margin-top: auto;
  align-self: center;
  font-family: var(--font-body);
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--forest);
  background-color: var(--card-fill);
  padding: 0.68rem 1.4rem;
  border-radius: 999px;
  transition: background-color 0.25s ease;
}

.offering-arrow {
  display: inline-block;
  margin-left: 0.35em;
  transition: transform 0.25s ease;
}

/* HOVER — guarded, so a phone never sticks in the hovered state after a tap.

   The card used to lift and deepen a drop shadow. With the shadow gone the move
   belongs to the WASH: more pigment, as though the brush went over it again. The
   2px lift is the one the buttons use (.btn:hover), kept because it is the site's
   own signal that a thing is pressable.

   The picture no longer zooms. A `scale` inside .offering-photo was legible when
   that box clipped a photograph against a white card edge; against a torn wash
   the clip line is invisible, so the zoom read as the drawing being cropped for
   no reason. */
@media (hover: hover) and (pointer: fine) {
  .offering-card:hover { transform: translateY(-2px); }
  .offering-card:hover::before { opacity: 0.72; }
  /* The ground gains colour and the picture loses its veil — the two halves of
     the same move, rather than a second unrelated one. */
  .offering-card:hover .offering-photo::after { opacity: 0.45; }
  /* And the pill deepens — same hue, ten points of lightness. Navy still
     measures 7.29 / 5.26 / 6.05 on the three deeper fills. */
  .offering-card:hover .offering-link { background-color: var(--card-fill-deep); }
  .offering-card:hover .offering-arrow { transform: translateX(5px); }
}

/* Keyboard users get the same card, outlined. `:focus-visible` rather than
   `:focus` so a mouse click never paints a ring. The ring is a plain rounded
   rectangle on purpose — it marks the HIT AREA, which is the rectangle, not the
   torn wash bleeding past it. */
.offering-card:focus-visible {
  outline: 3px solid var(--teal);
  outline-offset: 4px;
  border-radius: 6px;
}

@media (prefers-reduced-motion: reduce) {
  .offering-card,
  .offering-card::before,
  .offering-photo::after,
  .offering-link,
  .offering-arrow { transition: none; }
  .offering-card:hover { transform: none; }
}

/* Three across needs room. Below this the cards are under ~250px wide, which
   puts the longest description on seven lines and the photo at 250x188 — so the
   row goes to one column here rather than at the usual 700, and never sits in a
   squeezed three-up. There is no two-up step: three cards make an orphan. */
@media (max-width: 860px) {
  .offerings {
    /* The sprig is a different piece below 1100 — --crossover-drop drops to
       9.5rem there and `left` to -7%, so this padding is not clearing the same
       geometry the desktop one is.

       5.5rem -> 7rem on 2026-08-26. At --section-airy the sprig's lowest leaves
       were putting 9 painted pixels on the heading's TEXT at 390 — pre-existing
       since this section was built, and only caught because the desktop move
       right prompted a proper sweep. 7rem clears it with the sprig untouched,
       which is the right lever: its 9.5rem drop and -7% are a phone placement
       Lauren signed off, and lifting the sprig to fix a heading would undo it.
       Measured at 390: 0 hits on the heading text and 125px to the first card. */
    padding: 7rem 0 var(--section);
  }
  .offerings-heading { margin-bottom: 2.2rem; }
  .offering-grid {
    grid-template-columns: 1fr;
    /* 2rem -> 3.4rem. Stacked, the washes bleed 1.4rem up and 2.1rem down, so a
       2rem gap left the three of them touching down the column — one continuous
       band of colour rather than three torn pieces. This clears the bleed with
       ~0.6rem of bare paper to spare. It is not the desktop gap's concern: side
       by side the bleed is only 1.15rem and the row's own 2.1rem already clears
       it. */
    gap: 3.4rem;
  }
  /* A single column would otherwise run the picture the full width of the phone
     and push the third card two screens down. Held to a comfortable measure and
     centred, which also stops the paragraph reaching ~90 characters on a tablet. */
  .offering-card { max-width: 26rem; margin-inline: auto; width: 100%; }
}

.remember {
  position: relative;
  padding: var(--section-airy) 0 var(--section);
  background:
    radial-gradient(ellipse 24% 34% at 100% 14%, rgba(var(--c-blue), 0.38), transparent 70%),
    radial-gradient(ellipse 26% 32% at 0% 84%, rgba(var(--c-lav), 0.34), transparent 70%),
    radial-gradient(ellipse 18% 24% at 3% 6%, rgba(var(--c-sage), 0.30), transparent 72%),
    var(--soft-white);
}

/* Photo dropped at Lauren's request 2026-08-03. Without it the heading anchors
   its own narrow column and the prose runs in two columns beside it, as the
   mock does — a single wide measure here would run to ~110 characters. */
.remember .wrap {
  position: relative;
  display: grid;
  grid-template-columns: 0.78fr 1.22fr;
  column-gap: clamp(2rem, 4.5vw, 4rem);
  align-items: start;
}
.remember .wrap > :not(.deco) { position: relative; z-index: 1; }

.remember-intro { grid-column: 1; }
.remember-cols  { grid-column: 2; }

@media (max-width: 860px) {
  .remember .wrap { display: block; }
  .remember-intro { margin-bottom: var(--space-md); }

  /* The butterfly comes off with the columns, 2026-08-12. It lives in the band
     to the LEFT of the prose, and this is the line where that band stops
     existing — the copy goes from starting at x373 to starting at x34.

     There is no placement to fall back on: with the prose full-width, anything
     on the page here paints on it (2772 sampled points on "So many of us lost
     touch with ourselves." at 760, 3277 at 840), and the alternative it had
     before today was hanging half off the left edge, which is how it rendered in
     this band until the sweep found it. Below 700 it was already hidden. */
  .remember-bfly { display: none; }
}

.remember-heading { margin-bottom: 0.7rem; }

.remember-sub {
  margin: 1.6rem 0 0;
  font-family: var(--font-body);
  font-size: 1.11rem;
  font-weight: 600;
  letter-spacing: 0.13em;
  line-height: 1.7;
  text-transform: uppercase;
  color: var(--teal-label);
  max-width: 17rem;
}

/* Centred under the heading above it, desktop only — below 860px this column
   goes full width and the section has its own stacked treatment.

   `margin-inline: auto` is the half that matters, and it has to come *after* the
   `margin` shorthand above: the shorthand resets the inline margins to 0, so
   declared earlier this would be silently overridden and the block would stay
   pinned to the column's left edge with only its text centred inside it. */
@media (min-width: 861px) {
  .remember-heading,
  .remember-sub {
    text-align: center;
  }
  .remember-sub { margin-inline: auto; }
}

/* ---------- Keeping a phrase whole ---------- 2026-08-26
   Lauren, of the About page at 390: "the emojis on mobile after personal hype
   woman get split between lines, is they a way to keep them on the same line."

   There is: the break opportunity is the SPACE before them, so the fix is to
   remove that opportunity rather than to touch the type. `nowrap` on a span that
   holds the last word and the emojis makes the three a single unbreakable unit —
   if it does not fit, the whole unit wraps together and the emojis stay with the
   sentence they belong to instead of opening the next line on their own.

   Deliberately NOT `&nbsp;` alone: a non-breaking space would glue the emojis to
   the word, but the two emojis could still be split from EACH OTHER, which is the
   same fault one character further along.

   Keep the span small. Wrapping a long phrase in nowrap is how a line ends up
   running off a 320px screen. */
.keep-together { white-space: nowrap; }

/* The small heart the mock sets beside several headings — filled since
   2026-08-26, and on the same `--heart` property as the list bullets so a section
   that sets one gets it here too. The default is the paper colour from the table
   on .believe; --bullet-blue, the mock's grey-blue, is what it used to be and now
   reads as a smudge once the outline is filled in. */
.heading-heart,
.heart {
  color: var(--heart, var(--blob-teal));
}

.heading-heart {
  font-size: 0.66em;
  vertical-align: 0.22em;
  margin-left: 0.15em;
}

/* BLUE beside Sunday Spark, 2026-08-26 — Lauren: "make the heart next to sunday
   spark blue on the bottom of hojme page." Its neighbour in the same band, "A
   Note From Me", keeps the paper teal, so the two columns now differ the way the
   panels above them do.

   --spark-blue, and it went there in two steps. It was --club-playlist first —
   the 1:1 page's `.oto-do` choice, and the only ready-made blue in the palette
   dark enough to read on white paper — but that colour is a slate tuned for 15px
   labels, and at heart size Lauren read it as grey: "make it a shade of blue that
   pops more." --spark-blue is --periwinkle carried to ink weight, so the pop
   comes from saturation rather than from going darker still. See the token.

   The pale blues are not options here: --panel-blue, --butterfly-blue and
   --periwinkle are panel fills and vanish on this ground. */
.closing-band .reminders { --heart: var(--spark-blue); }

/* Beside the small-caps labels 0.66em lands at 9px, which reads as a speck.
   These want to be a shade larger than their heading, not smaller. */
.closing-band .note-copy h2 .heading-heart,
.closing-band .reminders h2 .heading-heart {
  font-size: 1.25em;
  vertical-align: -0.06em;
  letter-spacing: 0;
  margin-left: 0.3em;
}

/* Five narrow columns gave this section a ~28-character measure, which made the
   most important writing on the page read like fine print. The paragraphs now
   flow down one comfortable column. Indented a little from the heading above,
   as in the mock, so the block reads as the body of what the heading announces. */
.remember-cols {
  columns: 2;
  column-gap: clamp(1.5rem, 3vw, 2.6rem);
  font-size: var(--t-base);
  line-height: 1.8;
  margin-left: 0;
  max-width: none;
}

/* A blue sketch butterfly sat under "Those parts of us never actually went
   anywhere" for a while on 2026-08-04 and was removed. It moved right twice, ran
   out of column, and the only ground further right was the 60px page margin,
   where it had to shrink to ~50px and still clipped the edge once rotated.
   Nothing here to restore — noted so the same corner does not get re-proposed. */

.remember-cols > div { break-inside: avoid; }

.remember-cols > div + div { margin-top: 0.95rem; }

@media (max-width: 700px) { .remember-cols { columns: 1; } }
.remember-cols p + p { margin-top: 0.95rem; }

/* Photos laid on the page, corners squared and slightly tipped. The tall variant
   carries a portrait crop; the base .polaroid is square-ish. */
.polaroid-tall img { aspect-ratio: 4 / 5; object-fit: cover; }

/* ---------- Pillars ---------- */

.pillars {
  /* Kept relative although nothing is anchored to the section any more: the two
     vine segments hang off .wrap, and .pillars-flight — the one piece that
     needed the section's own box, to start at the page margin rather than the
     wrap's inset — was removed on 2026-08-24 at Lauren's ask. */
  position: relative;
  padding: var(--section) 0;
  text-align: center;
  background:
    radial-gradient(ellipse 24% 34% at 0% 12%, rgba(var(--c-blue), 0.36), transparent 70%),
    radial-gradient(ellipse 26% 32% at 100% 90%, rgba(var(--c-lav), 0.36), transparent 70%),
    radial-gradient(ellipse 20% 26% at 90% 4%, rgba(var(--c-pink), 0.15), transparent 72%),
    var(--cream);
}



/* The opener is a single small label now — Lauren cut the intro paragraph that
   used to sit under it ("Lumi Libra is a place to reconnect with yourself…"), so
   there is no left column left to justify a two-column grid. The label sits above
   the row and the five pillars take the full width. */
.pillars { text-align: left; }

.pillars .wrap {
  width: min(1260px, 94%);
  position: relative;
}

/* Lifts the real content above the decoration. `.deco` must be excluded as well
   as `.flight`: this selector outranks `.deco { position: absolute }`, so any
   deco added here is pulled back into flow and claims layout height — it added
   ~380px to this section and pushed the heading below the pillars before it was
   caught. Same hazard as the `.club-card > *` rule. */
.pillars .wrap > :not(.flight):not(.deco) { position: relative; z-index: 1; }

/* Heavier and larger than the site's other eyebrows. This one is not a label on
   a block of copy — with the intro paragraph gone it is the only thing announcing
   the section, so at the shared 0.78rem/400 it read as a caption floating above
   five icons rather than as a section opening. */
.pillars .eyebrow {
  letter-spacing: 0.14em;
  font-size: 1.166rem;
  font-weight: 700;
  color: var(--navy);
  margin-bottom: 2.8rem;
}

/* Centred within each column — patch, title and copy all on one axis. This was
   left-aligned to match the mock; Lauren asked for centred.

   Staggered rather than ruled into a straight row, which is what she asked for
   ("a more playful layout").

   An earlier attempt at this failed and the reason matters: the pillars were
   given *irregular* heights, which read as a broken grid rather than as
   hand-placement — five titles on five unrelated baselines with no line for the
   eye to follow. The difference here is that the offsets form an obvious
   rhythm. They rise and fall symmetrically about the middle pillar, so the row
   still scans as one gesture; it just isn't a ruled line. Keep any future
   adjustment patterned for the same reason. */
/* Gap comes in from 2rem to buy the columns back the width that the larger
   pillar copy costs. Five columns at 2rem gaps left each one ~215px, which is
   why the copy had been held a step down; at 1.2rem they are ~240px and carry
   --t-base without the four-line ragged wrap that made the row look broken. */
.pillar-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 1.2rem;
  align-items: start;
}

.pillar { margin-top: var(--lift, 0); text-align: center; }

/* Symmetric about the centre: low, high, low, high, low. */
.pillar:nth-child(1) { --lift: 0rem;   --tilt: -4deg; --patch: 1;    }
.pillar:nth-child(2) { --lift: 3.2rem; --tilt:  3deg; --patch: 0.93; }
.pillar:nth-child(3) { --lift: 0.9rem; --tilt: -2deg; --patch: 1.04; }
.pillar:nth-child(4) { --lift: 3.6rem; --tilt:  5deg; --patch: 0.91; }
.pillar:nth-child(5) { --lift: 0.4rem; --tilt: -3deg; --patch: 1;    }

/* Only the patch tilts and resizes. Rotating the whole pillar would tip the
   body copy with it, and slanted paragraphs stop being playful very fast. */
.pillar-blob {
  transform: rotate(var(--tilt, 0deg));
  width: calc(100% * var(--patch, 1));
  margin-inline: auto;
}

/* Below this the row wraps, and the stagger fights the wrap — pillars that were
   meant to sit high end up butted under the one above. Flat rows from here. */
@media (max-width: 1000px) {
  .pillars { text-align: left; }
  .pillars .eyebrow { text-align: center; margin-bottom: 2rem; }
  .pillar { margin-top: 0; }
}

/* Each icon now sits on a saturated painted blob instead of the pale circle
   baked into the artwork.

   Getting white line-art out of files that are DARK line-art on a PALE circle,
   without redrawing them: invert the image, then screen it over the blob. After
   inverting, the pale circle is near-black and screens away to nothing, while
   the dark strokes are near-white and screen to white. So the blob shows through
   everywhere except the drawing, which is exactly the mock's treatment. */
/* Lauren's own artwork, imported 2026-08-03 — the watercolour patch and the
   white line drawing are one piece, as in the mock. This replaces a generated
   patch with the drawing knocked out over it, which was a stand-in built before
   her versions existed. Imported by .claude/import-art.py.

   Left-aligned, not centred: the mock hangs the whole pillar — patch, title,
   rule and copy — off one left edge.

   The box is a fixed aspect with object-fit: contain because the five pieces
   trim to slightly different heights (307-327px at 340 wide). Left to size
   themselves, each title would land on its own baseline and the row would stop
   scanning left to right in one pass. */
.pillar-blob {
  display: block;
  max-width: 150px;
  aspect-ratio: 340 / 315;
  margin: 0 auto 0.9rem;
}

/* No filter and no blend mode: the art arrives finished. This carried
   `invert(1) contrast(2.4)` plus `mix-blend-mode: screen` to knock the old dark
   line-art off its baked pale disc, which was fragile — it depended on every
   icon's disc inverting to true black, and the per-icon
   `img[src$=...] { filter: hue-rotate() }` rules match the same element at the
   same specificity and were silently replacing the invert on some of them. */
.pillar-blob img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* The two `img[src$="receive-*.webp"] { filter: hue-rotate() }` rules that used
   to sit here are gone with the icons they corrected — the club patches are
   Lauren's own art now and arrive finished, toned at import like the pillars.
   Worth remembering why they were a hazard as well as dead: an attribute
   selector like that matches at the same specificity as `.pillar-blob img` and,
   coming later in the file, silently replaced its filter. Adjust art at import,
   not with a CSS filter keyed on a filename. */

/* Bigger than it was: in the mock these titles are the section's script voice,
   sized close to an h2, not captions under the patches. Each takes its own
   patch's colour — with the marker rules gone, that is what ties title to icon. */
.pillar h3 { margin-bottom: 0.9rem; font-weight: 600; font-size: 1.393rem; }

.pillar:nth-child(1) h3 { color: var(--blob-teal); }
.pillar:nth-child(2) h3 { color: var(--blob-purple); }
.pillar:nth-child(3) h3 { color: var(--blob-green); }
.pillar:nth-child(4) h3 { color: var(--blob-gold); }
.pillar:nth-child(5) h3 { color: var(--blob-pink); }

/* Was held at --t-sm to keep the wrap tidy; Lauren read it as small twice, so
   it joins the rest of the body copy and the grid gap above pays for it. */
.pillar p { font-size: var(--t-base); line-height: 1.7; }

/* ---------- The closing thought under the pillars, 2026-08-17 ----------
   Lauren's joy block, the home page's counterpart to the two on About. It
   closes "How We Find Our Way Back" from inside that section, so everything
   here is SPACING ONLY — no panel, no border, no card, and not one new type
   rule. The pull-quote is the site's existing `.script`, which is why there is
   no font declaration in this block at all.

   Centred to match `.pillars .eyebrow` above it, which is the only other thing
   in this section that is not a grid cell. The section itself is text-align:
   left, so the centring has to be stated. */
.pillars-close {
  text-align: center;
  /* Against the grid's own 1.2rem gap. The pillars carry `--lift` offsets of up
     to 3.6rem, so the bottom edge of that row is ragged by design and a small
     gap here would read as a collision with whichever column hangs lowest. */
  margin-top: 5.2rem;
}

/* `.script` is an inline span everywhere else it is used, so it needs to become
   a block to sit on its own line and take a measure. `margin-inline: auto`
   centres that measure; `text-align` alone would not, once max-width binds. */
.pillars-close .script {
  display: block;
  max-width: 34rem;
  margin: 0 auto 2rem;
}

/* THE SAME LINE, WHEN IT COMES LAST — 2026-08-26. The joy block was rewritten to
   END on "When we pay attention, joy becomes a compass." rather than to open on
   "Joy is a compass.", so the accent moved to the foot of the card. The rule
   above gives it a 2rem margin BELOW, which was the gap down to the paragraphs
   it used to introduce; left as-is that is 2rem of dead space under the last
   line of the section. Flipped to sit above it instead, same value, so the
   rhythm is unchanged and only its direction moves.

   Written as :last-child rather than by editing the rule above, because the same
   class is used head-first elsewhere — `.pillars-close` is a shared block. */
.pillars-close .script:last-child { margin: 2rem auto 0; }

/* Three separate paragraphs, not one with <br>s, precisely so this rule can
   exist: a line break cannot be given space, and "breathing room between them"
   is the whole request. 1.15rem apart, against the 1.7 line-height inside each
   line, so the gap between lines is clearly wider than the gap within one. */
.pillars-close p {
  max-width: 34rem;
  margin: 0 auto;
  font-size: var(--t-base);
  line-height: 1.7;
}

.pillars-close p + p { margin-top: 1.15rem; }

@media (max-width: 700px) {
  /* The grid is one column on a phone, so the row above ends flush rather than
     ragged and no longer needs to be cleared by that much. */
  .pillars-close { margin-top: 3.2rem; }

  /* THE 20rem CLAMP THAT LIVED HERE IS GONE, 2026-08-24, and this note is what
     replaces it. It existed because at 390px these lines took 16 painted pixels
     from .vine-pillars-left, a sprig anchored in `.pillars .wrap` — so the block
     was narrowed to 20rem to clear it, at the cost of an extra wrapped line.

     The block moved out of .pillars into its own photograph band, and the sprig
     did not go with it. Re-measured after the move: at 375 the vine's lowest
     paint ends within 2px of `.home-joy`'s top edge, and the card holding this
     copy starts 177px further down, so there is nothing left to clear.

     PUT IT BACK IF THIS BLOCK EVER RETURNS TO .pillars. The collision was real;
     it is only the geography that changed. */
}

/* ---------- "Joy is a compass." on a photograph, 2026-08-24 ----------
   The home page's first photograph. Its hero is the teal band, so nothing here
   had a picture in it before, which is part of why this is full-bleed rather
   than a framed panel — it should read as deliberate.

   THE CROP was chosen off a contact sheet of five candidate bands: y=2100 of
   the 4284x5712 source is the one holding the whole wingspan, the sun rays down
   the left, and the joe-pye flowers along the bottom. Re-crop the ASSET to
   reframe it; at this aspect only ~5% is cropped vertically, so
   background-position has almost no play.

   CONSTRUCTION IS .oto-do's, deliberately — same scrim weights, same frosted
   card, same torn-band padding. The two are the same object on two pages and
   should stay that way; if one changes, change both. */
.home-joy {
  position: relative;
  /* SYMMETRIC as of 2026-08-26 — the bottom used to be 1rem short. Together
     with .pillars-close's margin-top (killed further down) that put the copy
     100px lower in the band than it was high, which is what Lauren saw: "the
     joy as a compass section now needs the text centered more."

     NOTE the identical padding on `.oto-deeper` further down this file, which
     still carries the -1rem. The two rules look copy-pasted and are NOT the same
     decision any more; do not "fix" that one to match. */
  padding: calc(var(--section) + var(--wave-h) + 3.5rem) 0;
  /* `clip`, NOT `hidden`, AND THIS IS WHAT MADE THE PARALLAX WORK. Found
     2026-08-24: the drift below was measured, guarded and shipped, and it never
     ran once. `overflow: hidden` makes an element a SCROLL CONTAINER — a
     scrollport that simply cannot be scrolled — and `animation-timeline: view()`
     resolves against the subject's nearest ancestor scroll container. That was
     this section, which never scrolls, so the timeline sat at exactly 50%
     progress at every scroll position and the photograph held still.

     Nothing reported a fault. `getComputedStyle` returned the right
     animation-name and timeline, `document.getAnimations()` found the animation
     and called it running, and every contrast measurement passed. The only
     symptom was a progress that read 0.4999859 at the top of the page and
     0.4999859 at the bottom.

     `overflow: clip` clips identically and does NOT create a scroll container,
     so the timeline resolves against the document and the drift runs. The
     `hidden` above it is the fallback for browsers without `clip`; they lose the
     drift to the @supports guard anyway, so they only need the clipping. */
  overflow: hidden;
  overflow: clip;
  /* Split into two layers so the photograph can drift on its own — see
     .about-thankyou for the reasoning. The section carries no background of its
     own: an element's background paints beneath its pseudo-elements, so the
     scrim has to be ::after or the picture would bury it. */
}

/* 4%, not the 8% .about-thankyou uses, and the difference is measured rather
   than stylistic. OVERSIZING THIS LAYER RE-CROPS THE PICTURE: `cover` fits to
   this box, so a taller box takes a different slice of the photograph, and the
   scrim below was fitted to the slice the section-sized background gave. At 8%
   the static worst case fell from the documented 3.79:1 to 3.09 before the
   drift was even applied. 4% keeps the re-crop small. */
.home-joy::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: -4%;
  bottom: -4%;
  z-index: 0;
  background: url("../images/home-joy-dark.webp") center 50% / cover no-repeat;
}

/* DEEPENED FOR THE DRIFT, 2026-08-24. The shape is the same smooth bell — see
   the long note above for why a plateau and a radial both failed — but every
   stop is up about 6 points, 0.12->0.18 at the edges and 0.50->0.56 at the
   centre.

   It pays for two things at once: the re-crop described on ::before, and the
   copy passing over 34px of moving picture. Measured across the drift range,
   the original bell came back 3.05:1 against a 3.0 requirement — technically a
   pass, and far too thin a margin for the band this file already calls the
   tightest type on the site. This gives 3.62.

   Cost is 7 points of photograph, 72% surviving to 65%. */
.home-joy::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  /* TWO LAYERS, and the flat one is not decorative. `.home-joy::before` used to
     hold a flat rgba(20, 86, 94, 0.10) veil over the whole band; ::before is now
     the photograph, so the veil moved here. It is listed FIRST, which puts it on
     top of the bell — the order it painted in before, when it sat above the
     section's own background.

     This is what broke the band on the first attempt: the old veil rule appeared
     LATER in the file than the new photo rule, so it won the cascade and reset
     ::before's background to a flat colour. The picture vanished and the section
     rendered as a plain teal wash. */
  background:
    linear-gradient(rgba(20, 86, 94, 0.10), rgba(20, 86, 94, 0.10)),
    /* THE BELL'S PEAK FOLLOWS THE COPY — 56% originally, briefly 50% when the
       copy was dead-centred, and 43.5% now that it is lifted 2.75rem above
       centre. It had to move each time.
       Every VALUE here is unchanged; only the positions moved. This gradient is
       not decoration — it is a bell fitted to where the copy sits, and this band
       runs the tightest type on the site (measured 3.43-3.62 against a 3.0 bar).
       Centring the copy and leaving the peak at 56% would have slid the words
       off the darkest part of their own scrim and spent that margin.

       The flanks are RESCALED, not shifted, so the curve keeps its shape: the
       rise compressed by 50/56, the fall stretched by 50/44. */
    linear-gradient(180deg,
      rgba(14, 52, 60, 0.18) 0%,
      rgba(14, 52, 60, 0.24) 14.0%,
      rgba(14, 52, 60, 0.40) 26.4%,
      rgba(14, 52, 60, 0.56) 43.5%,
      rgba(14, 52, 60, 0.40) 64.0%,
      rgba(14, 52, 60, 0.24) 84.6%,
      rgba(14, 52, 60, 0.18) 100%);
}

/* Small-drift parallax, same construction and the same four guards as
   .about-thankyou. This band is the tighter of the two — its copy sits straight
   on the photograph with no card, documented at 3.79:1 static — so the drift was
   re-measured over its range rather than carried across. */
/* ---------- THE FULL EFFECT ON THIS BAND TOO, 2026-08-24 ----------
   Lauren: "i want it to be like its in the background and you scroll and moves
   over the pic". That is `background-attachment: fixed`, the version this file
   removed earlier the same day and told itself not to re-try. The note was right
   that the old scrim failed under it and wrong that the effect had to go: the
   answer is more scrim, and here is what it costs.

   THE PICTURE IS RE-CUT FOR IT. Under `fixed` the background is sized to the
   VIEWPORT, not to the band, so a 2:1 file gets cropped hard by a 1.42:1 window.
   images/home-joy-dark-wide.webp is 2400x1688 — the same photograph at the same
   centre, cut to the shape of a browser window, so nothing is enlarged.

     IMG_8020.HEIC  ->  crop (0, 1343, 3024, 3470)
                    ->  resize 2400x1688
                    ->  WEBP quality 76            253KB

   The source arrived on 2026-08-24, from Lauren, after a search of the repo came
   up empty — `images-original/home-joy-bfly-src.JPG` is the YELLOW swallowtail
   that was the first attempt at this band, not this one. The shipped 2400x1200
   file turned out to be a plain crop of IMG_8020 at rows 1650-3162 with NO
   darkening and NO blur (fitted brightness 0.9988), which is why this cut has
   none either.

   THE SCRIM IS 40% DEEPER, and this band pays far more than About did. Its copy
   sits directly on the butterfly with no card — Lauren's call, "i think i just
   want the text right on the butterfly" — so every line is reversed out onto
   whatever part of the picture happens to be behind it, and under `fixed` that
   is eventually ALL of it. Measured over the whole pass, worst pixel under the
   six line rectangles:

     scrim as it was    2.58:1   FAILS      59% of the photograph
     x1.3               3.38:1              50%
     x1.4               3.72:1   <- here    46%
     x1.5               4.10:1              43%

   Per line at x1.4: accent 4.13, then 5.63, 6.30, 5.38, 4.21, and 3.72 on the
   last short line, which is the one that sets the value. Bar is 3.0 throughout
   — 19px at weight 700 clears WCAG large text, and the accent is 29.8px.

   46% AGAINST 59% IS A REAL COST and it is the honest price of this effect on
   this band. If it reads too dark, the lever is not a shallower scrim — it is a
   frosted card behind the copy, which measures ~5.2 whatever is behind it and
   would let the butterfly come back up. That was ruled out once already.

   A POINTER, NOT A WIDTH — 2026-08-25, and this is the gate every pinned band
   uses. `background-attachment: fixed` is ignored or badly janky on iOS Safari
   and Android Chrome, so it has to be kept away from touch devices. That was
   originally written as `min-width: 1101px`, borrowing the burger breakpoint,
   which is a proxy and not the thing itself: a Mac window narrowed to 900 is not
   a phone, but the rule could not tell, and every band went flat.

   `(hover: hover) and (pointer: fine)` asks the actual question. A narrowed
   desktop window keeps the effect; a phone or tablet never matches it whatever
   its width. 761 stays as the lower bound because BELOW it the bands switch to
   their phone crops and to `.pin-photo`, which is a different treatment rather
   than an absence of one.

   DO NOT SIMPLY LOWER 1101 TO 761 WITHOUT THE POINTER TERMS. An iPad at 900
   would then take the deepened scrim — fitted for a picture the copy travels
   across — while `fixed` stayed ignored and the picture did not travel at all.
   That is a darker photograph bought for nothing. */
@media (min-width: 761px) and (hover: hover) and (pointer: fine) {
  /* A FIXED LAYER, NOT A FIXED BACKGROUND — 2026-08-26. Lauren: "on desktop, the
     paralax or whatever its called, across the site, is a little shaky. its fine
     on mobile though." Mobile is fine because none of this runs there; the
     pointer query keeps it off touch devices entirely.

     `background-attachment: fixed` is the shaky one, and it is shaky by
     construction rather than by tuning. It opts the element out of composited
     scrolling: the browser has to REPAINT the background on the main thread
     every frame, so the picture lands a frame or two behind the content moving
     over it. On a trackpad's inertial scroll, and worse on a high-refresh
     display, that reads as a shimmer.

     `position: fixed` on the same pseudo-element gets the identical geometry —
     `fixed` sizes a background to the viewport, which is exactly what inset:0 on
     a viewport-anchored box gives — but the compositor handles it: the layer
     simply is not moved, and nothing repaints.

     `clip-path` is what keeps it inside the band. `overflow: clip` above does
     not: a fixed-position descendant escapes overflow clipping, but clip-path
     applies to the whole subtree. It also must NOT be a transform or a filter —
     those would make this section a containing block and the "fixed" layer would
     go back to scrolling with the page.

     The scrim on ::after is untouched and still band-sized. That is the half
     that must not move: it is a bell fitted to where the copy sits, and pinning
     it to the viewport would slide the darkening off the words. */
  .home-joy { clip-path: inset(0); }

  .home-joy::before {
    position: fixed;
    inset: 0;
    background: url("../images/home-joy-dark-wide.webp") center 50% / cover no-repeat;
  }

  /* LIGHTENED 2026-08-25 — Lauren, on the first `fixed` version: "home could be a
     little lighter". It was a uniform x1.4 of the old bell, which took the
     photograph to 46%.

     THE SHAPE CHANGED RATHER THAN THE DEPTH, and that is what bought it back.
     The copy occupies roughly 39-74% of the band, so the middle of the bell has
     to stay deep; the flanks do not, and they are exactly where the butterfly's
     wings are. Lifting the flanks and easing the peak slightly gives 53% of the
     photograph against 46 — better than simply scaling the whole curve down,
     which reached 50% at the same contrast.

       shape                  worst    photo surviving
       x1.4, as shipped       3.72     46%
       x1.3, whole curve      3.38     50%
       flanks lifted          3.69     50%
       flanks + easier peak   3.43     53%   <- here
       lighter still          3.16     55%   too thin a margin on 3.0

     Per line: accent 3.45, then 4.87, 5.66, 4.88, 3.88, and 3.43 on the last
     short line, which sets the value as it has throughout. Bar is 3.0.

     The stops stay a smooth bell rather than a plateau — see the long note on
     the mobile curve for why an edge in this gradient is visible against the
     wings. */
  .home-joy::after {
    background:
      linear-gradient(rgba(20, 86, 94, 0.10), rgba(20, 86, 94, 0.10)),
      /* Same 56 -> 50 re-aim as the desktop curve above, same reason, same
         rescale. Values untouched — this curve was chosen from six candidates
         (the table above) and none of that is being re-litigated. */
      linear-gradient(180deg,
        rgba(14, 52, 60, 0.14) 0%,
        rgba(14, 52, 60, 0.23) 14.0%,
        rgba(14, 52, 60, 0.48) 26.4%,
        rgba(14, 52, 60, 0.74) 43.5%,
        rgba(14, 52, 60, 0.53) 64.0%,
        rgba(14, 52, 60, 0.27) 84.6%,
        rgba(14, 52, 60, 0.15) 100%);
  }
}

/* NO PARALLAX ON THIS BAND, and it was tried on 2026-08-24 rather than ruled
   out on principle. `background-attachment: fixed` pins the photograph to the
   viewport so the section scrolls over it — the effect Lauren asked for — but it
   also slides the picture UNDER the copy as the page moves, and this band's copy
   sits directly on the photograph with no card.

   Measured across the whole scroll range rather than at one position, worst-case
   contrast fell from the documented 3.79:1 to 2.21:1, against the 3.0 that 19px
   bold needs. The scrim cannot fix that cheaply: its bell is fitted to where the
   words are, and with the image moving the words pass over every part of it, so
   the only scrim that survives is a heavy flat one — which is what the note above
   already records as the option that threw away the photograph.

   If it is ever wanted here, the honest route is a SMALL drift (a scroll-driven
   transform of tens of pixels, not a viewport pin) so the copy stays over the
   pixels the scrim was measured against. */

.home-joy .wrap { position: relative; z-index: 2; }   /* above ::before (0) and the scrim (1) */

/* NO CARD — the copy sits directly on the butterfly, 2026-08-24. Lauren: "i
   think i just want the text right on the butterfly", then "make it white and
   bolder".

   THIS ELEMENT IS NOW ONLY A MEASURE. It has no background at all — width and
   padding, nothing else. Everything that darkens the ground lives in the
   section's own gradient.

   A RADIAL VEIL WAS TRIED HERE FIRST AND LAUREN CALLED IT: "i dont want the box
   behind it". She was right, and the reason is worth keeping. An ellipse sized
   to the copy has a visible boundary on all four sides no matter how soft the
   falloff — it is a shape, and the eye finds it. What replaced it is a
   FULL-WIDTH horizontal band in the section gradient: darker through the middle
   where the words are, fading to the edges top and bottom, and with no left or
   right edge whatsoever because it spans the section. There is nothing there to
   read as a box.

   It also measured better on both counts — 4.65:1 worst case against the
   radial's 3.79, while keeping 63% of the photograph's brightness against 68%.
   Nearly the same picture, a full contrast step better, and no shape.

   WHY BOLD IS DOING REAL WORK, not just styling. WCAG counts text as "large" at
   24px, OR at 18.66px when it is bold — and large text needs 3.0 contrast
   instead of 4.5. The body copy here is 19px, so bolding it moves the bar it
   has to clear rather than only making it easier to read. Measured on the
   composite: 3.79:1 worst case, which fails the 4.5 that regular 19px would
   have needed and clears the 3.0 that bold 19px actually needs. Un-bolding this
   copy silently puts it back under the standard.

   THE NUMBERS THIS LANDED ON, for anyone retuning it: the band runs 0.14 at the
   edges and 0.55 across 34%-66%, which is where the copy sits. A FLAT scrim
   heavy enough to do the same job left only 42% of the photograph and still did
   not pass. Darkening only the rows the words occupy is what bought that back —
   if the copy ever grows or shrinks, those two stops have to follow it.

   IT IS STILL THE TIGHTEST TYPE ON THE SITE. If this photo is ever swapped,
   re-measure before assuming the veil is enough — the failure mode here was
   never the dark wings, it was the pale flower behind the body and the cream
   markings on the lower wings, both of which sit dead centre under the copy. */
.home-joy-card {
  width: min(34rem, 100%);
  margin-inline: auto;
  padding: clamp(1.9rem, 4vw, 2.8rem) clamp(1.6rem, 3.2vw, 2.4rem);
}

/* Reversed out for the photograph. 700 on the paragraphs is load-bearing — see
   the note above — and the script line is already a display size, so it needs
   no weight change to qualify. */
/* HOW THIS ENDED UP A SMOOTH BELL, through three rejected versions — the shape
   matters more than the number, which is the whole lesson here.

     1. A radial veil sized to the copy. Lauren: "i dont want the box behind
        it". An ellipse has a boundary on all four sides however soft the
        falloff; the eye finds it.
     2. A full-width band, 0.66 with a flat plateau. No left or right edge, but
        the plateau gave it two horizontal ones. Lauren: "why is there a dark
        veil still? i dont want that".
     3. Nothing at all, text-shadow only. Honest, and too hard to read.

   What is here now: "you can add something very minor behind it again but i
   dont want it looking like a box or taking away from the photo." So it is a
   gradient with NO PLATEAU AND NO EDGE — 0.12 at top and bottom rising smoothly
   to 0.50 at 56%, which is where the copy's centre sits. Every stop is on a
   curve, so there is no line anywhere for the eye to catch, and it reads as the
   light falling off rather than as a layer laid over the picture.

   IT IS ALSO LIGHTER THAN THE BAND IT REPLACED, not just softer: 68% of the
   photograph survives against ~60%, because a bell spends its darkness only at
   the centre where a plateau spends it everywhere.

   THE TEXT-SHADOW STAYS and is doing real work alongside it — two shadows, a
   tight dark one for edge definition against pale detail and a wide soft one to
   lift the line off busy ground. Same idiom as `.oto-hero .script`. It helps a
   person read this but does NOT count toward WCAG contrast, which is measured
   against the background behind the glyph.

   WHERE THE NUMBERS LAND: 3.09:1 worst case, which clears the 3.0 the bold 19px
   paragraphs need. "Joy is a compass." is 22.7px and Courgette has one weight,
   so it cannot be bolded into that allowance and formally wants 4.5 — it is the
   one line still short, and deepening the bell far enough to fix it is exactly
   what Lauren has now rejected three times. Left as her call, deliberately. */
/* NO TOP MARGIN IN THIS BAND. `.pillars-close` carries `margin-top: 5.2rem` to
   clear the pillar row's ragged `--lift` offsets — and that row has been in a
   different section entirely since this block moved onto a photograph on
   2026-08-24. Inherited here it was 83px of one-sided offset with nothing above
   it to clear.

   THEN LIFTED 2.75rem ABOVE TRUE CENTRE. Dead-centring it was the first fix and
   Lauren still read it as wrong: "i think the text should still be moved up
   further in that section? it looks wierd." She is right, and the reason is the
   PHOTOGRAPH rather than the geometry — the butterfly's wings fill the upper
   half of the crop and the lower half is dark wing and shadow, so the band's
   optical centre sits above its measured one. Type centred to the box reads low
   against a subject that is not.

   -2.75rem TOP AND +2.75rem BOTTOM, so the band's height does not move — only
   the copy inside it. That matters: this section's height is what the two
   scrim curves and the photo crop are all proportioned against.

   THE 2.75rem AND THE BELLS' 43.5% ARE ONE NUMBER EXPRESSED TWICE. 44px on a
   664px band (desktop) and a 658px one (narrow) both land the copy's centre at
   ~43.4%, which is why a single rem value works for both. Move one and the other
   must move with it — see the note on .home-joy::after. */
.home-joy .pillars-close { margin-top: -2.75rem; margin-bottom: 2.75rem; }

.home-joy .pillars-close .script {
  /* RAISING THE FLOOR PAST 24px IS AN ACCESSIBILITY FIX, not a style choice, and
     it is the reason this line finally passes without darkening the photograph
     any further. Lauren: "we could also increase size if that helps with text".

     WCAG counts 24px as large text, and large text needs 3.0 contrast instead of
     4.5. `.script`'s clamp bottoms out at 1.417rem — 22.67px — so on narrow
     screens this heading sat just under the line and owed the full 4.5, which it
     could not reach. Courgette ships one weight, so bolding it into the
     allowance was not available the way it was for the 19px paragraphs.

     1.55rem is 24.8px, clearing 24 with a little room for rounding. Only the
     MINIMUM moves; the vw term and the 1.863rem cap are untouched, so nothing
     changes at desktop where this was already 29.8px and already passing.

     DO NOT LOWER THIS BELOW 1.5rem. It silently puts the line back under the
     threshold at exactly the widths where the photograph is busiest. */
  --accent-base: clamp(1.55rem, 2.592vw, 1.863rem);
  color: var(--cream);
  text-shadow:
    0 1px 3px rgba(6, 26, 32, 0.85),
    0 2px 16px rgba(6, 26, 32, 0.65);
}

.home-joy .pillars-close p {
  color: #FFF;
  font-weight: 700;
  text-shadow:
    0 1px 3px rgba(6, 26, 32, 0.85),
    0 2px 14px rgba(6, 26, 32, 0.6);
}

/* The narrow crop, same job as oto-do-flowers-tall.webp. */
/* THE BAND HAS TO BE RE-CUT FOR NARROW, not just inherited. Its stops are a
   PERCENTAGE OF THE SECTION, and the copy occupies a different slice of the
   section once it wraps to more lines: measured, it runs 31-78% at 360 against
   34-66% at desktop. Left on the desktop stops the darkening simply missed the
   words — every line failed, worst 1.5:1.

   THE NARROW CURVE IS BROADER THAN THE DESKTOP ONE, not just shifted, and that
   is the point. The copy occupies 31-78% of the section here against 30-56% at
   desktop, because it wraps to more lines in a shorter measure — so a bell
   tuned for desktop leaves this copy's top and bottom sitting on its shallow
   flanks. Measured that way it failed on 13 lines across the narrow widths,
   worst 2.35. Widened to peak across 40-72%, it clears everything.

   It costs more of the photograph than the desktop curve does — about 52%
   against 68% — and that is unavoidable: more of the frame has words over it
   here. If the copy ever changes length, re-measure these stops.

   0.66 RATHER THAN 0.58 BECAUSE OF ONE LINE. "Joy is a compass." is 22.7px here
   and Courgette ships a single weight, so it cannot be bolded into WCAG's
   large-text allowance the way the 19px paragraphs were — it is under 24px, so
   it needs the full 4.5. At 0.58 it measured 4.11 and missed. That one line
   sets the depth of this band; the bold paragraphs around it had already
   cleared. */
/* ON THE PSEUDO-ELEMENTS, NOT ON THE SECTION, AND THAT IS A FIX rather than a
   preference. This rule used to set `background` on `.home-joy` itself, which
   was right when the section carried its own picture. It stopped being right
   the moment the desktop photograph moved to ::before for the parallax: an
   element's background paints BENEATH its pseudo-elements, so from that point
   on the desktop crop and the desktop bell painted straight over this pair and
   a phone got neither. Verified at 390 before the fix — the section computed
   the tall asset, and what actually rendered was home-joy-dark.webp.

   Nothing failed loudly. `getComputedStyle(section).backgroundImage` returned
   the tall file, this media query matched, and the only symptom was that the
   picture on a phone was the wide crop with its butterfly cut in half.

   TOP AND BOTTOM GO BACK TO 0. The drift is desktop-only (min-width: 1101px),
   so a phone needs no slack — and it must not have any, because the stops below
   were fitted to `cover` in the exact section box. The 4% oversize would take a
   different slice and the measurements would not hold. */
@media (max-width: 760px) {
  /* RE-CUT 2026-08-24 from the original Lauren supplied, replacing a 1100x957
     crop that clipped both wingtips. Same filename, new picture:

       IMG_8020.HEIC  ->  crop (0, 760, 3024, 4032)     3024x3272, whole wingspan
                      ->  resize 1400x1515
                      ->  WEBP quality 78               160KB

     No darkening and no blur, matching the file it replaces. Lauren: "i also want
     the mobile view to be zoomed out so more of the pic is visible" — 57% of its
     width survives `cover` in a 390x742 band against 46% before, and both
     wingtips are now inside the frame. The bell below was re-measured against it:
     3.68:1 at the x1.2 depth already set, against a 3.0 bar. */
  .home-joy::before {
    top: 0;
    bottom: 0;
    background-image: url("../images/home-joy-dark-tall.webp");
  }

  /* The bell only — no flat teal veil. The veil is a desktop layer that came
     across when ::before stopped being the veil and became the photograph; it
     was never part of what this curve was measured against.

     DEEPENED 20% ACROSS THE INTERIOR, 2026-08-24, and re-measured rather than
     carried over. The old curve was fitted while this band still painted its
     own background, and against the tall asset in this box it no longer holds:
     at 390 the accent line came back 2.94 and the last paragraph line 2.77,
     both under the 3.0 they need. Every interior stop is up by a factor of 1.2
     — the shape is unchanged, only its depth.

     Worst pixel under the eight line rectangles, all widths measured on the
     real composite (tall asset at `cover` in the section box, this gradient
     over it):

       320   3.63:1      390   3.51:1      760   4.17:1
       360   3.67:1      430   3.51:1

     THE BAR IS 3.0, NOT THE 4.5 THE OLD NOTE ABOVE CLAIMS. Re-checked at every
     width above: "Joy is a compass." renders at 24.8px here, which clears
     WCAG's 24px large-text threshold on its own and does not need to be bold.
     It clears by 0.8px, so if this line's size is ever nudged down the bar
     jumps to 4.5 and this curve has to be re-measured.

     Cost is 53% of the photograph surviving, against 61% on the old curve —
     close to the ~52% the desktop note already budgeted for this band. */
  .home-joy::after {
    background:
      linear-gradient(180deg,
        rgba(14, 52, 60, 0.12) 0%,
        rgba(14, 52, 60, 0.24) 10%,
        rgba(14, 52, 60, 0.48) 24%,
        rgba(14, 52, 60, 0.62) 40%,
        rgba(14, 52, 60, 0.67) 56%,
        rgba(14, 52, 60, 0.62) 72%,
        rgba(14, 52, 60, 0.41) 85%,
        rgba(14, 52, 60, 0.22) 94%,
        rgba(14, 52, 60, 0.12) 100%);
  }
}

/* ---------- Believe / For ---------- */

/* Three solid colour panels butted edge to edge, full-bleed, as in the mock —
   sage, pale blue, lavender. This replaces a two-column wash band plus a
   separate teal club card further down; the club is the third panel now. */
.believe-for {
  display: grid;
  grid-template-columns: 1fr 1.04fr;
  /* start, not stretch: the panels are three separate washes laid down at
     different heights now, not one band ruled into three cells. */
  align-items: start;
  padding: 2rem 0 3.5rem;
}

/* Same baked paper as the hero: the mock's panels are visibly washes on a sheet,
   not flat fills. The colour stays in background-color underneath and the PNG
   carries only lightness, so the same file serves all three. It lands softer
   here than on the hero without any tuning — soft-light's effect falls off as
   the base colour approaches white, and these panels are pale. */
.believe,
.who-for,
.believe-for .club-copy {
  background-image: url("../images/art/paper-wash.png");
  background-size: cover;
  background-position: center;
  background-blend-mode: soft-light;
}

/* Floating and overlapping rather than butted edge to edge, which is what made
   the band read as rigid: three rectangles ruled into one strip.

   Each panel now carries its own torn top and bottom (the classes moved from the
   container to the panels in the markup), sits at its own height, and laps over
   its neighbour. Because the wave tile repeats at a fixed width, each panel cuts
   a different part of it, so no two edges match — which is the point.

   z-index descends left to right so the overlaps stack consistently; without it
   the later panels would always sit on top and the lapping would read one-way. */
/* ---------- Sage panel's colour-changing sprig ----------
   Same two-copy technique as the hero's: one drawing, two positions that
   coincide, each showing on its own side of the panel's torn base. White up on
   the sage, teal once it drops into the paper gap below.

   .believe is .torn-paper, so it crops the white half along its own tear for
   free. The teal half needs the wrapper below, because nothing else clips it.

   The wrapper's `top` is a measured offset from the section's top, like every
   other placement in this system — it tracks the panel's height, so re-derive it
   if the Believe list gains or loses a line. It starts a little ABOVE the
   panel's base so the two halves overlap rather than risking a gap in the stem
   where the tear rises. */
.believe-for { position: relative; }


/* White dotted flight crossing the top of the Believe and Who-For panels.
   Lauren: "so they cross on what i believe section and who lumi libra is for",
   "in the top part of the sections".

   ONE element, not the two-copy crossover the vines use. That technique exists
   to change a drawing's colour at a torn edge, and to survive it the two halves
   have to resolve against boxes sharing left/width/bottom — the hard part, and
   the thing that has silently split three times. None of it applies here: the
   art is white and both panels are coloured, so the same white reads across the
   join, and a single element cannot drift from itself.

   z-index 4 puts it above both panels (.believe is 2, .who-for 1). Without it a
   .deco's z-index 0 paints behind them and the piece is invisible.

   It needs no clip. White on white paper is nothing, so the drawing crops itself
   to the panels for free — but that also means a route that wanders off colour
   breaks the trail. Keep it inside the panels' union: continuous across the full
   width only between y 2259 and 2897 at 1280 (above that only the teal panel
   exists, below it only the blue).

   Compact and seated on the seam, not sweeping the full width. There is no clear
   horizontal band across the tops of both panels — the Believe heading sits at
   y 2257 and the Who-For heading at 2358, and the panels are 71px out of step —
   so a wide flight cuts through one list or the other. What there IS is a clear
   corridor at the join: the Believe text stops at x 571, the Who-For text starts
   at 671, and that gap runs the whole height of the band. The drawing's natural
   fall to the right takes it down that corridor, so it needs no rotation. */
.believe-cross-flight {
  top: 45px;
  left: 33%;
  width: min(360px, 29%);
  z-index: 4;
  opacity: 0.85;
}

/* The phone version of the same idea, bridging the seam where the two panels
   stack instead of the corridor where they sit side by side. Shown only below
   700px — above that the panels are side by side and there is no seam to cross,
   and .believe-cross-flight already has that job. */
.believe-seam-flight { display: none; }

/* Its anchor. `display: none` here is load-bearing, not tidiness: above 700px
   .believe-for is a two-column grid, and an empty-but-displayed div would take a
   cell and push .who-for out of the row. */
.believe-seam-anchor { display: none; }


.vine-believe-clip {
  position: absolute;
  left: 0;
  right: 0;
  /* Named so the teal half can derive its own offset from it instead of
     repeating the number — see --believe-cross-y at the two halves below. */
  --believe-clip-top: 595px;
  top: var(--believe-clip-top);
  /* 380px until 2026-08-04. The teal half moved down 124px when the type pass
     grew the panel, and at the old height the wrapper sheared ~90px off the
     bottom of the sprig. Must stay >= the teal half's `top` + its rendered
     height (22 + 491 = 513). */
  height: 510px;
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
}

.vine-believe-cross-white,
.vine-believe-cross-teal {
  width: 280px;
  opacity: 0.55;
  /* Mirrored on the vertical axis, so the arc curves the opposite way from the
     original placement while the stem stays up on the sage and the leaves fall
     into the white. Identical on both halves — they only read as one drawing
     while the transform matches. */
  transform: scaleX(-1) rotate(150deg);
}

/* The teal half's offsets are derived from where the white one renders,
   expressed against the clip wrapper — re-derive the pair together, never one
   alone. The two must land at the SAME absolute position; the panel (z-index 2)
   paints over the clip (z-index 0), so it hides the teal above the tear by
   itself and the join happens exactly on the torn edge.

   Re-derived 2026-08-04: the panel grew with the larger type and the halves had
   drifted 123.9px apart, which broke the stem across the tear. `top` went
   -102px -> 22px. Check with: both halves' getBoundingClientRect must agree to
   under a pixel in x AND y.

   The two halves resolve `left` against DIFFERENT boxes — white against the
   .believe panel, teal against the full-width clip — so they can only agree if
   the teal's percentage is scaled by the panel's share of the row. That share is
   fixed by the grid: `1fr 1.04fr` makes column one 1/2.04 = 49.02% at every
   width (measured identical at 1100, 1280, 1440 and 1600). So the teal's left is
   40% x 49.02% = 19.608%, which lands on the same page column as the white's
   40% no matter how wide the window gets. It was 251px — correct at 1280 and
   nowhere else; the pair was 31px apart at 1440 and 63px at 1600.

   If the grid ratio ever changes, recompute: teal-left = white-left x
   (column-1 fraction). */
/* Re-derived AGAIN on 2026-08-12, and this is the third time this pair has
   split — 22px -> -80.9px, the teal half up 102.9px to land back on the white
   one. Found by sweeping the page at 320/390/430/699/760/900/1100/1280/1440/1600
   and comparing both halves' boxes: dy was a constant 102.9 at every width from
   1280 up, and 0 is the only value that means anything here.

   IT IS NOT A WIDTH BUG, which is why the 2026-08-04 percentage fix did not
   prevent it. The geometry is identical at 1280, 1440 and 1600 (the wrap is
   capped, so the panel measures 608px tall at all three). What moved was the
   panel's HEIGHT, from the copy edits — and the two halves measure from
   different things:

     - the white half hangs off `.believe`'s BOTTOM (`bottom: -280px`), so it
       follows the panel and stays on the tear;
     - the teal half sits at a fixed `top` inside `.vine-believe-clip`, which is
       `top: 595px` from `.believe-for` — a number that knows nothing about the
       panel's height.

   So every copy or type change to that panel splits them by exactly the amount
   the panel grew or shrank. The durable fix is structural: the clip has to hang
   off the panel's bottom edge like the white half does, which needs a wrapper
   element around `.believe` + the clip (the same "same box, one rule" move that
   made `.vine-club-seam` resize-proof). Not done here; flagged to Lauren.

   So the anchor changed rather than the number. BOTH HALVES NOW MEASURE DOWN
   FROM `.believe-for`'s TOP, which is the one line in this section that does not
   move: the container's `padding-top` is a flat 32px and the clip's own top is a
   flat 595px at every width from 1101 to 1920 (measured). The panel's HEIGHT is
   the only thing that varies — 710px at 1101, 676 at 1150, 608 from 1280 up —
   and neither half depends on it any more.

   `--believe-cross-y` is where the pair sits, 514px below the container's top,
   and each half subtracts whatever its own box starts at. Change that ONE number
   to move the pair; the halves cannot come apart, because there is only one
   value.

   WHAT THIS TRADES AWAY, and it is worth knowing: the white half used to hang
   off the panel's bottom, so it held a fixed distance below the tear. Now the
   tear moves against a sprig that stays put, so how much of the drawing is white
   varies with the panel's height — 126px of it above the tear at 1280, 228px at
   1101. The drawing itself is never broken, which is the failure that actually
   shows; the colour just changes higher up the stem on a narrower window.

   The exact fix is structural — a wrapper around `.believe` + the clip so the
   clip can hang off the panel's bottom edge, the "same box, one rule" move that
   made `.vine-club-seam` resize-proof. It needs the `.believe-for > *` position
   and padding rules re-pointed at the panels first, which is the pair of rules
   that has broken this section twice. Flagged to Lauren, not done here.

   Verify with: both halves' getBoundingClientRect agreeing to under a pixel in x
   and y, with equal width, transform and opacity, at 1101 / 1150 / 1280 / 1440 /
   1600 / 1920. */
.believe-for { --believe-cross-y: 514px; --believe-panel-inset: 32px; }
.vine-believe-cross-white {
  left: 40%;
  top: calc(var(--believe-cross-y) - var(--believe-panel-inset));
  bottom: auto;
}
.vine-believe-cross-teal {
  left: 19.608%;
  top: calc(var(--believe-cross-y) - var(--believe-clip-top));
}

@media (max-width: 1100px) {
  .vine-believe-clip { display: none; }
  .vine-believe-cross-white { display: none; }
}

.believe { margin-top: 0;      z-index: 2; }
.who-for { margin-top: 4.5rem; margin-left: -3%; z-index: 1; }

/* Excludes decoration for the same reason .pillars .wrap does: this outranks
   `position: absolute`, and .believe-for is a grid — anything caught by it
   becomes a grid item. The clip wrapper below took column 1 and pushed both
   panels across before this was narrowed. */
.believe-for > :not(.deco):not(.vine-believe-clip) { position: relative; }

/* The lapping only works while the panels sit side by side. Stacked, a negative
   inline margin just pulls each one off the left edge of the page.

   They still need a real gap between them, though. Butted at margin-top:0, each
   panel's torn base met the next one's torn top with no paper showing between,
   so the two tears interlocked and the boundary read as a hard colour change —
   the torn edges looked like they had been taken away. The gap is what makes
   them visible.

   Wider inline padding for the same reason: the side tear is ~14px at this
   width, and the standard padding left only 8px of clearance to the text. */
@media (max-width: 900px) {
  .who-for { margin-left: 0; margin-top: 3rem; }
}

.believe   { background-color: var(--panel-teal); }
.who-for   { background-color: var(--panel-blue); }
.believe-for .club-copy { background-color: var(--panel-lav); }



/* Extra top padding over the nominal --space-xl: the torn top edge eats up to
   ~42px into the band at its deepest, and at 3.5rem the panel headings cleared
   it by only 9px. */
/* .believe-seam-anchor is excluded for the same reason .vine-believe-clip is —
   it is scaffolding, not a panel. It is a zero-height marker on the seam, and
   this rule's 72px/88px of vertical padding turned it into a 160px spacer that
   shoved .who-for down the page. Anything else added to this section that is
   not a panel needs the same exemption. */
.believe-for > :not(.deco):not(.vine-believe-clip):not(.believe-seam-anchor) {
  position: relative;
  padding: calc(var(--space-xl) + 1rem) clamp(1.4rem, 2.4vw, 2.6rem) calc(var(--space-xl) + 2rem);
}

/* Full-width panels take a ~14px side tear, and the clamp bottoms out at 1.4rem
   here — only 8px of clearance to the text. Declared after the rule above rather
   than with the other mobile overrides: same specificity, and a media query adds
   none, so source order is what decides. */
@media (max-width: 900px) {
  /* Excludes decoration, like the rule above it. `> *` caught the .deco images
     too: with border-box sizing, 2.2rem of inline padding on an absolutely
     positioned img eats 70px of its declared width and the auto height shrinks
     to match, so .believe-seam-flight rendered at 230x142 inside its 300px box
     instead of 300x185 — squashed and offset, not just smaller. The same was
     happening to .believe-cross-flight and .who-corner-bfly between 700 and
     900px, where those two are still shown. */
  .believe-for > *:not(.deco):not(.vine-believe-clip):not(.believe-seam-anchor) { padding-inline: 2.2rem; }
}

/* All three panels sit on colour now, so the type goes navy throughout and the
   old per-panel treatments (washes, the teal card's reversed colours) come off. */
.believe-for h2,
.believe-for .club-copy h2 { color: var(--navy); }
.believe-for .club-copy p,
.believe-for .club-features div { color: var(--ink); }
.believe-for .eyebrow { color: var(--teal-label); }
.believe-for .club-copy h2 .heart { color: var(--purple); }
.believe-for .club-features .mark { color: var(--purple); }

/* The club was a floating teal card; as a panel it must butt flush against its
   neighbours, so the card's rounding, shadow and gradient all come off. */
.believe-for .club-copy {
  order: 0;
  border-radius: 0;
  box-shadow: none;
  text-align: left;
}

.believe-for .flight-club { display: none; }

.believe-for .club-copy .btn-primary {
  background: rgba(255, 255, 255, 0.72);
  color: var(--navy);
  border-color: transparent;
  border-radius: 999px;
}
/* Was `#FFF`, which LIGHTENED a button whose rest state is already 72% white.
   Dropping the alpha instead lets more of the panel wash through, which is what
   darkening means for a translucent fill — and it stays panel-agnostic, so this
   still behaves if the wash underneath is ever retoned. */
.believe-for .club-copy .btn-primary:hover { background: rgba(255, 255, 255, 0.5); }

@media (max-width: 900px) {
  .believe-for { grid-template-columns: 1fr; }
}


/* These are the ONLY title each panel gets — there is no display heading above
   them — so they carry the same weight as "What You'll Find Here" rather than
   the site's quieter eyebrow. Tracking comes in from 0.26em: at 700 the wider
   setting went gappy and the words stopped holding together as a phrase. */
/* Navy, not teal, on the coloured panels — Lauren, 2026-08-04. Teal on sage and
   on butterfly blue measured 4.6:1; the navy is 9.0:1 on both and 8.2:1 on the
   lavender. It is #212E39, a dark navy-slate with a genuine blue cast, not
   black — black measures 13.7:1 here and is harder than anything else on the
   page. */
.believe h2, .who-for h2 {
  font-size: 1.166rem;
  font-family: var(--font-body);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--navy);
  font-weight: 700;
  margin-bottom: var(--space-md);
}

.believe ul, .who-for ul { list-style: none; }

/* ---------- The heart bullets ---------- 2026-08-26
   FILLED, AND COLOURED BY THE GROUND THEY SIT ON. Lauren: "i want to match the
   hearts that are on the 1:1 page with the rest of the site. i like them filled
   in better. so just alternate coloring. maybe on home page in the teal, we do
   lavender, and who lumi libra is for is a light teal."

   The 1:1 page has run filled hearts (\2665) on a `--heart` custom property since
   2026-08-23, set per section so each list is one value to change. That page is
   now the site's rule rather than an exception, and its two panel colours are
   exactly the two she named:

     ground                       heart              where
     --panel-teal  #BBDFDE   ->   --blob-purple      .believe, .feeling-card
     panel blue    #86C6EA   ->   --aqua-mist        .who-for, .beyond-card
     bare paper                ->   --blob-teal       (the default below)
     the deep teal card        ->   --lavender        (existing .club-copy rule)

   THE BLUE PANEL'S HEART WENT LIGHT, 2026-08-26. It was --blob-teal for a few
   hours and Lauren: "i dont like that dark teal on the blue, coud we do a really
   light shade almost mint?" --aqua-mist #DDF4F4 is the palest aqua the palette
   owns and the closest thing in it to a mint; --seafoam #D6F0F0 is its neighbour
   and reads barely different at this size.

   It is LIGHTER than the panel rather than darker, which is a different way of
   being seen and worth naming: 1.6:1 against the ground, where the dark teal was
   2.2:1 and the grey-blue before it 1.7:1. A pale mark on a mid-blue panel reads
   the way a highlight does — it is legible because it is the only light thing in
   the list, not because it is dark. If it ever needs more, the step is --seafoam
   then white, not back toward the teals.

   So the colour is picked by what the list sits ON, not by which page it is on —
   which is what makes it alternate down a page by itself, since the panels
   alternate. Both pairings are lifted from `.oto-panel-teal` / `.oto-panel-blue`,
   so the hearts on four pages are now literally the same two decisions.

   The watercolour-PATCH tints (#B5A5D1, #7AB8B7) are the ones that read as
   "lavender" and "light teal" in the abstract, and neither survives on these
   grounds: measured, the patch teal is 1.5:1 on the blue panel. The --blob-*
   inks are the same hues carried to a weight that holds — 2.9:1 for the purple on
   the teal panel and 2.2:1 for the teal on the blue, against the 1.7:1 the old
   --bullet-blue managed on that blue. All three are decorative marks beside text
   that carries its own contrast, not information of their own.

   0.92em, from the 1:1 rule: a filled heart at the body size sits heavier than
   the outline it replaces, and the size is what takes that back out.

   The mock marked both panels' lists with a small OPEN heart in the muted
   blue-grey, which is where --bullet-blue came from; it survives as the fallback
   in `var(--heart, ...)` for any list whose section forgets to set one. Before
   that they were 26px watercolour butterfly images, which read as five
   illustrations stacked down the panel rather than as bullets. */
.believe  { --heart: var(--blob-purple); }
.who-for  { --heart: var(--aqua-mist); }

.believe li {
  position: relative;
  padding-left: 2rem;
  margin-bottom: 1.5rem;
  font-size: var(--t-base);
  line-height: 1.8;
  max-width: 34rem;
}

.believe li::before {
  content: "\2665";
  position: absolute;
  left: 0;
  color: var(--heart, var(--bullet-blue));
  font-size: 0.92em;
}

.who-for {
  position: relative;
  overflow: hidden;
}

.who-list, .who-quote {
  font-size: 1.3rem;
  display: block;
  max-width: 22rem;
  margin: 1.8rem 0 0;
  color: var(--navy);
}

/* The 22rem measure belongs to the list, not to the block that wraps it. While
   the cap sat on .who-list the heading inherited it, so centring the heading
   centred it inside a 352px column at the panel's left edge rather than across
   the panel — it read as still left-aligned. The wrapper now runs full width and
   the cap moves down to the ul, which keeps the same line length as before. */
.who-list { max-width: none; }
.who-list ul { max-width: 22rem; }


.who-for li {
  position: relative;
  padding-left: 2rem;
  margin-bottom: 1.05rem;
  font-size: var(--t-base);
  line-height: 1.8;
}

.who-for li::before {
  content: "\2665";
  position: absolute;
  left: 0;
  color: var(--heart, var(--bullet-blue));
  font-size: 0.92em;
}

/* ---------- Centred text ----------
   Two different treatments, at Lauren's direction.

   The panels and the pillars row centre their *heading only* — the body copy and
   both bulleted lists stay flush left, so the hearts keep their hanging indent. */
.believe > h2,
.who-list > h2,
.pillars .eyebrow {
  text-align: center;
}

/* The Who-For panel's closing script line centres too — it is a quote closing
   the panel, not another list item, so it reads as its own beat. Its max-width
   needs re-centring with it, or the cap would hold it off-centre in the panel. */
.who-quote {
  text-align: center;
  margin-inline: auto;
}

/* The club card's copy column centres; its feature list stays flush left, so the
   diamond marks keep the hanging indent of the base `auto 1fr` grid. */
.club-card-copy {
  text-align: center;
}

.club-card-copy .club-lead { margin-inline: auto; }

/* The closing line of this section is a quote, so it gets the painted band —
   the same treatment as Sunday Spark, in a quieter colourway. Pulled right and
   up so it tucks under the photo's bottom-left corner, as in the mock, instead
   of sitting alone in the column below the list. */
/* The photo this used to tuck under is gone from this panel, so the -8rem pull
   was hanging the quote off the panel's right edge into the club panel, where
   .who-for's overflow:hidden then cut it in half. It sits in the column now,
   closing the panel, as the mock has it. */
.who-quote {
  font-size: 1.094rem;
  display: block;
  max-width: 24rem;
  margin: 2.4rem 0 0;
  position: relative;
  z-index: 1;
}





/* ---------- Self-Love Club feature (home) ----------
   Lifted out of the three-panel band 2026-08-03. As one of three equal panels the
   paid offering was ranked alongside two blocks of supporting copy — and being
   the narrowest and shortest of the three, it read as the least important thing
   in the row. It gets its own section, its own width, and a heading a full step
   above the panel headings.

   Inset from the page edges rather than full-bleed, so the whole card sits ON the
   paper with its torn edge visible the whole way round — the panels above are
   cropped by the viewport on their outer sides. */
/* SLC-HIDDEN, 2026-08-25. `hidden` on the section in index.html does the work;
   this only guarantees it cannot be undone by accident. The UA sheet gives
   [hidden] `display: none`, and ANY author rule that sets `display` on this
   element would silently outrank it — this section does not set one today, but
   a future layout change easily could, and the failure would be the section
   quietly reappearing. Harmless once the attribute is removed. */
.club-feature[hidden] { display: none !important; }

.club-feature {
  position: relative;
  z-index: 3;
  padding: calc(var(--section) - 1rem) 0 var(--section);
}

.club-feature .wrap { width: min(1080px, 90%); position: relative; }

/* Painted teal-and-purple butterfly perched on the club card's top-left corner.
   Its fourth home in one session — Believe tear, swap with .club-approach-bfly,
   Who-For left edge, and now here ("new spot ... resting on the top left corner
   of the self love club"). Expect it to move again.

   In .wrap, not in .club-card. The card is .torn-paper, so as a child it would
   be cropped along the very corner it is supposed to sit across. .wrap shares
   the card's left, width and bottom exactly (see the note at .vine-club-seam),
   so measuring from it is the same as measuring from the card — this is the
   anchoring pattern the vine crossovers settled on, and it survives a resize.

   z-index 4 lifts it over the card; without it a .deco's 0 would put it behind
   the lavender and only the part above the corner would show.

   Sits in the clear run above the card's copy: "Join the" starts at y 3241, and
   this stops at 3246 on the far left where the heading has not begun. Painted
   x 51-208, y 3053-3246 at 1280, about a third of it on the lavender.

   No scaleX: the drawing faces right as exported, which is the way Lauren wants
   it. If it is ever mirrored, write the rotate to the LEFT of the scaleX so the
   angle still reads in screen space — the other order flips the angle's sense
   and a positive value tips the head down instead of lifting it.

   It was sized against .club-approach-bfly, the teal sketch butterfly that used
   to sit above this card — Lauren: "its good its a little bigger then the sketch
   and pops out creating some dimension". That sketch was removed on 2026-08-24,
   so this size no longer has a partner to read against; it is kept as-is rather
   than re-chosen. */
.club-corner-bfly {
  /* 140px -> 115px on 2026-08-24: "make that teal and purple butterfly on the
     lavender section a little smaller its pretty laarge". It was the largest
     butterfly left on the page by a wide margin — measured at 1280 it laid out
     to a 164x200 box against 145x90 for .remember-bfly, 107x99 for .footer-bfly
     and 90x94 for .spark-corner-bfly. At 115 it is 135x164: still the biggest,
     which suits the corner it holds, but no longer twice the mass of anything
     else.

     TOP AND LEFT MOVED WITH IT, and they have to. The piece is anchored from its
     top-left, so shrinking it alone walks the drawing up and off the card corner
     it is perched on rather than just making it smaller — the lap onto the card
     went 67px to 31px vertically in the first attempt. -124px/-3.7% -> -100px/
     -2.87% holds the original perch: the drawing keeps ~68% of its width and
     ~34% of its height over the card, measured the same way at both sizes. */
  top: -100px;
  left: -2.87%;
  width: min(115px, 10.7%);
  z-index: 4;
  opacity: 0.9;
  transform: rotate(8deg);
}

.club-card {
  position: relative;
  display: grid;
  /* copy | features. The photo is no longer a cell — it sits outside the card. */
  grid-template-columns: 1.05fr 0.9fr;
  gap: clamp(1.5rem, 3.2vw, 3rem);
  align-items: center;
  padding: clamp(2.8rem, 4.6vw, 4rem) clamp(2.4rem, 4vw, 3.6rem);
  /* Room for the heart rock, which laps over this edge from outside. */
  padding-right: clamp(2.4rem, 30%, 22rem);
  background-color: var(--panel-lav);
  background-image: url("../images/art/paper-wash.png");
  background-size: cover;
  background-position: center;
  background-blend-mode: soft-light;
  /* This asked for torn-paper-club.svg, drawn at the card's wide-and-short
     proportions, but it never took: `.torn-paper:nth-of-type(1)` outranked it
     at 0,2,0 and the card has been rendering with torn-paper-a.svg since. The
     nth-of-type rules are gone now, so this declaration would finally apply —
     and quietly change a card that has looked settled for weeks. Held at the
     `a` tear it actually has; switch this line to torn-paper-club.svg if the
     wide tear is wanted, as a decision rather than a side effect. */
  --panel-tear: url("../images/art/torn-paper-a.svg");
}

/* Not decoration: .deco and .flight are absolutely positioned, and `position:
   relative` here puts them back in flow, where they claim a grid cell — which
   pushed the copy into the wrong column the first time and later added 280px of
   dead height to the section. Only the card's real content wants this. */
.club-card > *:not(.flight):not(.deco) { position: relative; z-index: 1; }

/* Navy for the same reason as the panel labels — this is the third coloured
   box, and leaving its kicker teal read as an oversight next to the other two. */
.club-card .eyebrow {
  color: var(--navy);
  margin-bottom: 0.4rem;
}

/* A step above the panel headings — this is the loudest thing on the page after
   the hero wordmark, which is the point of moving it out. */
.club-card h2 {
  font-size: clamp(2.025rem, 3.564vw, 2.835rem);
  color: var(--navy);
  margin-bottom: 0.9rem;
}

.club-card h2 .heart { color: var(--purple); font-size: 0.55em; vertical-align: middle; }

.club-lead {
  font-size: var(--t-md);
  line-height: 1.7;
  color: var(--ink);
  max-width: 24rem;
  margin: 0 0 2rem;
}

/* Solid, not the translucent white the panel version used — a paid offer's CTA
   should be the most definite control on the page. */
.club-card .btn-primary {
  background-color: var(--teal);
  border-color: transparent;
  border-radius: 999px;
  color: #FFF;
  padding: 1.05rem 2.2rem;
  font-size: 0.977rem;
}
.club-card .btn-primary:hover { background-color: var(--teal-deep); }

.club-card .club-features {
  display: grid;
  gap: 0.95rem;
  margin: 0;
  font-size: var(--t-base);
  line-height: 1.55;
  color: var(--ink);
}

.club-card .club-features > div {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.8rem;
  align-items: start;
}

.club-card .club-features .mark { color: var(--purple); font-size: 1.15rem; line-height: 1.1; }

.club-card .flight-club {
  left: 3%;
  bottom: -4%;
  width: min(190px, 22%);
  opacity: 0.55;
  z-index: 0;
}

/* The heart rock, moved here from the closing band 2026-08-03 — running it in
   both places would read as a mistake, and it belongs with the offer.

   It hangs off the card's left edge, half on and half off, so the club breaks the
   run of coloured boxes above it instead of reading as one more of them. It has
   to be a SIBLING of the card, not a child: .club-card carries a mask, and a mask
   clips its children, so a photo inside it could never cross its edge.

   On the RIGHT, and raised so it laps up over the blue panel above. That side is
   the only one where a real overlap is reachable: the sage panel does sit above
   the photo's column on the left, but its base is 346px above the card, while the
   blue panel hangs to within 112px on the right.

   Absolutely positioned against .club-feature .wrap. The card's right padding is
   what keeps the feature list clear of it. */
.club-photo {
  position: absolute;
  z-index: 2;
  /* -2%, brought in from -5% on 2026-08-04. The floor is the card's feature
     list, which ends at x 837: at -2% the blob's painted left edge is 881, so
     44px of clearance. Measure that against the MASK, not the photo — the blob
     shape is a CSS mask, so the image itself is a full rectangle and its box
     says nothing about where the picture actually starts. */
  right: -2%;
  top: 0;
  width: min(330px, 30%);
  /* Tilted so it reads as laid down rather than placed, and lifted so roughly a
     third of it sits above the card. Rotation widens the box's footprint (~16px
     each side at this size), which the card's padding accounts for. */
  transform: translateY(-38%) rotate(-5deg);
  margin: 0;
}

/* 5/6, near the source's own 0.8 aspect (820x1025), so almost nothing is cropped.
   At 1/1 the square crop plus the blob mask's inward bite were between them
   trimming the point off the bottom of the heart. */
.club-photo img {
  position: relative;
  z-index: 1;
  display: block;
  width: 100%;
  aspect-ratio: 5 / 6;
  object-fit: cover;
  -webkit-mask: url("../images/art/photo-blob-c.svg") center / 100% 100% no-repeat;
          mask: url("../images/art/photo-blob-c.svg") center / 100% 100% no-repeat;
}

/* The DARK teal, Lauren's call — the pale --panel-teal it started on read as
   another wash beside the lavender card rather than a border. --teal-deep is the
   token nearest the deep teal the join card and the About band are painted in.
   5/6, so the vertical inset is 7 x 5/6. */
.club-photo::before {
  --mount: var(--teal-deep);
  --rim: url("../images/art/photo-rim-c.svg");
  inset: -5.83% -7%;
}

/* Below this there isn't room to hang it off the side without it covering the
   copy, so it goes back into the flow above the card. */
@media (max-width: 900px) {
  /* relative, not static: the negative bottom margin pulls the card up under the
     photo, and the card comes later in the DOM — so with the photo unpositioned
     its z-index does nothing, the card paints over it, and the bottom of the
     heart rock is sliced off along the card's top edge. */
  .club-photo {
    position: relative;
    z-index: 2;
    /* left/top carry over from the absolute rule above and still offset a
       relatively-positioned box — without clearing them the auto margins centre
       it and then `left: -5%` slides it back off centre. */
    right: auto;
    top: auto;
    transform: rotate(-5deg);
    width: min(260px, 62%);
    margin: 0 auto -3.5rem;
  }
  .club-card { padding-right: clamp(2.4rem, 4vw, 3.6rem); padding-top: 5rem; }
}

/* Phone: bigger, and pulled up to close the gap the stacked layout opens between
   the Who-For panel and the card — Lauren, 2026-08-04: "make the heart rock
   image larger and fill more of the blank space between sections". At 62% it sat
   240px wide in a 430 viewport with ~100px of bare paper above it.

   Only the top margin changes; the -3.5rem bottom is left alone deliberately.
   That value sets how far the card is pulled up UNDER the photo, and because it
   is measured from the photo's own box it holds the same overlap at any size —
   so growing the image does not eat into the card's "Join the" line, and
   .club-card's 5rem padding-top still clears it. */
@media (max-width: 700px) {
  .club-photo {
    /* Filling the band, 2026-08-04 (second pass). 84% left 53px of bare paper
       between the Who-For panel's torn base and the photo's box — and more than
       that on screen, because the blob mask curves the picture in from the top of
       its box. Now the full wrap width, pulled up so the box starts level with
       the tear. */
    width: min(360px, 100%);
    margin-top: -5.5rem;
  }

  /* And the same treatment below the card. The band under it was 103px of bare
     paper on a phone — the section's own 72px bottom padding plus the closing
     band's 32px top. The band's side was already trimmed to 2rem for this exact
     reason; this is the other half of it.

     The floor here is .vine-club-seam, which hangs 150px below the card and is
     the only thing in that space. It stays clear down to 12px of padding and
     lands 22px of leaf on "A Note From Me" at 0. 24px keeps a real margin on
     that rather than sitting on the edge of it. */
  .club-feature { padding-bottom: 1.5rem; }
}

@media (max-width: 820px) {
  .club-card {
    grid-template-columns: 1fr;
    gap: 2rem;
    text-align: left;
  }
  .club-lead { max-width: none; }
  .club-card .flight-club { display: none; }
}

/* ---------- Club banner (home) ---------- */

.club-banner {
  padding: var(--section) 0;
}

/* Per the mock the club is a hand-shaped card sitting on the page, not a teal
   stripe running edge to edge — and the club, the heart-rock photo and the note
   share one band, read left to right, rather than stacking as two sections with
   a screen of empty page between them. */
.club-banner .wrap {
  width: min(1360px, 95%);
  display: grid;
  grid-template-columns: 1.2fr 0.58fr 1fr;
  gap: clamp(1.5rem, 3vw, 2.8rem);
  align-items: center;
}

.club-figure { position: relative; }

/* A soft-cornered square, not an oval — the heart in the rock is the subject and
   an ellipse crops the top of it away. */
.club-figure img.club-photo {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  border-radius: 34% 30% 32% 36% / 32% 36% 30% 34%;
  box-shadow: var(--shadow-soft);
}

@media (max-width: 1150px) {
  .club-banner .wrap { grid-template-columns: 1.1fr 0.9fr; }
  .club-banner .note { grid-column: 1 / -1; margin-top: var(--space-lg); }
}

@media (max-width: 760px) {
  .club-banner .wrap { grid-template-columns: 1fr; }
  .club-banner .note { margin-top: 0; }
}

.club-copy {
  position: relative;
  text-align: left;
  /* Softened on every corner but by different amounts, so it reads as a shape
     drawn by hand rather than a rounded rectangle or an abstract blob. */
  border-radius: 62px 34px 54px 40px / 48px 56px 40px 50px;
  padding: clamp(2.6rem, 4vw, 3.4rem) clamp(2.2rem, 4vw, 3.4rem);
  /* Mock club card measures #0E636F, footer #0C5E6B — deeper and bluer than the
     card used to be, and much closer to flat than a strong gradient. */
  background:
    radial-gradient(ellipse 60% 55% at 88% 8%, rgba(var(--c-blue), 0.16), transparent 66%),
    radial-gradient(ellipse 55% 60% at 6% 94%, rgba(var(--c-lav), 0.14), transparent 70%),
    linear-gradient(150deg, #126975 0%, #0C5A66 100%);
  box-shadow: 0 18px 46px rgba(23, 84, 91, 0.18);
}

.club-copy h2 {
  font-size: clamp(1.62rem, 2.592vw, 2.187rem);
  margin-bottom: 0.8rem;
}

.club-copy h2 .heart { color: var(--teal); font-size: 0.6em; vertical-align: middle; }

.club-copy > p { max-width: 27rem; margin: 0 0 2.2rem; font-size: var(--t-base); line-height: 1.75; }

/* 2 x 2 inside the card, as in the mock — the mark sits beside its line
   rather than centred above it. */
.club-features {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.7rem;
  margin-bottom: 1.6rem;
  font-size: var(--t-base);
  line-height: 1.5;
}

.club-features > div {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.75rem;
  align-items: start;
}

.club-features span.mark {
  font-size: 1.15rem;
  line-height: 1.2;
  color: var(--teal);
}



/* ---------- Closing band ----------
   Per the mock the page ends on one row that alternates photo, text, photo,
   text, photo — rather than a club band with a separate signup strip beneath. */
.closing-band {
  position: relative;
  padding: var(--section) 0 var(--section);
}

/* .note-dot-path — the looped dotted trail above "A Note From Me" — was removed
   on 2026-08-04 at Lauren's request ("remove the loop line under the self love
   club section"). Its markup, its narrow-width rule and its entry in the
   below-700px list went with it. The desktop seam there is already carried by
   .vine-club-seam, which is why it was desktop-hidden to begin with.

   Two lessons from it are cross-referenced elsewhere in this file and outlive
   the rule:

   1. RESTRAIN A DOTTED LINE BY SIZE, NOT OPACITY. The art is teal (#317583),
      but a thin dashed line loses its colour to transparency far faster than a
      leafy sprig — at 0.45 it composited to #A1C0C6 and Lauren read it as white
      ("this shouldnt be white i believe its teal"). These sit at 0.75 and get
      quiet by being small. Fading one brings the grey straight back.
   2. THE GAP IS THE BUDGET. At 560-760px wide these path drawings stand
      250-340px tall against a 144px gap, which forces a crop or a tuck behind
      the card — and Lauren wants neither ("i want the full line on the page",
      "not hide behind the colored text box"). Keeping them small dissolves the
      problem instead of managing it. */

/* Blue sketch butterfly under Sunday Spark, in the space a second dotted trail
   briefly occupied. A butterfly rather than another path keeps the pair above
   from becoming a motif repeated down one page — and this is the thing the
   trails are the record of.

   It moved twice on 2026-08-04. First it was pulled right to nearly touch
   .vine-closing-right; then Lauren gave it a job instead of a spot — "above the
   leaves under the I'd love that button as if signalling people to click it".
   So it now sits directly under the sign-up button, angled up at it.

   Parented to .reminders, NOT .closing-band. .reminders already ends exactly at
   the button's bottom edge, so `top: 100%` pins the butterfly to the button
   itself and survives any reflow of the copy above. Anchored to the band it
   would have needed a bottom offset measured against the note column beside it,
   which is taller and changes with its own copy.

   `right` rather than `left`: .reminders' right edge and the button's are the
   same edge, so the offset is read straight off the button.

   The tilt is what does the signalling. The drawing flies up and to the RIGHT —
   head and antennae lead — so a negative angle (CSS rotates clockwise) raises
   the head toward the button. At -7deg it just sat there; -20deg reads as
   pointing.

   Small on purpose. The butterflies elsewhere on the page run 280px in the hero,
   and this one has to fit the ~100px band between the button and the vine's
   painted leaves below without crowding either. Check that gap by sampling the
   vine's ALPHA, not its box: it is rotated 90deg and its box top sits ~30px
   above where the leaves actually start.

   NOT called .spark-bfly, which looks like the obvious name and is a trap: a
   dead rule by that name survives further down this file from the superseded
   bottom-band layout (`right: -7%; width: min(250px, 20%); rotate(-14deg)`),
   with no markup anywhere. It silently captured this element and rendered it at
   250px rotated. Its sibling .note-reminders is dead too — both want clearing
   out, but not in the middle of a decor pass. */
.spark-corner-bfly {
  top: calc(100% + 0.4rem);
  /* Centred on the SEAM between the email field and the button, not on the
     button — Lauren: "under where the 2 buttons above it meet". At 1280 the
     field ends at 1033 and the button starts at 1043, so the target is 1038,
     and 11rem off .reminders' right edge puts the painted centre there. The
     offset is in rem rather than % because it is measured against a fixed 10px
     gap between two controls, not against the column's width. */
  right: 11rem;
  width: min(68px, 11.5%);
  opacity: 0.75;
  transform: rotate(-20deg);
}

/* Dotted trail running in from the left to meet .spark-corner-bfly. Same parent
   and same anchoring as the butterfly, so the two hold their relationship to
   each other and to the form no matter how the copy above reflows.

   Kept quiet by SIZE, not opacity — see the note at .note-dot-path. A thin
   dashed line loses its teal to transparency far faster than a leafy sprig does
   and starts reading as grey. */
.spark-dot-path {
  top: calc(100% + 1.1rem);
  right: 17rem;
  width: min(210px, 36%);
  opacity: 0.75;
  /* The drawing climbs left to right, so rotating it clockwise levels its two
     ends and the trail runs parallel to the email field above it instead of
     cutting across the band on a diagonal. 21deg, not the 24 the corner-to-
     corner slope suggests — the ends are blunt strokes, not points, so measure
     the average painted y of the first and last 12px of the trail and level
     those. At 24 the right end sat 13px low. */
  transform: rotate(21deg);
}

/* Once the band drops out of two columns the vine climbs: its leaves come up to
   ~50px below the button instead of ~100px, and the desktop size no longer fits
   between them. Resized rather than moved — sliding it left only makes things
   worse, because narrow the vine spans the full width and its top edge is high
   right across it. Measured clear at 900 and at 430; it stays on the page at
   every width, per the standing rule about decor on mobile. */
@media (max-width: 1100px) {
  .spark-corner-bfly {
    top: calc(100% + 0.1rem);
    width: min(42px, 9.5%);
  }
}

/* Hidden on mobile, on Lauren's instruction 2026-08-04 — first "remove the
   butterfly on the mobile version" (the blue one), then "remove the teal and the
   blue and the dotted lines on the mobile view". These are deliberate exceptions
   to the standing rule that decor is resized rather than hidden at narrow
   widths; she asked for each by name, as she did for .note-leaf-corner. Don't
   "fix" them back.

   The leaf vines stay. She named butterflies and dotted lines, not the sprigs,
   and the vines are what carries the section-to-section thread on a phone once
   these are gone.

   700px is the site's mobile breakpoint: it is where the closing band centres
   and where an offset from the right edge stops landing under the button at all.

   The hero's dotted flight trail (.hero-flight) is deliberately NOT in this
   list — the hero is on hold until Lauren redraws its art. */
@media (max-width: 700px) {
  .spark-corner-bfly,
  .spark-dot-path,
  /* Then the rule generalised: "everything weve added together just now should
     be hidden on mobile ... not what was already placed on mobile though before
     our session". So this list is exactly the pieces added in the 2026-08-04
     decor pass, and every NEW piece belongs here by default.

     It was four entries longer until 2026-08-24, when .club-approach-bfly,
     .club-white-bfly, .who-corner-bfly and .vine-who-right were removed from the
     page outright and their lines here went with them.

     .hero-flight is a dotted trail and is NOT here: the hero is on hold until
     Lauren redraws its art. */
  .believe-cross-flight,
  .club-corner-bfly,
  .remember-bfly { display: none; }
}

.closing-band .wrap {
  position: relative;
  z-index: 1;
  width: min(1340px, 95%);
  display: grid;
  grid-template-columns: 1fr 1.05fr;
  align-items: start;
  gap: clamp(1.5rem, 3.5vw, 3.5rem);
}

/* One photo left in this band, seated below the note's copy rather than beside
   it — the row's other two slots are gone (the heart rock moved to the club
   card, the remaining spot Lauren dropped).

   Masked with a generated path rather than shaped with border-radius, for the
   reason given at .hero-figure img: four elliptical quadrants always read as an
   oval, and at 1:1 as a plain circle, which is what these were. */
/* Pushed well right of the column's left edge so it sits under the body of the
   note rather than hanging off its start. */
.closing-band .closing-photo {
  position: relative;      /* containing block for the torn mount */
  /* 190 -> 230. Lauren, 2026-08-07: "can we make the butterfly pic in a note
     from me a bit larger."

     The real limit is not the 629px column but the TORN MOUNT, which is
     `inset: -7%` on ::before and so grows with the picture — at 230 the mount
     paints x298-560 against a column ending at x679, leaving 119px. The 42%
     left offset is a percentage, so the piece stays put and only its right side
     advances. Checked against .vine-closing-right, the only decor near it. */
  max-width: 230px;
  margin: 1.6rem 0 0 42%;
}

.closing-photo img {
  position: relative;
  z-index: 1;
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-size: 100% 100%;   mask-size: 100% 100%;
}

/* Blue, so the two home-page mounts don't repeat one colour — the heart rock up
   at the club card has the teal. Square, so both insets are the same figure. */
.closing-photo::before {
  --mount: var(--panel-blue);
  --rim: url("../images/art/photo-rim-a.svg");
  inset: -7%;
}

.closing-band .closing-photo img {
  -webkit-mask-image: url("../images/art/photo-blob-a.svg");
          mask-image: url("../images/art/photo-blob-a.svg");
}

/* ---------- The vine ----------
   leaf-vine-teal and leaf-vine-sage are the same long arcing sprig in two
   colourways. Repeated down the page — rotated, mirrored, alternating colour —
   the segments chain into one line travelling through the sections rather than
   reading as sprigs dropped in separate corners. Each segment is placed to cross
   a seam between two sections, so the vine is what stitches them together.

   Shared rules only here; each segment's placement is its own rule, named for
   the seam it crosses.

   Two things bite when placing these:

   1. Rotation is about the element's centre, so the layout box and the visual
      box are different rectangles — a 320 x 573 box lands as ~573 x 320, centre
      unchanged. `top`/`left` therefore look far off from where the piece
      appears; set them by measuring the visual box, not by reading the values.

   2. The art is a thin arc, so its bounding box is mostly empty. A box-overlap
      check reports collisions that aren't real *and* misses real ones — the
      stem tail crossed two lines of the note's copy while the box test looked
      clean at a glance. Check painted alpha, not boxes. */
.vine-seg {
  opacity: 0.5;
}

/* ---------- PHONE-ONLY, AND THEY HAVE TO SAY SO ---------- 2026-08-25
   `.vine-note-left` and `.vine-note-white` are the crossover that runs onto
   "A Note From Me", and every rule either of them has — width, position, offsets,
   transform, opacity — lives inside `@media (max-width: 700px)`. There is no
   desktop rule anywhere in this file.

   SO ABOVE 700px THEY WERE INHERITING NOTHING BUT `.deco`, which is
   `position: absolute` with no width. An <img> with no width renders at its
   INTRINSIC size, and leaf-vine-sage is 560x1004 — so both drawings were painting
   at full native scale, 560px wide and 1004 tall, in whatever spot absolute
   positioning with no offsets left them. Measured on the live page: 562,240px²
   each, against 218,689 for the next largest decoration and ~10,000 for a
   butterfly. They were the two biggest things on the home page by a factor of
   two and a half.

   Lauren, 2026-08-25: "there are 2 huge leaves towards the bottom half, please
   remove them." They are not removed — they are the phone crossover and still
   wanted there — they are simply confined to the widths they were written for.

   THE LESSON IS GENERAL: a decoration whose ONLY rules are inside a media query
   needs an explicit default outside it. `.deco` gives it position but not size,
   and an unsized <img> is never invisible. */
.vine-note-left,
.vine-note-white { display: none; }

/* First segment: across the seam between the club card and the note band, its
   leafy end lapping the card's torn bottom edge and its stem running down into
   the paper below.

   The orientation is not cosmetic. Two other rotations put the long bare stem
   straight through the note's copy — invisible at this opacity, but there in
   the pixels. This one is one of the few that clears every line of text while
   still crossing the seam; re-derive it against the painted alpha if the copy
   or the card's height ever changes, rather than nudging it by eye. */
/* ONE rule for both halves — the only arrangement that cannot split.
   .vine-club-white is a child of .club-card; .vine-club-seam is a child of
   .club-feature .wrap. Those two boxes share their left, their width AND their
   bottom edge at every viewport (the card is the wrap's last in-flow child, and
   both measure 351px at 390 and min(1080px, 90%) on desktop), so one set of
   percentages puts the two copies on the same page pixel everywhere.

   Before this, the seam lived in .closing-band and was positioned against the
   full-width section while its partner was positioned against the centred,
   width-capped card. They agreed at 1280 and nowhere else — 83px apart at 1440,
   166px at 1600. `top: -16rem` had the same flaw vertically: it measured down
   from the closing band while the white half measured up from the card's bottom.

   Opacity is stated here because `.vine-seg` sets 0.5 and this pair needs 0.6 on
   both — a crossover has to match in opacity as well as position, or the drawing
   changes density as it crosses.

   The card paints above decoration, so it hides the part of the sage half that
   crosses it and .vine-club-white draws that part in white instead. That relies
   on the seam being BEFORE .club-card in the markup. */
.vine-club-white,
.vine-club-seam {
  left: -11.63%;
  bottom: -246px;
  width: 22.22%;
  opacity: 0.6;
  transform: rotate(90deg);
}

@media (max-width: 1100px) {
  /* Below here the crossover stops being a crossover: the white half goes and
     the sage one carries on alone as an ordinary sprig in the gap under the
     card. Re-derived against .wrap when the seam moved parents — .wrap is 90% of
     the viewport at these widths where .closing-band was 100%, so the old
     -6% / 42% of the section become -12.22% / 46.67% of the wrap, and the
     vertical is anchored to the card's base instead of the next section's top. */
  .vine-club-white { display: none; }
  .vine-club-seam {
    left: -12.22%;
    bottom: -222px;
    width: min(210px, 46.67%);
  }
}

/* ---------- Phones get the crossover back ----------
   Lauren, 2026-08-07: "the sage leaf above a note from me should be layered on
   top of the purple section, and the leaves should change color to white when it
   hits the purple."

   That is this crossover, which the 1100px block above had switched off — below
   1100 the white half went and the sage one carried on alone as a plain sprig in
   the gap under the card. Measured at 375 it sat at y7220 against a card ending
   at y7218: two pixels clear, touching nothing, which is exactly what she is
   describing.

   -222px -> -182px raises it 40px so it straddles the card's base: 49% of the
   painted sprig lands on the purple and 51% on the paper below, the evenest
   split the drawing's own shape allows. Swept the range — -190 is 36/64 and
   reads as a sprig that merely grazes the card, -170 is 65/35 and reads as one
   growing out of it.

   THE COLOUR CHANGE NEEDS NO CLIPPING OF ITS OWN, and this is the part worth
   understanding before touching either value. The two halves sit at identical
   percentages, and they are complementary by construction:
     - `.vine-club-white` is INSIDE the card, so the card's torn mask crops it to
       wherever the paper actually is;
     - `.vine-club-seam` is a sibling written BEFORE the card, so the card paints
       over it wherever the paper actually is.
   Every pixel is therefore covered by exactly one of them, and the seam between
   the colours follows the real torn contour rather than a straight line at the
   card's box edge. A tear trough that dips above the box bottom shows sage; a
   crest that hangs below it shows white. Neither needed to be told where the
   tear is.

   The percentages can be shared because `.club-feature .wrap` and `.club-card`
   have the same left, width AND bottom here too — re-verified at 375, where both
   measure l19 / w338 / b7218. That is the whole reason one set of numbers can
   place two elements in different parents on the same page pixel.

   Zero painted pixels on the card's copy or on the note below it. Note the OLD
   value was not clean: at -222 the sprig put 14 pixels on text, so this fixes a
   small collision on the way past. */
@media (max-width: 700px) {
  .vine-club-white {
    display: block;
  }

  .vine-club-white,
  .vine-club-seam {
    /* THE SIZE AND THE VERTICAL ARE TIED, and they have to be. A flat
       `bottom: -182px` is right at 375 and wrong everywhere else: the sprig
       grows with the screen while a px offset does not, so the split slid from
       49% on the purple at 375 to 74% at 430. The crossover stopped being a
       crossover on a bigger phone.

       So the size gets a name and the offset is derived from it. The fit is
       linear and came from solving both ends independently — 157.5px wide wants
       -182, 180.6px wants -207 — which is 1.08x the width plus 12px.

       42vw, NOT the 46.67% the width used to carry. Percentages resolve against
       different axes depending on the property: 46.67% is correct in `width`
       (against .wrap's width) but inside `bottom` it would resolve against
       .wrap's HEIGHT and land nowhere near. .wrap is 90% of the viewport at
       these widths, so 46.67% of it is 42vw — the same number in a unit that
       means the same thing in both properties. Verified: 42vw is 157.5px at 375
       and 180.6px at 430, matching the old width exactly. */
    --club-sprig: min(210px, 42vw);
    left: -12.22%;
    width: var(--club-sprig);
    bottom: calc(-1.08 * var(--club-sprig) - 12px);
  }
}

/* Both pillars segments are anchored to .pillars .wrap rather than to the
   section, because only the wrap is positioned. The wrap is inset from the page
   edge, so their negative insets are what carry them out to the margins. */

/* Sage, on the right, in the gap between the Remember section's copy and the
   Self-Expression icon below it — the one place on this side where neither
   section reaches. Sized to sit inside that 220px band rather than running down
   over the icon.

   The mobile override moves it above the "What You'll Find Here" heading
   instead: stacked, the columns collapse and this right-hand gap closes up. */
/* 3% -> 1.1%. Lauren, 2026-08-06: "move to the right so the stem is hidden but
   most leaves are still seen."

   Those two pull against each other and the balance point is measurable, not a
   feel. Turned -90deg this drawing's foot maps to the RIGHT, so the stem hides
   by overhanging the page edge — and it was barely overhanging at all: the
   painted tip sat only 4px past it.

   THE BARE STALK IS 23.8px HERE. Measured by sampling the ASSET row by row up
   from its foot: the painted width stays under 40 of 560 for the first 65 rows
   and then jumps to 263 where the leaves start, so the stalk is 65 asset px,
   which at this element's 205px render (scale 205/560) is 23.8 screen px. That
   left ~20px of bare stem on the page, which is what Lauren was seeing. Do NOT
   try to read this off the rotated element — every page-column then cuts across
   leaves at other heights and the profile is meaningless.

   1.1% is the FIRST value that buries it: the tip lands 27px past the edge
   against the 23.8 needed, a 3.2px margin. The cost is 23px of drawing, so 335
   of the 362 painted pixels are still on the page — 93% of the leaves for a stem
   that is now fully hidden. 0.6% would give a 9px margin but throws away 29px,
   which is the wrong side of the trade she asked for.

   A percentage is safe here in a way it usually is not: this resolves against
   `.pillars .wrap`, which is `min(1160px, 92%)` and therefore CAPPED, so at every
   viewport from 1261 up it is a constant 1160 and 1.1% is a constant 12.8px. */
.vine-pillars-top {
  right: 1.1%;
  top: -16rem;
  width: min(210px, 17%);
  transform: rotate(-90deg);
}

/* Teal butterfly beside the sage sprig that sits above "How We Find Our Way
   Back". PHONE ONLY, and deliberately so: the sprig is out on the section's
   right-hand margin at full width and only swings up over the heading once the
   pillars stack, so "next to the sage leaves" describes a place that exists
   below 700px and nowhere else. Hidden by default, shown in the media query
   further down — the inverse of the usual rule, same as .note-dot-path.

   Same drawing as .club-approach-bfly on the Self-Love Club section — Lauren
   picked it from the four teal options knowing that. */
.pillars-teal-bfly,
.pillars-blue-bfly { display: none; }

@media (max-width: 700px) {
  .pillars-teal-bfly {
    display: block;
    /* Measured at 375 against .pillars .wrap (origin 11, 2621). The sprig's
       painted edge starts at x 130 and the last line of "Little by little"
       ends at y 2471, so the pocket to its left is x 0-130 below that line. */
    top: -78px;
    /* 56 -> 24. Lauren, 2026-08-06: "move the teal butterfly to the left an inch
       and tilt it right slightly."

       An inch is 96px and there were only about 60 to give — the drawing painted
       x73-143, so a full inch would put its left edge at x-23, a quarter of the
       butterfly off the page, which reads as broken on a piece with no stem to
       justify running off. -8px was tried, taking the whole 60 and landing the
       painted edge flush with the body copy's left margin; Lauren: "thats too
       far left now." So 24, a 28px move — half of what was available.

       The number that actually matters here is the gap to the sage sprig, since
       this butterfly exists to sit beside it: it was overlapping by 9px and now
       stands 19px clear.

       24 -> 44 -> 70, 2026-08-06, in two steps, both chasing .vine-pillars-top's
       own 34px move right. That move had opened the gap from 19px to 51 and left
       the butterfly on its own; Lauren: "move the teal butterfly a little to the
       right now", then "move them closer to the leaves, maybe like an inch and a
       half more".

       An inch and a half is 144px and there are 30. The sprig's painted edge is
       at x167 at 390 and this drawing's box ends at x136, so 26px is everything
       available short of the two touching — which is why the second step is 26
       and not 144. The remaining 4px of box gap reads wider than it sounds: the
       butterfly is rotated 22deg, so its wing tips sit well inside the corners of
       the box being measured.

       This holds across phone widths even though it looks like it should not.
       The offset is against .pillars .wrap, whose inset is a percentage
       (`width: min(1160px, 92%)`), so the wrap's left edge tracks the viewport —
       4.8px at 320, 12 at 390, 28 at 699 — and the painted edge stays on the
       page at all of them. */
    left: 70px;
    width: 74px;
    opacity: 0.75;
    /* Positive tips it right. The drawing is a symmetric head-up butterfly, so
       the sign of the angle is the direction of the lean and nothing else.
       12 -> 22 for Lauren's "tilt it right slightly". */
    transform: rotate(22deg);
  }

  /* The sage sprig above "How We Find Our Way Back", nudged right so its cut
     stem runs off the page. Lauren, 2026-08-06: "move them slightly to the right
     to hide the stem."

     PHONE ONLY, as an override of the max-width:1100 rule rather than an edit to
     it. That rule's `right: 14%` resolves against .pillars .wrap, so at 1100 the
     14% is ~140px and the sprig sits well inside the paper with its stem nowhere
     near an edge — moving it right there would just push a whole drawing across
     the middle of the page. It is only on a phone that the wrap's right edge and
     the viewport's are close enough for this to hide anything.

     34px, in px and not a percentage: what has to clear the edge is a fixed
     ~26px of bare stem at the drawing's top end, not a fraction of anything. At
     390 this takes the rotated box from x132-382 to x167-417, putting the stem
     past the 390 edge with the outermost LEAF still on the page, which is the
     whole point — the vine now enters from the margin the way every other
     coloured segment on this site does. `body` is overflow-x: hidden and the
     document's scrollWidth stays 390, so nothing scrolls sideways.

     Watch the gap to .pillars-teal-bfly. That butterfly exists to sit beside
     this sprig and was tuned to stand 19px clear of it; this move widens that to
     ~53px. If the pair should stay tight, the butterfly's `left: 24px` moves by
     the same 34, not by eye.

     The selector is `.pillars .vine-pillars-top`, not the bare class, and that
     is load-bearing. The max-width:1100 rule this overrides sits BELOW this
     block in the file, so at a single class the two tie on specificity and the
     later one silently wins — the same trap the note on .vine-who-right
     describes. The extra class breaks the tie in the right direction. */
  .pillars .vine-pillars-top { right: 17px; }

  /* The teal vine under "Self-Expression", pulled back onto the page. Lauren,
     2026-08-06: "move the teal leaves under self expression to the right more."

     Same phone-only override shape as the sprig above, and the same specificity
     guard applies for the same reason — the max-width:1100 rule sits below this
     block in the file.

     `left: -10%` there resolved to -36.7px at 390 and put the rotated box at
     x-64, a quarter of the drawing off the left edge. 13px moved it 50 right, to
     x-14: all but the outermost leaf tip on the page. Then back 20 to -7px,
     because at 13 the vine had closed right up on .pillars-blue-bfly — the
     butterfly had not moved, the leaves had arrived. Lauren, on that: "the blue
     one is a little too close", then "actually i think its the leaves that need
     to go to the left just a tiny bit", so the correction is here rather than on
     the butterfly, which stays where she put it. In px rather than a
     percentage because what is being corrected is a fixed overhang, not a
     fraction of the wrap — at -10% the overhang grew with the viewport, 56px at
     320 and 78 at 699 off three different drawing widths. */
  .pillars .vine-pillars-left { left: -7px; }

  /* Blue sketch butterfly in the open paper to the right of .vine-pillars-left,
     in the band between the last pillar's copy and the Believe panel.

     Anchored to the wrap's BOTTOM-right rather than its top: the pillars stack
     into one tall column on a phone, so a top offset here would be ~1650px of
     accumulated content and would move with every copy edit above it. The band
     itself is fixed to the end of the section.

     The band is the size limit — the copy ends at y 4260 and the panel starts at
     4369, so ~95px of paper. Same drawing Lauren picked for the desktop try in
     the Remember section, and the one already at the Sunday Spark. */
  .pillars-blue-bfly {
    display: block;
    bottom: -83px;
    right: 79px;
    width: 70px;
    opacity: 0.75;
    /* The drawing faces right as exported; mirrored so it faces left. */
    transform: scaleX(-1);
  }

  /* White dotted butterflies crossing the seam between the stacked panels.
     Unrotated: the drawing already falls from a small butterfly at its top-left,
     through a trail, to the big one at middle-right, so it descends on its own.

     Measured against .believe-for (top 4337) with the page fully settled. The
     Believe panel ends at 5353 and Who-For begins at 5401, and each has empty
     colour on its side of that seam, so the run from 5285 to 5470 clears the
     last list item above (its text ends at 5236) and the Who-For heading below
     (5501). Measure this one late — the panels are ~100px shorter before the
     images below have loaded, and a placement set on that reading lands on the
     last list item.

     Positioned so the BIG butterfly lands on the blue rather than in the gap: it
     sits at about 72% of the drawing's height, which at 185px tall puts it at
     5418, comfortably past the seam.

     Note the piece is self-clipping across the 48px seam — it is white line art
     and the paper between the panels is white, so the trail fades out there and
     picks up again on the blue. */
  .believe-seam-anchor {
    display: block;
    position: relative;
    height: 0;
  }

  .believe-seam-flight {
    display: block;
    /* MEASURED FROM THE SEAM, not from the section's top, and that change is the
       fix rather than the number.

       History, because the old number looked carefully derived and still failed:
       it was `top: 920px` against .believe-for, chosen as the bottom of a usable
       window of 863-920 so the lower butterfly would land whole on the blue.
       That window is 57px wide — the last Believe list item and the "Who Lumi
       Libra Is For" heading leave a 208px-tall drawing only 57px of travel. But
       both panels reflow with viewport width, so the seam MOVES relative to the
       section: 982px down at 390, 1017px at 375. 35px of drift into a 57px
       window. At 390 the lower butterfly sat 21px onto the blue; at 375 it sat
       13px ABOVE it, stranded in the white gap. Lauren, 2026-08-07: "the bottom
       butterfly stays in the blue and the top one reaches and sits in the teal."

       Anchored to the seam the drift is gone by construction — the offset below
       is a distance from the join itself, so it means the same thing at every
       width. Verified at 320/375/390/430: the lower butterfly lands 33-36px onto
       the blue and the upper one 60px+ clear of the teal's bottom edge, with
       zero painted pixels on the copy at either end.

       -62px is the BALANCE POINT, and it is solved rather than picked. Measuring
       the two butterfly bands against the offset gives two straight lines —
       clearance above the teal's edge is (-top - 40), depth onto the blue is
       (top + 83) — and setting them equal puts both at 21px. That is as good as
       this drawing allows, and the reason is worth writing down: the butterflies
       are 91px apart vertically, while the seam they must span is 108px of
       danger (a 30px tear trough on the teal, the 48px gap, another 30px trough
       on the blue). 91 < 108, so no offset clears both troughs completely.
       Anything gained at one end is lost at the other, one-for-one.

       Which means the old 920 was not badly chosen — at 390 it landed on exactly
       this balance, 22px and 21px. It just could not HOLD it, because it measured
       from a section top that drifts away from the seam. Same optimum, now
       reached at every width instead of one.

       Still a limit, and unchanged by any of this: both panels' edges are TORN
       and wander up to --wave-h (30px), so 21px clears the box edges but not the
       deepest troughs. Fixing that needs a taller drawing or a wider seam, not a
       different number here. */
    top: -62px;
    left: 22px;
    width: 340px;
    z-index: 4;
    opacity: 0.85;
    /* Mirrored. As drawn it opens at the top-LEFT and the big butterfly sits
       low-right, so the teal half sat left and the blue half swung right.
       Flipped, it starts high on the RIGHT of the teal, curves down under the
       seam, and carries left across the blue — which is the gesture asked for.
       Nothing else in the drawing changes; the fall is vertical either way. */
    transform: scaleX(-1);
  }
}

/* Teal, out of the pillars row's bottom-left where the first pillar's copy runs
   out, and over the seam into the panels below. */
.vine-pillars-left {
  left: -8%;
  bottom: -7rem;
  width: min(270px, 22%);
  transform: scaleY(-1) rotate(90deg);
}

/* The teal's turn on the right-hand margin, so the two paper colourways enter
   from both sides rather than stacking down one edge — sage low-left at the club
   seam, teal low-right here, above the footer's tear. */
/* Laid flat directly beneath the signup button.

   215px -> 280px on 2026-08-10. Lauren: "the teal leaves on the bottom right
   under sunday spark — can you match the size of those with the rest of the
   leaves on the page." It was the odd one out. Every other sprig cut from
   leaf-vine-teal/white.webp (both 560x811, so declared width IS apparent leaf
   size) runs 270-320: .vine-believe-cross-teal 280, .vine-who-right 280,
   .vine-pillars-left 270, .vine-crossover-* 320. At 215 this one was ~23%
   smaller than its two nearest neighbours, which is what she was seeing.

   The old note here claimed 215 was forced — "anything past ~215px either rides
   up over the button or disappears under the footer". That is TRUE of the
   narrow-width rule below, where the band under the button really is ~72px. It
   was never true on desktop: measured at 1440 there are 543px of clear band
   between the button and the footer, and at 280 the piece still clears the
   button by 267px.

   `right` and `bottom` are re-derived rather than left alone, so the drawing
   does not drift while it grows. It is rotated 90deg about its own centre, so
   the box it occupies on screen is not the box it was laid out in: the height
   collapses to W and the width opens out to k*W, where k = 811/560 is the
   asset's aspect. Both visible edges therefore move by (k/2 - 1/2)*W = 0.2241*W
   — the right edge OUTWARD, the bottom edge UP:

     on-screen right  = layoutRight  + 0.2241 * W
     on-screen bottom = layoutBottom - 0.2241 * W

   which is why both offsets had to change to keep the drawing where it was.
   At W = 280 that term is 62.7px, so:

     right: 87px   -> a page margin of 87 - 62.7 = 24px
     bottom: -4.1rem (65.6px) -> 65.6 - 62.7 = 3px tucked under the footer's tear

   Both measured against the old placement and identical to it. Only the size
   changed.

   `right` is a derived px, not the % it used to be, and that is the fix for a
   pre-existing drift: a percentage right minus a fixed transform term made the
   page margin a function of window width. It ran 24px at 1440 but only 7px at
   1101, and at 280 it would have been 3px — the sprig jammed against the page
   edge on a small laptop. In px the margin is 24 at every width above 1100.

   The `min(280px, N%)` idiom is gone for the same kind of reason: 26% only
   drops below 280px under 1077, and the narrow-width rule below already owns
   everything under 1100, so the percentage could never bind. A flat 280px says
   what actually happens — and matches .vine-believe-cross-teal, which is the
   sibling this is being sized against. */
/* ---------- The vine above "A Note From Me", PHONES ONLY ----------
   2026-08-25. Restores what disappeared when the Coming Soon club card was
   hidden: .vine-club-seam and .vine-club-white both live inside that section, so
   hiding it took them with it — the note on that section records this as a
   deliberate consequence at the time. Lauren noticed the gap.

   IT CANNOT COME BACK AS THE CROSSOVER. That pair changed colour where it
   crossed the card's lavender edge; with no card there is no edge, so this is
   the sage half alone, on paper, from the same drawing.

   PHONES ONLY, which is where the pair was last tuned. Above 700px the crossover
   was already reduced to the sage half by itself, and on desktop this corner
   already has .vine-pillars-top — a third piece there is exactly what the
   2026-08-24 thinning pass was cutting.

   IT KEEPS THE PAIR'S OWN `rotate(90deg)`. The About page's crossover uses a
   flipped construction, but this is a restoration and the sage drawing behaves
   differently under rotation — see the note on the transform below. */
@media (max-width: 700px) {
  .vine-note-left,
  .vine-note-white {
    /* Turns the pair back on — they are display:none by default above this
       breakpoint. See the note beside `.vine-seg`. */
    display: block;
    /* SHARED: width, transform and opacity must match or the sprig steps
       sideways where it changes colour. --note-sprig names the width so the two
       vertical offsets below can both be derived from it. */
    /* 52vw -> 46vw (and the px cap with it, 215 -> 190). Lauren: "lets just make
       them a little smaller" — about 12% off, not the full match described below.

       WHY THEY LOOKED OVERSIZED IN THE FIRST PLACE: the width was never the outlier.
       At 375 this pair was 195px wide, the SAME as the hero crossover and less than
       `.vine-closing-right`'s 218 — but its rotated box was 398x360, roughly 35% more
       area than anything else on the page. The cause is the drawing: leaf-vine-sage
       is 560x1004 (aspect 1.793) where leaf-vine-teal is 560x811 (1.448), so at an
       identical `width` the sage vine is 24% LONGER. Matching these two crossovers by
       `width` does not match them at all.

       42vw would make the lengths identical — 195 x 1.448 = 282px of teal against
       157 x 1.793 = 282px of sage. 46vw stops short of that on purpose; it is her
       "a little", and it keeps this piece slightly the larger of the two.

       EVERY OFFSET BELOW IS IN SPRIG UNITS, so they all scale with this and the
       1.793 invariant survives a resize untouched. What does NOT scale is
       `--note-gap`, which is spacing rather than artwork — see its own note. */
    --note-sprig: min(190px, 46vw);
    position: absolute;
    /* FLIPPED TO THE RIGHT MARGIN, 2026-08-25: "lets actually flip sides so they
       come from the right side." It entered from the left for its whole life, at
       -11.63% and then -16.96%.

       `right`, and `left: auto` WITH IT. `left` is what the rule set before, and
       leaving both would pin the element to both edges and stretch it. The magnitude
       is unchanged, so the sprig loses the same amount of stalk to the margin on the
       right as it did on the left.

       ONE REAL DIFFERENCE BETWEEN THE TWO SIDES: overflow past the LEFT page edge is
       free, while overflow past the right can open a horizontal scrollbar. `main` is
       `overflow-x: clip`, which is what makes this safe — verified at 375, 390 and
       430 rather than assumed. */
    left: auto;
    right: -16.96%;
    width: var(--note-sprig);
    opacity: 0.6;
    /* rotate(90deg), WHICH IS THE ORIGINAL PAIR'S OWN TRANSFORM — not the About
       page's `rotate(104deg) scaleX(-1)`. This is a restoration, so it keeps the
       gesture it had. It also happens to be the right choice here: this is the
       SAGE drawing, a different aspect from the teal one (1.793 against 1.448),
       and at 90deg its ink sits in the TOP QUARTER of its rotated box — 90% of
       it above 0.641 — which is what lets the piece clear the "A Note From Me"
       heading below it. The teal drawing flipped puts its ink in the LOWER half
       and would sit straight on the words. */
    /* 125deg, NOT THE PAIR'S ORIGINAL 90. Lauren wants the sprig to cross the
       panel's edge AND reach down over "A Note From Me", and at 90deg it cannot:
       lying flat, its visible leaves form a band about 60px tall, while the tear
       and the heading are 86px apart. Sampled at several angles, the visible ink
       spans 0.43-0.57 of the box from 115deg on — at 125 that is 176px, which
       covers both with room to spare. The drawing also reads as travelling DOWN
       the page at this angle rather than lying across it, which is the gesture
       the vine makes everywhere else.

       THE TWO OFFSETS ABOVE ARE TIED TO THIS ANGLE. Changing it changes the box
       height (1.850 * sprig here, 1.000 at 90deg) and both multipliers have to
       be re-derived together or the halves separate at the tear. */
    /* MIRRORED FOR THE SIDE SWAP. `scaleX(-1) rotate(125deg)` — CSS applies
       transform functions right to left, so the rotation happens first and the mirror
       then flips the FINISHED drawing across the vertical axis. That is what makes
       this an exact mirror image of the composition that used to sit on the left,
       and it leaves 125deg reading in screen space so the notes above still hold.

       Written the other way round, `rotate(125deg) scaleX(-1)`, the mirror would
       apply to the upright drawing and the angle would carry the mirrored copy
       somewhere else entirely. Both orders appear in this file deliberately — see
       `.beyond-corner-white` and `.chalk-intro-leaf`.

       The box dimensions are unchanged by a mirror, so the two vertical multipliers
       and their 1.793 invariant survive this edit untouched. */
    transform: scaleX(-1) rotate(125deg);
    /* ABOVE THE PANELS, and it has to be. With the club card hidden its section
       collapsed to nothing, so `.believe-for`'s panels now butt straight up
       against this band — there is no gap left to hang in, and the band's own
       padding leaves only 31px above the heading, far less than this sprig's
       ink. At z-index 0 the "Who It's For" panel painted straight over it and
       the piece was simply invisible; `elementFromPoint` at its centre returned
       `.who-for`, which is how that was found rather than guessed.

       Crossing onto the panel is also the faithful restoration: the vine this
       replaces crossed onto the club CARD in exactly this way. Checked: it lands
       on no copy in either panel. */
    pointer-events: none;
  }

  /* THE SAGE HALF SITS BEHIND THE PANEL. `.who-for` carries z-index 1, so
     leaving this at the default lets the panel paint over the part that crosses
     it — which is what makes the white copy inside the panel the only thing
     visible up there. Do NOT raise this; at z-index 5 the sage ran straight
     across the blue and the crossover stopped existing. */
  .vine-note-left {
    /* THE INVARIANT, and it is the only thing to understand about this pair:
         (this multiplier) + (.vine-note-white's) = 1.793
       1.793 is the sage drawing's own aspect (1004/560). Move one half up by D and
       the other MUST move down by D or the sprig steps sideways at the tear. The
       history checks out against it — 1.187/0.606, then 1.009/0.784, then
       0.859/0.934, now 1.141/0.652 — every pair sums to 1.793.

       0.859 -> 1.141, 2026-08-25: "those sage leaves above a note from me need to be
       moved higher." Not taste — measured, 389 painted pixels were sitting on the
       "A Note From Me ♡" heading. 55px of lift at a 195px sprig clears it.

       (The earlier note here described growing the sprig as an alternative and it is
       still true: at this rotation the drawing's ink sits in the top quarter of its
       box, so reaching further down the page by scaling would need a ~545px sprig.
       Moving it is the lever, in both directions.) */
    top: calc(-1.141 * var(--note-sprig));
    z-index: 0;
  }

  /* THE WHITE HALF, ANCHORED TO THE PANEL'S BOTTOM, and the offset is derived
     rather than measured so the two halves cannot drift apart when the sprig
     resizes. The sage copy hangs (1.187 * sprig) above the closing band's top;
     this one hangs below the panel's bottom by that same geometry re-expressed
     from the other end: the element is 1.793 * sprig tall (the sage drawing's
     own aspect), so the distance is the fixed gap between the two boxes plus
     (1.793 - 1.009) = 0.784 * sprig. THE TWO MULTIPLIERS MOVE TOGETHER — change
     the sage `top` and this one has to be re-derived or the halves separate at
     the tear.

     --note-gap IS THE ONE MEASURED NUMBER: 56px between `.who-for`'s bottom edge
     and `.closing-band`'s top at 375. It is spacing, not artwork, so it does not
     scale with the sprig — which is exactly why it has to be added separately
     rather than folded into the multiplier. If the halves ever separate, this is
     the number that changed. */
  .vine-note-white {
    --note-gap: 56px;
    /* 0.934 -> 0.652, the exact counterpart of the sage half's 0.859 -> 1.141. The
       two sum to 1.793; see the invariant note above. Changing one alone is what
       separates the halves at the tear. */
    bottom: calc(-1 * (var(--note-gap) + 0.652 * var(--note-sprig)));
    z-index: 2;
  }
}

.vine-closing-right {
  /* FLIPPED 2026-08-25, Lauren: "flip them so the stem is coming from the right
     side and the leaves are scooping down... and have the stem slightly off
     page".

     `rotate(270deg)`, WHERE IT WAS `scaleX(-1) rotate(90deg)`, and the two differ
     by exactly a vertical flip — scaleX(-1)·scaleY(-1) is a 180deg turn, so
     adding the mirror and simplifying lands on 270. Before, the thin tip sat
     upper-left and the stem ran down to the lower right, arc bulging upward.
     Now the stem enters at the upper RIGHT and the vine sweeps down and left
     with the arc bulging down, which is the scooping read.

     RIGHT: -18px, NOT THE 87px IT HAD. The old note here warned that -6% pushed
     more than half the sprig off the page and read as a stub — that was the old
     orientation, where the drawing's long axis ran across the page. Rotated, the
     footprint is ~405px wide and about 75 of it runs off, so roughly 80% is
     still on the page: the stem end disappears past the edge and nothing else
     does.

     BOTTOM: -1.2rem, up from -4.1. The rotation moves the painted leaves down
     within the box, and at the old offset they crossed the footer's torn edge.

     DESKTOP ONLY WITHOUT A MEDIA QUERY, and that is not an accident: the
     <=1100px rule further down sets its own right/bottom/width/transform for
     this element and comes later in the file, so it wins on its own. Change one
     and the other is unaffected. */
  right: -18px;
  bottom: -1.2rem;
  width: 280px;
  transform: rotate(270deg);
}

@media (max-width: 1100px) {
  /* .vine-club-seam's narrow-width placement used to live here. It moved up
     beside .vine-club-white when the seam changed parents — the two have to be
     read together, and leaving a second rule this far down the file meant it
     silently outranked the new one and set `top` against a `bottom`, which
     stretches an absolutely positioned image instead of moving it. */
  /* The pillars stack into one column here, so the copy runs the full width and
     the desktop overhang clipped the section heading. Lifted and narrowed. */
  .vine-pillars-left { left: -10%; bottom: -7rem; width: min(190px, 48%); }
  .vine-pillars-top {
    right: 14%;
    /* Lifted well clear of the heading. The band between the section top and the
       heading is only ~72px, and the heading is centred so it spans the middle
       of the column — every placement inside that band crossed the words. This
       carries up into the empty space above the section instead. */
    top: -16rem;
    width: min(150px, 38%);
    /* -90deg puts the stem at the top-right and sweeps the leaves down-left. */
    transform: rotate(-90deg);
  }
    /* Laid flat and wide directly under the signup button. The band below the
     button is only ~72px before the footer covers everything, so "bigger" here
     is horizontal reach, not height — the piece runs 327px across and the footer
     hides its lower half. */
  .vine-closing-right {
    right: 14%;
    bottom: -14rem;
    width: min(230px, 58%);
    transform: scaleX(-1) rotate(90deg);
  }
}

/* Both headings in this row are letterspaced small caps in the mock — the script
   weight belongs to the note's closing line, not to its title. */
.closing-band .note-copy h2,
.closing-band .reminders h2 {
  font-family: var(--font-body);
  font-size: 1.166rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--teal-label);
  margin-bottom: 1rem;
}

/* "Read my story ->", added 2026-08-07. Its own wrapper rather than a bare <a>
   inside the flow, because `.note-copy p` carries the paragraph rhythm here and
   an inline-block anchor would inherit none of it. 1.4rem is a touch more than
   the 0.9rem between paragraphs — enough to read as a separate action, less than
   the 1.6rem the photo below takes, so the note still ends as one block.

   No width or alignment of its own: at <=700px `.note-copy` goes `text-align:
   center` and the inline-block pill follows it, the same way the copy does. */
.note-actions { margin: 1.4rem 0 0; }

/* Smaller than a standard .btn, at Lauren's ask on 2026-08-07. Scoped to this
   one button rather than touched on .btn — every other button on the site is a
   primary action and they all share that base.

   It is the quietest call to action on the page and now looks it: it sits a
   column away from the Sunday Spark submit, which stays full size, so the two
   were competing at matched dimensions. The border, pill radius and uppercase
   tracking are untouched, so it still reads as the same button family — only
   the type and the padding come down. Letter-spacing is reduced with the type
   because 0.18em was tuned at the larger size and holds the word too loosely
   once the type shrinks. */
.note-actions .btn {
  font-size: 0.86rem;
  letter-spacing: 0.14em;
  padding: 0.72rem 1.5rem;
}

.note-script {
  font-family: var(--font-script);
  font-size: 1.094rem;
  line-height: 1.5;
  /* --teal-ink, NOT --teal. This measured 3.88:1 on bare white against the 4.5
     that 19px at weight 400 needs — it was failing before the ground wash
     existed and nobody had caught it, because --teal is a button-and-accent
     colour that happened to get used as body ink. --teal-ink is the variable
     that exists for exactly this and measures 6.75. */
  color: var(--teal-ink);
}

@media (max-width: 1100px) {
  .closing-band .wrap { grid-template-columns: 1fr; }
}

@media (max-width: 700px) {
  .closing-band .wrap { grid-template-columns: 1fr; justify-items: center; text-align: center; }
  .closing-band .closing-photo { margin-inline: auto; }
  /* Lauren, 2026-08-04: bring "A Note From Me" up on mobile. Stacked, the club
     section's 72px bottom padding and this band's 72px top padding met as 144px
     of blank paper — read as a gap on desktop, as a dead screen on a phone.
     Only the top comes in; the footer still needs the bottom. The floor is set
     by the club sprig, which hangs to y+164 below the card and would otherwise
     land on the heading. */
  .closing-band { padding-top: 2rem; }

  /* .note-dot-path's narrow rule lived here and went with the element. One
     thing it taught is worth keeping for the next full-bleed piece: `max-width:
     none` is required to overhang the viewport at all, or the global
     `img { max-width: 100% }` clamps the overhang back and the bleed silently
     does nothing. */
}

.note-reminders {
  position: relative;
  padding: var(--space-lg) 0 0;
  background: none;
}

.note-reminders .wrap { position: relative; z-index: 1; }

/* A teal pool in the bottom-right corner, under the butterfly that straddles
   into the footer. Same construction as the hero halo and the Remember pool —
   one radial pool, heavy blur, no mask — so the page opens and closes on the
   same note instead of the bottom-right corner being bare paper.
   Held above the footer's top edge: the footer is a solid teal slab, and teal
   paint on teal reads as a smudge rather than as a wash. */
.note-reminders::after {
  content: "";
  position: absolute;
  right: -14%;
  bottom: 0;
  width: 46%;
  height: 17rem;
  z-index: 0;
  border-radius: 48% 52% 44% 56% / 46% 42% 58% 54%;
  background: radial-gradient(ellipse 64% 64% at 46% 68%,
    rgba(var(--c-teal), 0.5) 0%,
    rgba(var(--c-teal), 0.27) 54%,
    transparent 78%);
  filter: blur(30px);
  pointer-events: none;
}

@media (max-width: 900px) {
  .note-reminders::after { right: -18%; width: 70%; height: 14rem; }
}

/* A large butterfly straddling the boundary into the footer, and a line-art
   sprig down the opposite edge — the two hold the bottom of the page together
   the way the mock does. Both are clipped by main's overflow. */
.spark-bfly {
  right: -7%;
  bottom: -8.5rem;
  width: min(250px, 20%);
  transform: rotate(-14deg);
  /* Deliberately rides over the footer's teal, as in the mock — the two blocks
     read as one page rather than a band butted against a coloured slab. */
  z-index: 3;
}



/* ---------- A note from me ---------- */

/* Third column of the club band: the writing with its polaroid beside it. */
.note {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: clamp(1.2rem, 2.5vw, 2rem);
  align-items: center;
}

.note-leaf {
  right: -12%;
  bottom: 4%;
  width: min(150px, 34%);
  opacity: 0.45;
  transform: rotate(-8deg);
}

@media (max-width: 1150px) {
  .note-leaf { display: none; }
}

/* "Sunday Spark" stays a label; "A Note From Me" becomes a display heading, as
   in the mock — now that the note runs the width of the band, a small uppercase
   label was too quiet to open it. */
.reminders h2 {
  font-size: 1.166rem;
  font-family: var(--font-body);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--teal);
}

.note-copy h2 {
  font-family: var(--font-heading);
  font-size: clamp(1.296rem, 1.782vw, 1.62rem);
  font-weight: 500;
  text-transform: none;
  letter-spacing: 0.01em;
  color: var(--teal);
  margin-bottom: 1rem;
}

.note-copy p { font-size: var(--t-base); line-height: 1.8; margin-bottom: 0.9rem; }

.note .script { font-size: 1.377rem; margin-top: 0.5rem; }

.note .polaroid { width: clamp(120px, 12vw, 165px); }

.polaroid {
  background: var(--white);
  padding: 10px 10px 42px;
  box-shadow: var(--shadow-soft);
  transform: rotate(3deg);
  width: 210px;
}

/* The Remember photo is the anchor of its column rather than a small keepsake
   beside a paragraph, so it fills the column and tips the other way. */
.polaroid-tall {
  width: 100%;
  padding: 12px 12px 46px;
  transform: rotate(-2.5deg);
}

/* One row on a painted band: the sun, then the label with its copy, then the
   signup. The sun used to overlap the heading from a flex box of its own while
   the copy sat in a separate grid row starting further left, so the label and
   the sentence under it never lined up. All three are columns of one grid now. */
.reminders {
  position: relative;
  display: block;

  /* #sunday-spark is a shared link — the Sunday Spark nav item on every inner
     page, and the URL Lauren hands out on Instagram. Landed flush, the Sunday
     Spark heading sits hard against the top edge and reads as clipped. Enough
     room to look placed rather than cut off. */
  scroll-margin-top: 2rem;
}

.spark-copy h2 { margin: 0 0 0.4rem; }

@media (max-width: 860px) {
  .reminders { grid-template-columns: auto minmax(0, 1fr); row-gap: 1.2rem; }
  .reminders .ml-form-embedContainer { grid-column: 1 / -1; }
}

.reminders p { font-size: var(--t-base); line-height: 1.75; margin-bottom: 0; max-width: 30rem; }

.signup-form {
  display: flex;
  gap: 0.6rem;
  flex-wrap: wrap;
  margin-top: 1rem;
}

/* Lauren 2026-08-06: "the forms, lets also make them look more cohesive. change
   the backgrounds to the light teal water color."

   Same treatment the hero band and the Believe/Who-For panels take — a flat
   colour with the baked paper PNG blended over it in soft-light — so the fields
   are washes on a sheet like everything else, not white boxes dropped onto the
   page. The two email forms (home Sunday Spark, club waitlist) were white and
   the club one restated white on top of that; both come through here now.

   --panel-teal, the colour of the Believe / Who-For panels. This went in as the
   paler --aqua-mist first, on the grounds that a field holding typed text wants
   headroom for its placeholder; Lauren asked for it to match "the lighter teal
   boxes that are water colored" instead, so the field is now painted in the same
   colour as those panels and the placeholder is what moved instead — see below.

   Pill radius to match the buttons the fields sit beside — 12px next to a 999px
   submit was the most visible part of what read as incohesive. */
.signup-form input[type="email"] {
  flex: 1 1 200px;
  font-family: var(--font-body);
  font-size: 1.132rem;
  color: var(--charcoal);
  padding: 0.9rem 1.3rem;
  border: 1.5px solid rgba(44, 122, 120, 0.35);
  border-radius: 999px;
  background-color: var(--panel-teal);
  background-image: url("../images/art/paper-wash.png");
  background-size: cover;
  background-position: center;
  background-blend-mode: soft-light;
}

/* The browser default placeholder grey lands at 4.0:1 on the wash, and the field
   went a step darker when it moved from --aqua-mist to --panel-teal, so the
   placeholder had to move with it: --teal-deep measures 4.18:1 on #BBDFDE, which
   is under AA for text this size. --teal-ink is --teal-deep taken down the same
   hue until it clears — 4.8:1. Still unmistakably the field's own teal. */
.signup-form input[type="email"]::placeholder {
  color: var(--teal-ink);
  opacity: 1;
}

.signup-form input[type="email"]:focus {
  outline: none;
  border-color: var(--teal);
}

.ml-form-success-message {
  color: var(--teal);
  line-height: 1.6;
}

.ml-form-success-message strong,
.ml-form-success-message span {
  display: block;
}

.ml-form-success-message strong {
  margin-bottom: 0.2rem;
  font-family: var(--font-heading);
  font-size: 1.296rem;
  font-weight: 600;
}

.reminders .script { display: block; font-size: 1.296rem; margin-top: 1.6rem; }

/* ---------- Footer ---------- */

.site-footer {
  background-color: var(--forest);
  color: rgba(255, 255, 255, 0.85);
  padding: 3.5rem 0 2rem;
  font-size: 1.088rem;
}

/* The footer was the last hard stop on the page — a dark slab butted straight
   against the paper. It takes the same torn top edge as the colour bands via
   .torn-top in the markup; the extra padding keeps the first row of footer
   content clear of the wave's deepest trough.

   Applies to every page from 2026-08-05. It was scoped to .page-home while the
   other two footers were still hard-edged; now that all three carry .torn-top,
   leaving them at the base 3.5rem would put the first row of footer content
   about 14px from the wave's deepest trough.

   Lauren confirmed 2026-08-03 that the footer is right as it is — torn on the
   top edge only. A four-sided version was tried and reverted. */
.site-footer.torn-top { padding-top: 5rem; }

.footer-grid {
  display: grid;
  grid-template-columns: 1.3fr 1fr 1fr;
  gap: 2.5rem;
  align-items: start;
  margin-bottom: 2.5rem;
}

.footer-brand img { height: 40px; width: auto; margin-bottom: 1rem; }

.footer-brand p { max-width: 240px; line-height: 1.6; }

.footer-links ul { list-style: none; }

.footer-links a {
  color: rgba(255, 255, 255, 0.85);
  text-decoration: none;
  display: inline-block;
  padding: 0.25rem 0;
}

.footer-links a:hover { color: var(--gold); }

/* First piece of the bottom-up decoration pass: one white butterfly in the
   footer's bottom-right, sitting under the Sunday Spark column above it. White
   line-art reads only on the coloured sections, and the footer is the darkest
   of them. A child of .site-footer, so the torn top edge crops it — it sits
   well inside, in the gap between the social icons and the copyright rule. */
.footer-bfly {
  right: 5%;
  top: 165px;
  width: 92px;
  opacity: 0.78;
  transform: rotate(-12deg);
}

.footer-connect { text-align: center; }

.footer-connect h3 {
  color: var(--white);
  font-family: var(--font-body);
  font-size: 0.999rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  font-weight: 500;
  margin-bottom: 1rem;
}

.social-icons { display: flex; justify-content: center; gap: 1rem; }

.social-icons a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border: 1px solid rgba(255, 255, 255, 0.4);
  border-radius: 50%;
  transition: border-color 0.2s ease, background-color 0.2s ease;
}

.social-icons a:hover { border-color: var(--gold); background: rgba(255, 255, 255, 0.08); }

.social-icons svg { width: 17px; height: 17px; fill: rgba(255, 255, 255, 0.9); }

.footer-bottom {
  border-top: 1px solid rgba(255, 255, 255, 0.15);
  padding-top: 1.4rem;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 1rem;
  font-size: 0.977rem;
  color: rgba(255, 255, 255, 0.6);
}

.footer-bottom a { color: rgba(255, 255, 255, 0.6); text-decoration: none; }
.footer-bottom a:hover { color: var(--gold); }

.footer-copyright {
  max-width: 700px;
  line-height: 1.6;
}

.footer-copyright p + p { margin-top: 0.45rem; }

/* ==========================================================================
   Policies page
   ========================================================================== */

/* Policies AND the Wellness Notice / Participant Agreement — both pages use this
   one rule. Lauren 2026-08-06: "the wellness waiver and policies pages, please
   make the backgrounds of those the lighter watercolor teal."

   Was a --cream ground under blue and lavender pools. Now the same construction
   the hero band and the Believe/Who-For panels use: a flat colour with the baked
   paper PNG blended over it in soft-light, so it is a wash on a sheet rather
   than a flat fill.

   --panel-teal, corrected the same day. This first went in as --aqua-mist and
   Lauren pulled it back: "i want the teal to match the colors we have on the
   web site already. the lighter teal boxes that are water colored." Those boxes
   are the Believe / Who-For panels, and --panel-teal IS their colour, so this
   page is now painted in a colour the site already owns rather than in a paler
   neighbour of it. The email fields moved with it.

   The blue and lavender pools are gone — they were tinting a cream ground and on
   teal they just muddied it. What is left is one white pool and one teal pool of
   the SAME hue as the base, which is what keeps the field moving without
   introducing a second colour.

   The card on top is rgba(255,255,255,0.92) and reads as a white sheet laid on
   the wash; body copy sits on the card, not on the teal, so nothing here changes
   the reading contrast of the legal text. */
.policies-main {
  padding: 9rem 0 6rem;
  background:
    url("../images/art/paper-wash.png"),
    radial-gradient(ellipse 48% 44% at 5% 10%, rgba(255, 255, 255, 0.55), transparent 72%),
    radial-gradient(ellipse 50% 40% at 22% 82%, rgba(var(--c-teal), 0.18), transparent 72%),
    var(--panel-teal);
  background-size: cover, auto, auto, auto;
  background-position: center, 0 0, 0 0, 0 0;
  background-blend-mode: soft-light, normal, normal, normal;
}

.policies-wrap { max-width: 940px; }

.policies-header {
  text-align: center;
  margin-bottom: 2.5rem;
}

.policies-header .eyebrow { margin-bottom: 0.55rem; }

.policies-header h1 {
  color: var(--forest);
  font-size: clamp(2.43rem, 5.67vw, 3.888rem);
  margin-bottom: 0.6rem;
}

.policies-header h1.agreement-title {
  max-width: 900px;
  margin-left: auto;
  margin-right: auto;
  font-size: clamp(2.025rem, 4.86vw, 3.402rem);
  line-height: 1.08;
}

.policies-updated {
  color: var(--teal);
  font-size: 1.054rem;
}

.policies-card {
  background: rgba(255, 255, 255, 0.92);
  border: 1px solid rgba(44, 122, 120, 0.12);
  border-radius: calc(var(--radius) + 4px);
  box-shadow: var(--shadow-soft);
  padding: clamp(2rem, 6vw, 4.5rem);
}

.policy-section + .policy-section {
  border-top: 1px solid rgba(44, 122, 120, 0.16);
  margin-top: 2.5rem;
  padding-top: 2.5rem;
}

.policy-section h2 {
  color: var(--teal);
  font-size: clamp(1.458rem, 3.24vw, 1.904rem);
  margin-bottom: 1rem;
}

.policy-section p {
  line-height: 1.85;
  margin-bottom: 1rem;
}

.policy-section p:last-child { margin-bottom: 0; }

.footer-policy-links {
  max-width: 360px;
  text-align: right;
  line-height: 1.65;
}

.contact-main { min-height: 72vh; }

/* The two ways off thank-you.html. Flex with a real gap rather than inline-block
   pills: side by side they were separated only by the whitespace between the
   tags, which measured 5px and read as one wide button. `wrap` because the
   second label is long — on a narrow phone they stack instead of overflowing. */
.thanks-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.9rem;
  margin-top: 2.2rem;
}

.contact-wrap { max-width: 820px; }

.contact-card {
  text-align: center;
  padding-top: clamp(2.5rem, 7vw, 4.5rem);
  padding-bottom: clamp(2.5rem, 7vw, 4.5rem);
}

.contact-question {
  color: var(--forest);
  font-family: var(--font-heading);
  font-size: clamp(1.458rem, 3.24vw, 2.025rem);
  line-height: 1.25;
  margin-bottom: 0.8rem;
}

.contact-welcome {
  color: var(--teal);
  font-size: 1.221rem;
  margin-bottom: 2.6rem;
}

/* The .contact-email-block rules that were here styled the published mailto:
   address and went with it on 2026-08-06. What follows is the form that
   replaced it. It keeps that block's border-top, so the page's rhythm below the
   welcome lines is unchanged. */

/* Off-screen rather than display:none — the honeypot has to be a field a bot can
   find and fill, which is the whole trick, and display:none is the first thing a
   half-decent bot checks for. Also the correct way to hide a label from sight
   without hiding it from a screen reader, so it is written as a general helper
   rather than as something private to the contact form. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.contact-form {
  border-top: 1px solid rgba(44, 122, 120, 0.16);
  padding-top: 2.3rem;
}

.contact-form h2 {
  color: var(--teal);
  font-size: 1.256rem;
  margin-bottom: 1.4rem;
}

.contact-form .field { margin-bottom: 1.15rem; }

/* Real labels above the fields, not placeholders standing in for them. A
   placeholder disappears the moment someone starts typing, which is exactly
   when they most need to know which box they are in. */
.contact-form label {
  display: block;
  margin-bottom: 0.4rem;
  font-family: var(--font-body);
  font-size: 0.94rem;
  font-weight: var(--fw-ui);
  letter-spacing: 0.04em;
  color: var(--teal-label);
}

/* "(optional)" inside a label, first used on the 1:1 interest form. It sits IN
   the label rather than beside the field so a screen reader reads it as part of
   the question — a visitor who cannot see the lighter grey still hears which
   boxes they can skip. Weight and colour drop away from --teal-label so it
   reads as an aside without becoming unreadable: it is still the same family
   and size as the label it sits in. */
/* ---------- Tick box + its label, first used on the 1:1 form ----------
   Grid rather than flex, so a label that wraps to two lines stays aligned under
   itself instead of running back under the box. `start` on the box so it sits
   with the FIRST line of the label rather than centring against the block.

   1.05rem square: the site's fields are generous and a default 13px checkbox
   beside them looks like a mistake. `accent-color` tints the checked state to
   the brand teal in one line, which is all this needs — a fully custom control
   here would mean rebuilding focus and keyboard states that the native one
   already has right.

   The label is NOT the small-print colour the consent line below it takes. It
   is a choice the visitor is making, so it reads at body strength. */
.contact-form .field-check {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.6rem;
  align-items: start;
  margin-bottom: 1rem;
}

.contact-form .field-check input[type="checkbox"] {
  width: 1.05rem;
  height: 1.05rem;
  margin: 0.15rem 0 0;
  accent-color: var(--teal);
  cursor: pointer;
}

.contact-form .field-check label {
  margin: 0;
  font-size: 0.94rem;
  font-weight: 400;
  line-height: 1.5;
  letter-spacing: 0.01em;
  color: var(--navy);
  cursor: pointer;
}

/* The consent line above the submit button on the 1:1 form. Small print, but
   NOT --t-sm and not grey-on-grey: it is the sentence that tells someone what
   happens to their address, and the one place on a form where quiet type is a
   dark pattern rather than a style. Sized and coloured to the same #5C7178 the
   "(optional)" hint uses — 5.14:1 on the card — and given real air above the
   button so it reads as part of the decision rather than as filler. */
.contact-form .field-consent {
  margin: 0 0 1rem;
  font-family: var(--font-body);
  font-size: 0.9rem;
  line-height: 1.55;
  color: #5C7178;
}

.contact-form .field-optional {
  font-weight: 400;
  letter-spacing: 0.02em;
  /* #5C7178, MEASURED. The first value tried was #6b8087, which reads as the
     obvious "muted grey" and fails: 4.15:1 on the card's near-white, under the
     4.5 AA needs at this size — and 15px is normal text, not large, so the
     3:1 allowance does not apply. This is the same slate taken down two steps,
     5.14:1, which clears with room. There is no --muted token on this site;
     don't invent one here without checking it on the panels too. */
  color: #5C7178;
}

/* Same wash as the Sunday Spark and waitlist fields — --panel-teal under the
   baked paper in soft-light — so every input on the site is the same object.
   See `.signup-form input[type="email"]` for the reasoning behind the colour. */
.contact-form input[type="text"],
.contact-form input[type="email"],
.contact-form textarea {
  display: block;
  width: 100%;
  font-family: var(--font-body);
  font-size: 1.06rem;
  color: var(--charcoal);
  padding: 0.85rem 1.3rem;
  border: 1.5px solid rgba(44, 122, 120, 0.35);
  background-color: var(--panel-teal);
  background-image: url("../images/art/paper-wash.png");
  background-size: cover;
  background-position: center;
  background-blend-mode: soft-light;
}

/* Pills for the single-line fields, to match the buttons and the email inputs.
   NOT for the textarea — a 999px radius on a six-row box bows its sides into an
   oval and eats the top and bottom corners of the text. It takes a rounded
   rectangle instead, sized off --radius so it still belongs to the same family. */
.contact-form input[type="text"],
.contact-form input[type="email"] { border-radius: 999px; }

.contact-form textarea {
  border-radius: calc(var(--radius) + 6px);
  resize: vertical;
  min-height: 9rem;
  line-height: 1.6;
}

.contact-form input:focus,
.contact-form textarea:focus {
  outline: none;
  border-color: var(--teal);
}

.contact-form button { margin-top: 0.5rem; }

.contact-form .contact-response {
  margin-top: 1.1rem;
  color: rgba(74, 74, 74, 0.78);
}

/* Shown only when Formspree refuses a submission — see js/contact-form.js.
   Deliberately not red: nothing on this site is, and a warning colour on a page
   whose whole job is to feel welcoming would be the loudest thing on it. This is
   the site's own deep teal at a weight that still reads as "stop and look",
   and it clears AA on the card at 5.9:1. `[hidden]` needs asserting because the
   base stylesheet gives <p> a display that would otherwise beat it. */
.contact-form .contact-error {
  margin-top: 1.1rem;
  font-weight: var(--fw-ui);
  color: var(--teal-deep);
}

.contact-form .contact-error[hidden] { display: none; }

@media (max-width: 760px) {
  .policies-main { padding: 7.5rem 0 4rem; }
  .policies-card { border-radius: var(--radius); }
  .footer-policy-links { max-width: none; text-align: left; }
}

/* ==========================================================================
   Self-Love Club page
   ========================================================================== */

.club-hero {
  position: relative;
  padding: 10rem 0 5rem;
  text-align: center;
  background:
    radial-gradient(ellipse 52% 58% at 12% 20%, rgba(var(--c-blue), 0.4), transparent 72%),
    radial-gradient(ellipse 48% 55% at 88% 24%, rgba(var(--c-lav), 0.38), transparent 72%),
    radial-gradient(ellipse 55% 45% at 50% 104%, rgba(var(--c-teal), 0.16), transparent 70%),
    var(--cream);
  overflow: hidden;
}

.club-hero h1 { font-size: clamp(2.268rem, 4.86vw, 3.645rem); margin-bottom: 0.5rem; }

.club-hero .script { display: block; margin-bottom: 1.6rem; }

.club-hero p.lead { max-width: 40rem; margin: 0 auto 2.4rem; }

/* inside the club */

.club-inside { padding: 5.5rem 0; background: var(--white); text-align: center; }

.club-inside > .wrap > p {
  max-width: 42rem;
  margin: 1.2rem auto 3.5rem;
}

.inside-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 2rem;
  text-align: center;
}

.inside-card {
  background: var(--cream);
  border-radius: var(--radius);
  padding: 2.2rem 1.6rem;
  box-shadow: 0 6px 22px rgba(31, 94, 92, 0.06);
}

.inside-card img { width: 92px; height: 92px; object-fit: contain; margin: 0 auto 1.1rem; }

.inside-card h3 { font-size: 1.013rem; font-weight: 600; margin-bottom: 0.6rem; }

.inside-card p { font-size: 0.999rem; line-height: 1.7; }

/* how it works */

.club-how {
  padding: 5.5rem 0;
  background:
    radial-gradient(ellipse 50% 70% at 100% 20%, rgba(var(--c-blue), 0.5), transparent 72%),
    var(--cream);
  text-align: center;
}

.how-steps {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2.5rem;
  margin-top: 3rem;
}

.how-step .step-num {
  font-family: var(--font-heading);
  font-size: 2.106rem;
  color: var(--teal);
  display: block;
  margin-bottom: 0.6rem;
}

.how-step h3 { margin-bottom: 0.6rem; font-weight: 600; }

.how-step p { font-size: 1.054rem; }

/* pillars strip */

.club-pillars {
  padding: 4.5rem 0;
  background: var(--white);
  text-align: center;
}

.pillar-strip {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 2.5rem;
  margin-top: 2.5rem;
}

.pillar-strip figure { width: 120px; }

.pillar-strip img { width: 86px; height: 86px; object-fit: contain; margin: 0 auto 0.6rem; }

.pillar-strip figcaption { font-size: 0.944rem; color: var(--forest); }

/* join card */

/* The two blurred pseudo-element "glows" behind this card are gone. They were a
   1040x640 ellipse under blur(34px), which is the dead end the wash system
   documents: blur a gradient hard enough to lose its edge and it fills its box
   evenly, so what reads on the page is a soft rectangle of dark teal, not a
   wash. The card carries its own torn edge now and needs nothing behind it. */
/* Padding-bottom cut from var(--section) so the FAQ card sits close under this
   one — the sign-up and "You Might Be Wondering" read as a single unit rather
   than two sections a full gap apart. The other half is .club-faq's padding-top;
   between them the card-to-card gap went 144px to ~48. */
.club-join {
  position: relative;
  padding: var(--section) 0 1.5rem;
}

/* z-index 2, NOT 1, since 2026-08-26 — and this is what makes the sage sprig's
   crossover work rather than a value anyone should tidy back down.

   `.club-faq .wrap` also carries z-index 1 and comes LATER in the document, so at
   equal z-index it won. The sage half of `.join-side-*` lives in that wrap, which
   meant it painted OVER this card: the leaves that crossed onto the teal stayed
   sage, and the white copy inside the card sat underneath them, invisible. Lauren
   saw exactly that — "its not showing up white" — twice.

   Raising this wrap above the FAQ's puts the card back on top, which is the whole
   mechanism of a crossover here: the card hides the sage where the teal is, and
   the white child of the card shows there instead. Nothing else on the page
   overlaps this section, so the bump costs nothing. */
.club-join .wrap { position: relative; z-index: 2; }

/* Torn on all four sides, like the home page's club card — which is the same
   offer, so the two should look like the same object. Uses the club-specific
   tear (torn-paper-club.svg) rather than one of the a/b/c panel masks, so it
   doesn't repeat a tear used elsewhere on this page.
   `border-radius` came off with the mask: a mask and a radius fight, and the
   radius was giving it the rounded-app-card look the torn paper replaces. A
   box-shadow goes too — it follows the element box and would be sheared off
   square across the torn corners. */
.join-card {
  position: relative;
  max-width: 720px;
  margin: 0 auto;
  background-image:
    url("../images/art/paper-wash.png"),
    radial-gradient(ellipse 60% 55% at 88% 8%, rgba(var(--c-blue), 0.22), transparent 66%),
    radial-gradient(ellipse 55% 60% at 6% 94%, rgba(var(--c-lav), 0.20), transparent 70%),
    linear-gradient(158deg, #2A7A78 0%, #1C6469 100%);
  background-size: cover, auto, auto, auto;
  background-position: center, 0 0, 0 0, 0 0;
  background-blend-mode: soft-light, normal, normal, normal;
  -webkit-mask: url("../images/art/torn-paper-club.svg") center / 100% 100% no-repeat;
          mask: url("../images/art/torn-paper-club.svg") center / 100% 100% no-repeat;
  /* Generous padding because the tear bites inward on every side. */
  padding: 4.2rem clamp(2.4rem, 5vw, 4.4rem);
  text-align: center;
}

/* Dark card text — matched to the club hero */
.join-card h2 { color: var(--cream); }
.join-card .script { color: var(--seafoam); }
.join-card .club-price { color: var(--cream); }
.join-card .club-price span { color: rgba(248, 245, 239, 0.75); }
/* Teal like the other three club CTAs, but the PALE teal with a navy label —
   this is the only one sitting on the deep teal card, and --teal on that measures
   1.7:1, i.e. the button would disappear into its own panel. --panel-teal gives
   4.8:1 against the card and 9.7:1 on the label, and still reads as the teal
   Lauren asked for rather than a fifth colour. */
.join-card .btn-primary {
  background: var(--panel-teal);
  color: var(--navy);
  border-color: var(--panel-teal);
}
/* --seafoam was LIGHTER than the --panel-teal rest state. Same token as the hero
   secondary now, so the two --panel-teal buttons press identically. */
.join-card .btn-primary:hover {
  background: var(--panel-teal-deep);
  border-color: var(--panel-teal-deep);
}

/* ---------- The 1:1 card's single button, 2026-08-24 ----------
   This card asks people to go and fill in a form rather than to hand over an
   email address, so where the Club's card has `.waitlist-form` (a field and a
   button on one row) this has one control on its own line.

   The margin matches `.waitlist-form`'s 1rem top so the two cards still open
   the same distance under their last paragraph — they are meant to read as the
   same object, and this is the one place they now differ.

   The `aria-disabled` state this carried for one revision is gone with the
   placeholder href — the button points at one-on-one-form.html now. */
/* The butterfly that replaced the heart in "Interested in 1:1 Sessions?".
   2026-08-25.

   SIZED IN em, NOT px, AND BY HEIGHT RATHER THAN WIDTH. The heading is
   clamp()-ed, so a px size would drift out of proportion with the type at every
   width; em keeps the mark at a fixed fraction of the line. Height rather than
   width because the drawing is a PORTRAIT side view (400x520) — set a width and its
   height follows the aspect, which is what pushes a line box taller and opens a gap
   above the heading.

   0.85em against the 1em the heart glyph occupied: "make it smaller" was part of the
   ask, and a painted butterfly carries far more visual weight than an outline heart
   at the same size. It renders 34px tall at the desktop heading's 40.4px.

   NO `.deco` CLASS, which is the trap here — `.deco` is position:absolute, and this
   is the one butterfly on the site that has to stay in the text flow. */
.oto-join-bfly {
  /* THE SITE'S RESET IS `img { display: block }`, and that is what this rule most
     needs to undo. Left alone, the butterfly became a block box: it took a line of
     its own below the heading, and because text-align does not centre a block child
     it sat flush left with only its own margin holding it off the edge. It looked
     like a wrapping problem — the heading had 77px of room to spare, so it was not
     one. Anything inline added to a heading on this site has to say so explicitly. */
  display: inline-block;
  /* 0.85em -> 2.2em. Lauren: "way too small i just meant smaller than its
     original." 0.85em matched the HEART it replaced, which was the wrong reference
     — the heart is an outline glyph and this is a painted drawing, and at 34px the
     wash read as a coloured smudge rather than as a butterfly. The reference is the
     asset's own 400x520; 2.2em renders it 89px tall, about a sixth of that.

     IT IS NOW TALLER THAN THE LINE IT SITS ON, which is the whole reason for the
     negative block margins below. */
  height: 2.2em;
  width: auto;
  /* RAISED ABOVE THE BASELINE, not hung below it. At -0.75em the drawing straddled
     the heading but its lower wing painted 32px into "I'll be opening just a few
     spots…" — measured, not eyeballed; the bounding box alone would have missed it
     since the wing is the only thing that far down.

     0.2em centred it on the heading's line, which STILL left 22 painted pixels on
     that paragraph — checked by compositing the drawing to a canvas and testing its
     alpha against the text's own client rects, because at this size the box
     overstates the wing by only a pixel and the real answer was not obvious either
     way. 0.92em lifts it 29px clear: painted top y4437 against a card top of y4413,
     painted bottom y4525 against the paragraph at y4533.

     THE DRAWING IS TALLER THAN THE LINE IT SITS ON, so it has to spend that
     difference somewhere — up into the card's top padding, or down onto the copy.
     Up is the only side with room. */
  vertical-align: 0.92em;
  /* The space that used to be a literal space before the glyph. In em so it tracks
     the type; a word space here would break to a new line on its own. */
  margin-left: 0.22em;
  /* THE LINE BOX MEASURES AN INLINE-BLOCK BY ITS MARGIN BOX, so negative block
     margins let an 89px drawing sit in a 46px line without opening a gap above the
     heading or shoving the paragraph below it down. Without these the card grows by
     ~40px and the heading stops looking centred in its own space. */
  margin-block: -1.15em;
  /* MIRRORED TO FACE LEFT, 2026-08-25 — Lauren: "and turn it so its facing the
     left." The drawing is exported facing RIGHT: head, antennae and legs are all on
     the right-hand side, with the wings sweeping back to the left. Facing right it
     pointed away off the end of the line; mirrored it looks back along the heading
     it sits after.

     scaleX, NOT a rotation. This is a side view, so a rotation would tip the
     butterfly nose-down or nose-up rather than turn it around — only a mirror swaps
     which way it faces. Nothing else here is transformed, so no order question
     arises. */
  transform: scaleX(-1);
}

/* THE LIFT IS A ONE-LINE-HEADING ASSUMPTION, and on a phone the heading is two
   lines. `vertical-align: 0.92em` raises the drawing 29px above its own line's
   baseline, which is clear air when there is nothing above it and is the tail of
   "Interested in 1:1" when the heading has wrapped. Measured at 390: the butterfly
   painted from y6224 while line one's ink runs to about y6248 in exactly its x
   range, so it sat squarely on top of "1:1" — the only decoration on this page that
   lands on a heading, and the most legible-copy damage anywhere on it.

   SO ON A PHONE IT HANGS INSTEAD OF LIFTING. Dropped to the baseline the drawing
   spends its extra height downward, into the gap under the heading rather than into
   the line above it. That is the same "up is the only side with room" reasoning as
   the desktop rule, run the other way, because on a phone up is the side without
   room.

   AND THE GAP HAS TO BE MADE. The heading's own margin-bottom is 0.4rem — 6px — so
   there is nothing under it to hang into, and this is the one place on the page
   where a piece of decoration asks the layout for something. It is also better type
   either way: a 30px heading sitting 6px off its paragraph is tight on any phone,
   and the desktop heading only gets away with it because its butterfly is lifted
   clear.

   RE-MEASURE BOTH NUMBERS TOGETHER if either changes. The clearance below is
   6px — painted butterfly to paragraph ink — so the margin and the drawing's
   height are one setting, not two. */
@media (max-width: 760px) {
  /* `.oto-interest .join-card h2`, NOT `.oto-interest h2`. `.join-card h2` sets
     margin-bottom: 0.4rem further down this file at equal specificity, so the
     shorter selector loses to it on source order and the rule silently did
     nothing — the butterfly still painted 327px into the paragraph. */
  .oto-interest .join-card h2 { margin-bottom: 1.75rem; }
  .oto-join-bfly {
    /* 1.8em against the desktop 2.2 — a step down, not a return to the 0.85em
       Lauren rejected ("way too small i just meant smaller than its original"). The
       heading is 30px here against 40px at 1280, so this renders 54px against 89 and
       the drawing keeps its relationship to the type. */
    height: 1.8em;
    /* Barely off the baseline. Anything more positive puts the wing tip back into
       the line above; anything negative reaches the paragraph. */
    vertical-align: 0.05em;
  }
}

.oto-interest-cta { margin: 1rem 0 0; }

.join-card .waitlist-form {
  justify-content: center;
  max-width: 610px;
  margin: 1rem auto 0;
}

/* The white override is gone — the club field takes the same teal wash as the
   home one, which is the whole point of the cohesion pass. Left as a marker so
   nobody re-adds it: the club form is NOT meant to differ from Sunday Spark. */

.join-card .ml-form-success-message {
  margin-top: 1rem;
  color: var(--cream);
}

.join-card h2 { margin-bottom: 0.4rem; }

.join-card .script { display: block; margin-bottom: 1rem; }

.join-card .join-note {
  max-width: 480px;
  margin: 0 auto 1.8rem;
  color: rgba(248, 245, 239, 0.9);
}

.club-price {
  font-family: var(--font-heading);
  font-size: 2.43rem;
  line-height: 1;
  color: var(--teal);
  margin-bottom: 1.8rem;
}

.club-price span {
  font-family: var(--font-body);
  font-size: 1.11rem;
  color: rgba(74, 74, 74, 0.75);
}

.join-list {
  list-style: none;
  text-align: left;
  max-width: 420px;
  margin: 0 auto 2.4rem;
}

.join-list li {
  position: relative;
  padding-left: 2rem;
  margin-bottom: 0.85rem;
  font-size: 1.088rem;
}

/* DORMANT — the join card's list is inside an SLC-LAUNCH comment. Filled and on
   the same `--heart` property as every other list, so it matches whenever the
   launch copy comes back; the fallback stays --teal because this list sits on
   the deep teal card, where both --blob-* inks would disappear. */
.join-list li::before {
  content: "\2665";
  position: absolute;
  left: 0;
  color: var(--heart, var(--teal));
  font-size: 0.92em;
}

.join-card .small-print {
  font-size: 0.944rem;
  color: rgba(248, 245, 239, 0.72);
  margin-top: 1.2rem;
}

/* quote band */

/* WAS BARE PAPER until 2026-08-24 — "the page's breath between the blue scrap
   above and the teal card below". Lauren asked for a butterfly photograph behind
   it, the same treatment .home-joy and .oto-do carry.

   THE PHOTOGRAPH is images/club-quote-bg.webp — a monarch on a pink zinnia,
   1600x787 off `monarch on flower.JPG` in the repo root, cropped y520-1016 of
   that source so the whole butterfly is held rather than clipped at the wing.
   Lauren dropped the photo in and picked it over the first attempt.

   A TIGER SWALLOWTAIL ON MAUVE JOE-PYE was here first, cropped off the 4284x5712
   `yellow bfly flower.JPG` at y2214-4356. If it is ever wanted back, that is the
   whole recipe: full width, 2:1, resize to 2400x1200, brightness 0.86, q74.

   THE SOURCE IS SMALL — 1008x1792, against 2400-wide assets everywhere else on
   the site. It is written out at 1600 so it is DOWNSCALED at a 1280 band rather
   than stretched, which is why it holds up; past about 1600px of viewport it
   starts upscaling and will soften. 62KB, so there is no weight argument for
   going smaller — the ceiling here is the source, not the file. Pre-darkened to
   0.88 in the asset; the rest of the darkening is in the gradient below.

   Same construction as the other two: full-bleed, torn top and bottom, a BELL
   scrim rather than a flat one so there is no horizontal edge for the eye to
   catch. See .home-joy-card for why a plateau or a radial both failed there. */
.club-quote {
  position: relative;
  /* DEEP, and the depth is set by the photograph rather than by the copy — "id
     like to make this section bigger with the photo as well, wider than it is".

     At 1280 this picture covers to 640px tall, so a band of ~630 shows very
     nearly all of it. The band was 373px when the photo went in, which showed
     only 58% — a letterbox slot through the middle of the wings. Stepping the
     padding: +2/+1rem gave 373 (58%), +5/+4 gave 469 (73%), +8/+7 gave 565
     (88%), and this gives 629 (98%).

     DO NOT GO PAST THIS. Beyond ~640 the band is taller than the photograph's
     cover height, so `cover` scales the image UP to fill it and crops the SIDES
     instead — which trims the wingtips, the one thing this crop was chosen for.
     +11/+10rem already measured 103%. */
  padding:
    calc(var(--section) + var(--wave-h) + 10rem) 0
    calc(var(--section) + var(--wave-h) + 9rem);
  text-align: center;
  /* `clip`, NOT `hidden`, and it is load-bearing for the phone pinning below.
     `overflow: hidden` makes an element a SCROLL CONTAINER — a scrollport that
     cannot actually be scrolled — and `animation-timeline: view()` resolves
     against the subject's nearest ancestor scroll container. With `hidden` here
     the timeline sat frozen and the picture tracked the band instead of the
     window, which looks exactly like the effect simply not being applied.
     Measured before the fix: the picture's top stayed a constant 116px from the
     band's top at every scroll position. `clip` clips identically and creates no
     scroll container. See the same note on `.home-joy`. */
  overflow: hidden;
  overflow: clip;
  /* MEASURED against the real composite, worst pixel under the two script lines.
     This band is the easiest of the three photo bands to light, because the copy
     is only two centred lines occupying 40-64% of its height — there is room to
     be generous with the picture:

       0.34 -> 0.60   4.96:1   49% of the photograph
       0.24 -> 0.48   3.63:1   61%      <- here
       0.20 -> 0.42   3.14:1   67%
       0.16 -> 0.36   2.73:1   72%      fails

     Re-measured against the monarch when it replaced the swallowtail: the same
     stops come back 3.78:1 at the same 61%, so nothing needed retuning. Deeper
     was checked anyway — 0.28->0.56 gives 4.61 at 55%, 0.30->0.62 gives 5.39 at
     50% — and neither is worth six to eleven points of photograph here.

     The script is 33.7px, so it counts as large text and needs 3.0 rather than
     4.5. 3.14 clears that on paper and is not taken: Courgette is a thin
     single-weight face, and a ratio a tenth above the floor is not the place to
     put one. 3.63 keeps a real margin and still returns 12 points of photograph
     over the first attempt.

     Every stop is on a curve — max slope 0.73, against the 6.0 that a
     hold-the-edge-light ramp needed on About. No plateau, no edge. */
  background:
    linear-gradient(180deg,
      rgba(46, 30, 58, 0.24) 0%,
      rgba(46, 30, 58, 0.40) 22%,
      rgba(46, 30, 58, 0.48) 45%,
      rgba(46, 30, 58, 0.48) 62%,
      rgba(46, 30, 58, 0.36) 82%,
      rgba(46, 30, 58, 0.24) 100%),
    url("../images/club-quote-bg.webp") center 50% / cover no-repeat;
}

/* ---------- The same pinned-photograph effect as .home-joy and .about-thankyou,
     2026-08-25 ---------- Lauren asked for it here and on .oto-hero after seeing
   it on the other two: the picture holds still and the band scrolls over it.

   THE PHOTOGRAPH IS RE-CUT FOR IT, because `fixed` sizes the background to the
   VIEWPORT rather than to the band — and the long note above is explicit that
   this crop must not be made to fill a box taller than about 640px, or `cover`
   scales it up and trims the wingtips. A 900px-tall window would have done
   exactly that. images/club-quote-bg-wide.webp is the same frame at the same
   centre, opened out to a window's shape so nothing has to be scaled up:

     monarch on flower.JPG  ->  crop (0, 413, 1008, 1123)   1008x710, aspect 1.42
                            ->  resize 1600x1127            the same 1.587x the
                                                            shipped file uses
                            ->  brightness 0.8762           fitted, not guessed
                            ->  WEBP quality 76             77KB

   The shipped 1600x787 is crop y520-1016 of the same source at the same
   brightness, so this is that crop with 107 rows added above and below. 100% of
   its width survives `cover` in a 1280x900 window, which is what the old note
   was protecting.

   THE WASH GOES UP ONLY 10%. Measured over the whole pass — every position the
   band takes as it crosses the window — the copy comes back 3.46:1 at the
   existing depth, which clears the 3.0 this 33.7px script needs but sits under
   the 3.63 the note above settled on as a real margin for a thin single-weight
   face. x1.1 gives 3.92 for four points of photograph:

     as it is    3.46   61% of the photograph
     x1.1        3.92   57%   <- here
     x1.2        4.44   53%
     x1.35       5.42   47%

   This band pays the least of the four, and the reason is in the old note: the
   copy is two centred lines over grass rather than over the butterfly.

   POINTER-GATED, as everywhere else — see the long note at `.home-joy::before`.
   Touch devices keep the shipped crop and its original wash at every width. */
@media (min-width: 761px) and (hover: hover) and (pointer: fine) {
  /* A FIXED LAYER, NOT A FIXED BACKGROUND — 2026-08-26, the same swap as
     `.home-joy::before`; the reasoning lives there in full. Short version:
     `background-attachment: fixed` repaints on the main thread every frame and
     lags the copy moving over it, which is the shakiness Lauren reported; a
     `position: fixed` box has identical geometry and the compositor simply does
     not move it. `clip-path` is what holds it inside the band — `overflow: clip`
     cannot clip a fixed descendant — and it must not be a transform or a filter,
     which would make the section a containing block and un-fix the layer.

     THE SCRIM HAD TO COME OFF THE SECTION with it. It was the first layer of the
     same `background` shorthand, which is what guaranteed it painted above the
     picture; a pseudo-element always paints above its element's own background,
     so once the picture is a pseudo the scrim cannot stay where it was. It moves
     to ::after at the band's size — the shape is byte-for-byte the gradient that
     was measured for this band, only its host changed. */
  .club-quote {
    clip-path: inset(0);
    background-image: none;
  }

  .club-quote::before {
    content: "";
    position: fixed;
    inset: 0;
    z-index: 0;
    background: url("../images/club-quote-bg-wide.webp") center 50% / cover no-repeat;
  }

  .club-quote::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    background:
      linear-gradient(180deg,
        rgba(46, 30, 58, 0.26) 0%,
        rgba(46, 30, 58, 0.44) 22%,
        rgba(46, 30, 58, 0.53) 45%,
        rgba(46, 30, 58, 0.53) 62%,
        rgba(46, 30, 58, 0.40) 82%,
        rgba(46, 30, 58, 0.26) 100%);
  }
}

/* OFF THE CENTRE LINE, 2026-08-24. Every section on this page was full-bleed,
   centred and near enough the same measure, which is what made the layout read as
   a stack of horizontal stripes — measured: 7 of 7 full-bleed, 6 of 7 centred,
   five of them within 1080-1203px of each other. This block and the FAQ card
   below now pull opposite ways so the eye moves laterally down the page instead
   of tracking one centre line.

   RIGHT rather than left, and the photograph decided that rather than taste. The
   monarch and the pink zinnia occupy the left and centre of the crop, so sampling
   the real composite across the copy's own rows, a 560px block measures 3.39:1 on
   the left, 3.39 centred and 3.74 on the right — moving the words off the
   butterfly and onto the grass. It is the rare change that buys asymmetry and
   contrast at the same time.

   The block is capped and pushed with `margin-left: auto` rather than being
   right-ALIGNED: the two lines still read centred against each other, which keeps
   the handwritten note feeling like a note. */
.club-quote .wrap { max-width: 34rem; margin-left: auto; margin-right: 6%; }

/* Reversed out for the photograph. The scrim is plum rather than the teal the
   other two bands use: it was chosen against the mauve joe-pye that was here
   first, and it still suits the monarch's pink zinnia better than teal would. */
.club-quote .script.accent {
  color: var(--cream);
  text-shadow:
    0 1px 2px rgba(38, 22, 48, 0.55),
    0 2px 16px rgba(38, 22, 48, 0.38);
}

/* NOTE: this band holds no decoration at all now. The sketch butterfly and its
   dotted trail (.quote-you-bfly / .quote-you-path) were knocked to white to
   survive the photograph and then removed outright on 2026-08-24 — the picture
   is the feature here. If art is ever put back on this band it must be WHITE, or
   knocked to white, for the reason recorded throughout this file: coloured line
   art on a photograph disappears. */

.club-quote .wrap { position: relative; z-index: 1; }
.club-quote .script { font-size: clamp(1.539rem, 2.835vw, 2.106rem); display: block; }

/* Large faded butterfly sitting behind the quote */
.club-quote .quote-butterfly {
  position: absolute;
  left: 50%;
  top: 60%;
  transform: translate(-50%, -50%);
  width: min(360px, 60%);
  opacity: 0.28;
  z-index: 0;
  pointer-events: none;
  -webkit-mask-image: radial-gradient(ellipse 80% 80% at 50% 45%, #000 58%, transparent 82%);
          mask-image: radial-gradient(ellipse 80% 80% at 50% 45%, #000 58%, transparent 82%);
}

/* A few questions — FAQ near the bottom of the club page.
   Its own ground and both blurred pseudo-element splashes are gone, for the same
   reason as the join card's: a blurred gradient ellipse cannot read as a wash,
   only as a soft rectangle. Bare paper. */
/* Padding-top cut from var(--section) so this card sits close under the join
   card rather than a full section away — the two are one unit now. The other
   half of the gap is .club-join's padding-bottom. 144px between the cards became
   ~48. */
.club-faq {
  position: relative;
  padding: 1.5rem 0 var(--section);
}
.club-faq .wrap { position: relative; z-index: 1; }

/* The questions sit on their own torn watercolour scrap, per Lauren
   2026-08-05 — "let's make the faq a ripped watercolour background as well".
   BLUE since later the same day: she swapped this and the "Is This For You?"
   panel, which had the blue. The two are still different colours from each other
   and from the join card, which is the point — just the other way round.
   Contrast was unaffected by the swap: --panel-blue and --panel-teal were tuned
   to sit at the same luminance (0.634 against 0.636), so nothing on either scrap
   needed re-checking.

   Generous padding because the tear bites inward on all four sides, and the
   first thing inside is a centred illustration that would otherwise land in it. */
/* CONDENSED TO THE JOIN CARD'S OWN WIDTH, 2026-08-24 — "condense the you might
   be wondering section, it doesnt have to be that wide, and then we can have it
   be more touching with the actual sign up section... like how the other pages
   look".

   720px is not a chosen number: it is exactly what .join-card measures directly
   above, and it is the measure this page already uses for .club-hero .wrap. It
   also lands inside the band every other page keeps its copy in — the site's
   content widths run 34rem, 40rem, 680, 700, 720, 780. At the full 1160px wrap
   this card was wider than anything else on the site.

   CENTRED AGAIN, deliberately reversing the left-pull this rule carried for one
   round. That pull was there to break the page's centre line, and the quote band
   above still does it — but the ask here is for these two cards to read as ONE
   unit, and two stacked cards of identical width, close together, only do that
   from the same axis. It is not a loss for the horizontality problem either: two
   720px cards in a column on a 1280 page read considerably more vertical than one
   1160px band did.

   The gap between the two is closed to match, on .club-join's padding-bottom and
   this section's padding-top — see those. The sage crossover at this card's
   top-right is unaffected; it is anchored to .wrap, not to the card. */
.faq-card {
  width: min(720px, 100%);
  margin-inline: auto;
  background-color: var(--panel-blue);
  background-image: url("../images/art/paper-wash.png");
  background-size: cover;
  background-position: center;
  background-blend-mode: soft-light;
  padding: calc(var(--space-xl) + 0.5rem) clamp(1.8rem, 4vw, 3.2rem) calc(var(--space-xl) + 1rem);
}

/* Heading */
.faq-head { text-align: center; margin-bottom: 1.8rem; }

/* The teal moon that sat above this heading was removed on 2026-08-06 at
   Lauren's call, markup and rule both. Don't reintroduce `.faq-celestial` — a
   rule with no markup is exactly the kind of dead CSS that silently captures a
   later class of the same name. */

.club-faq .faq-title {
  font-family: var(--font-heading);
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-weight: 500;
  font-size: clamp(0.972rem, 1.944vw, 1.377rem);
  color: var(--forest);
  margin: 0.25rem 0 0;
}

.faq-rule {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.9rem;
  margin-top: 0.85rem;
}
.faq-rule-heart { color: var(--teal); font-size: 1rem; line-height: 1; }
.faq-rule-line {
  position: relative;
  width: 64px;
  height: 1px;
  background: rgba(23, 93, 102, 0.35);
}
.faq-rule-line::after {
  content: "";
  position: absolute;
  top: 50%;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: rgba(23, 93, 102, 0.5);
  transform: translateY(-50%);
}
.faq-rule-line:first-child::after { left: -7px; }
.faq-rule-line:last-child::after { right: -7px; }

/* Dropdown items.

   These were six bordered, rounded, drop-shadowed white boxes stacked down the
   page — the app-card look the whole direction moves away from, and the single
   boxiest thing left on either page once the panels became torn scraps. They are
   editorial rows now: no fill, no border, no radius, just a hairline between
   them. The icon roundels stay, because a circle is a mark rather than a box.

   Slightly wider, since losing the padding of a box costs measure. */
.faq-list {
  max-width: 720px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
}

/* Hairlines rather than boxes, and they read as rules drawn on the wash now that
   the rows sit on the aqua scrap instead of on bare paper. */
.faq-item {
  border-bottom: 1px solid rgba(23, 93, 102, 0.22);
}
.faq-item:first-child { border-top: 1px solid rgba(23, 93, 102, 0.22); }

.faq-item summary {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  cursor: pointer;
  list-style: none;
  position: relative;
  padding: 1.05rem 2.6rem 1.05rem 0.2rem;
}
.faq-item summary::-webkit-details-marker { display: none; }

.faq-icon {
  flex-shrink: 0;
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  /* Reversed out on Lauren's call: a solid navy disc with the line-art in light
     teal. It was a blue-to-teal wash with a teal stroke, which worked while the
     scrap was aqua and vanished into it the moment the card took the blue. Flat
     rather than a gradient — at 38px a two-stop wash under a 1.4px stroke only
     muddies it, and the whole point of going dark was to make the strokes pop.
     9.7:1 stroke on disc, and the disc itself 9.0:1 on the blue scrap. */
  color: var(--panel-teal);
  background: var(--navy);
}
.faq-icon svg { width: 19px; height: 19px; }

/* Was 0.907rem, well under the site's caption size on a line that is the only
   thing you read before deciding whether to open the row. */
.faq-q {
  font-family: var(--font-heading);
  font-variation-settings: var(--display-vars);
  font-size: 1.11rem;
  font-weight: 600;
  color: var(--forest);
  line-height: 1.25;
  transition: color 0.2s ease;
}
.faq-item summary:hover .faq-q { color: var(--teal); }

/* 3. The FAQ row itself. The question already turned teal, but the whole row is
      the click target and it gave no feedback of its own — on a card of eight
      stacked rows, a colour change confined to the words is easy to miss and
      does not tell you how far the target extends.

      A white veil rather than a palette colour: the card is --panel-blue with
      paper-wash blended over it, so any tint would fight the wash, while white
      at low alpha just lifts what is already there. The negative inline margin
      with matching padding lets the highlight reach the card's padding edge, so
      it reads as a full row rather than a patch behind the text. */
.faq-item summary {
  transition: background-color 0.2s ease;
  border-radius: 10px;
  margin-inline: -0.7rem;
  padding-inline: 0.9rem 3.3rem;
}

.faq-item summary:hover { background-color: rgba(255, 255, 255, 0.34); }

.faq-item summary::after {
  content: "+";
  position: absolute;
  right: 1rem;
  top: 50%;
  transform: translateY(-50%);
  font-family: var(--font-body);
  font-size: 1.3rem;
  line-height: 1;
  color: var(--teal);
}
.faq-item[open] summary::after { content: "\2013"; }

.faq-item > p {
  margin: 0;
  padding: 0 1rem 1.15rem calc(38px + 1.1rem);
  font-size: var(--t-base);
  line-height: 1.65;
  color: var(--charcoal);
}

@media (max-width: 760px) {
  .faq-item summary { padding: 0.95rem 2.3rem 0.95rem 0.1rem; gap: 0.75rem; }
  .faq-icon { width: 34px; height: 34px; }
  .faq-icon svg { width: 17px; height: 17px; }
  .faq-q { font-size: 1.02rem; }
  .faq-item > p { padding-left: calc(34px + 0.85rem); }
}

/* ==========================================================================
   Responsive
   ========================================================================== */

@media (max-width: 1000px) {
  .pillar-grid { grid-template-columns: repeat(3, 1fr); row-gap: 3rem; }
  .believe-for { grid-template-columns: 1fr; }
  .club-banner .wrap { grid-template-columns: 1fr; }
  .inside-grid { grid-template-columns: repeat(2, 1fr); }
  .note-reminders .wrap { grid-template-columns: 1fr; }
}

/* ---------- The header collapses to the burger at 1100px, not 760 ----------
   Lauren, 2026-08-10: Connect went back to meaning the contact page and Sunday
   Spark became a nav item of its own. That is six items, and the row cannot
   hold them — measured, the full nav needs 979px of a wrap that is only
   `min(1160px, 100vw - 64px)` wide, so it runs out at about 1043 —
   and measured at 1045 it had already gone to two lines with the wordmark
   crushed 184 -> 181. 1100 leaves 62px of slack rather than 0.

   It did not fit at FIVE either. At 800px "Self-Love Club" was already breaking
   across three stacked lines and the row had zero px to spare; that has been
   live on all six pages and is the tablet range the notes list as unchecked.

   So everything the phone menu does now starts at 1100. Only the drawer moved.
   The phone-sized wordmark and Jam pill stay at 760 below, because a tablet is
   not a phone — at these widths both keep their full-size treatment.

   1100 -> 1245 ON 2026-08-23, when "1:1 Sessions" became a SEVENTH item.
   Measured by binary search with the webfont loaded: the seven-item row is
   clean at 1206 and at 1205 three labels — "Sunday Spark", "1:1 Sessions" and
   "Self-Love Club" — each break across two lines. Note the failure mode is NOT
   the flex row wrapping; `flex-wrap` is `nowrap`, so the row holds and the
   individual labels break inside their own boxes instead. Anything checking
   this by looking at item `left` values will see them still increasing and
   conclude the row is fine. Compare item HEIGHTS: a broken label is 63.4px
   against 31.7.

   1245 rather than 1206 leaves 39px of slack, the same reasoning the 1100
   above used — the measurement is one browser with one loaded webfont, and
   Safari and Windows draw this row a few px wider. It also keeps a 1280
   viewport on the full row with 35px clear, which was the point of not going
   higher.

   SHORTENING THE LABEL WAS NOT ENOUGH, checked before moving this: the row
   needs 106px more than 1100 gives it, and "1:1 Sessions" is only 93px wide —
   cutting it to "1:1" outright still would not have bought the band back.

   ONLY THE TWO NAV BLOCKS MOVED. Seven other `max-width: 1100px` blocks in
   this file are vine and butterfly placements and have nothing to do with the
   header; they stay at 1100.
   ---------------------------------------------------------------------- */
@media (max-width: 1245px) {
  .site-header { padding: 1rem 0; }

  .site-header .wrap { gap: 0.7rem; }

  .nav-song-mobile {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin-left: auto;
    padding: 0.45rem 1.15rem !important;
    font-size: 0.932rem !important;
    letter-spacing: 0.14em;
    white-space: nowrap;
  }

  .nav-toggle-label { display: block; }

  /* ---------- The wordmark: smaller, and actually flush left ----------
     Lauren, 2026-08-07: "the lumi libra logo isn't fully left aligned, and I'd
     like to make it smaller."

     TWO SEPARATE FAULTS, and neither is the `left` you would go looking for.

     1. THE ASSET CARRIES ITS OWN MARGIN. logo.webp is 640x153 with a 17px
        transparent border on all four sides — the ink runs x17-622. The <img>
        box IS flush with .wrap, but the drawing inside it starts 4.6px further
        right, so the wordmark sits inset from every other thing on the page.
        `margin-left` pulls that border back off the edge. It is derived, not
        eyeballed: the border is 17 of the asset's 153px height, so at any
        rendered height it is height x 0.1111.

     2. IT WAS BEING SQUEEZED. The header wrap is flex, and at 390 the logo, the
        "This Week's Jam" pill and the burger were tight enough that the logo
        shrank — measured, it rendered 173.9x44 where its own aspect wants
        184x44, a 5.5% horizontal crush. `flex-shrink: 0` stops that, and the
        smaller size below gives the row the space to allow it.

     44 -> 34px, which was a bigger cut than it sounded: the visible wordmark
     went 34.2px -> 26.4px tall, because the transparent border ate 22% of any
     height you gave that file. THAT BORDER IS GONE as of 2026-08-20 — the asset
     is trimmed to its painted alpha now — so these numbers are the whole story
     and the sizes came down to 36/28 to compensate.

     THE PULL GOES ON THE LINK, NOT THE IMAGE. Tried on the <img> first and it
     also shortened the drawing: the element is the flex item's whole content, so
     a negative inline margin fed back into the width it resolved against and
     re-introduced the very squeeze `flex-shrink: 0` had just removed — 138.4px
     where the aspect wants 142.2. On the link the image's own box is left alone
     and only the whole unit slides.

     The real fix for (1) was trimming the border out of the asset. DONE on
     2026-08-20, in .claude/import-logo.py and .claude/make-logo.py, and it does
     serve the footer and desktop as promised. */
  .logo-link {
    /* Tracks the desktop size — same 36 -> 32 and the same reasoning. */
    --logo-h: 32px;
    flex-shrink: 0;
    margin-left: calc(var(--logo-h) * -0.1111);
  }

  .logo-link img { height: var(--logo-h); }

  .main-nav {
    position: fixed;
    inset: 0;
    /* Lauren, 2026-08-07: "the page that opens on mobile with the 3 lines —
       let's color that the light teal water colour." Was flat --cream.

       Not just a colour swap: this is the SAME treatment .believe and .who-for
       get, so the menu reads as one of the site's paper panels rather than a
       tinted overlay. --panel-teal under paper-wash.png at `soft-light` is what
       makes it watercolour rather than a flat fill — the texture is baked into
       the asset, which is the site's standing rule for wash (a CSS gradient or
       filter has been tried on this site and does not read the same).

       `background` -> `background-color`, deliberately. The shorthand would
       reset background-image on every later declaration and quietly drop the
       wash. Text contrast needed nothing: the links and the close X both
       already flip to navy when the menu opens (#212E39 on #BBDFDE), while the
       closed burger stays cream over the dark hero. Verified in both states. */
    background-color: var(--panel-teal);
    background-image: url("../images/art/paper-wash.png");
    background-size: cover;
    background-position: center;
    background-blend-mode: soft-light;
    /* CLIPS THE TWO BUTTERFLIES TO THIS PANEL, and it is a bug fix, not tidying.

       Both decorations are deliberately bled past the panel's edges (left: -13%,
       right: -14%) so they read as cut off. But the closed menu is not hidden —
       it is parked off-screen with `transform: translateX(100%)`, and anything
       hanging off its LEFT edge lands back inside the viewport once the whole
       panel has moved a screen-width right. Measured at 390: the top-left
       butterfly sat at x339-589 with the menu shut, putting 50.7px of wing on
       the page over every section, on all six pages. Lauren, 2026-08-07: "that
       top butterfly is actually showing up on the other pages... the part that
       is cut off."

       Clipping to the panel changes nothing when the menu is open — the cut
       falls on the panel's edge, which is exactly where the viewport's edge is
       — and leaves nothing outside it to escape when shut. The alternative,
       pulling the drawings inside the box, would cost the bleed she asked for. */
    overflow: hidden;
    flex-direction: column;
    justify-content: center;
    gap: 1.6rem;
    font-size: 1.332rem;
    transform: translateX(100%);
    transition: transform 0.3s ease;
    z-index: 55;
  }

  /* Lauren, 2026-08-07: "can we add a large white sketch butterfly in here too,
     but faded." bfly-white-large is the site's designated large white drawing
     and was the one asset in the set still unused anywhere, so nothing is
     repeated by taking it.

     A PSEUDO-ELEMENT, not an <img>, for two reasons. One markup change would
     otherwise have to be made identically on six pages and stay in step. Two,
     .main-nav is a flex container, and a ::before on a flex container becomes a
     FLEX ITEM — it would have been laid out as a sixth nav link and pushed the
     menu off centre. `position: absolute` is what takes it back out of flow, and
     it is load-bearing rather than habit.

     Painted before the anchors and given no z-index, so it sits behind them by
     ordinary paint order without a stacking contest. pointer-events off so the
     dead centre of the menu is not a tap target that does nothing.

     Bled off the right edge and sat low, the way the site treats its other big
     botanicals: a drawing that runs off the page reads as a glimpse of something
     larger, where one floating fully inside its box reads as a sticker. 0.28
     because the drawing is WHITE LINE ART on a pale teal wash and has very
     little contrast to spend — it goes from "faded" to "gone" quickly, and 0.2
     was already too close to nothing at this size. */
  .main-nav::before {
    content: "";
    position: absolute;
    right: -14%;
    bottom: 4%;
    width: min(340px, 86vw);
    aspect-ratio: 480 / 557;
    background: url("../images/art/bfly-white-large.webp") no-repeat center / contain;
    opacity: 0.28;
    pointer-events: none;
  }

  /* Its open-winged partner, top-left, 2026-08-07: "another one with the open
     wings (nothing trailing behind it) to the left top, having part of it being
     cut off, and same fading."

     bfly-white-open-2, which is the clean cut-out. It was bfly-white-open first,
     on the assumption that trails on this site are always separate `path-*`
     assets — that is true of most of them and NOT of this drawing, which has a
     dashed curve and a sparkle baked into the file below its lower wing. Lauren
     caught it: "yes remove the trailing, there is also a different version in
     the folder without that attached." Check the asset rather than the naming
     convention before treating a butterfly as bare.

     This drawing is also wider for its height (300x217 against 420x375), so the
     aspect-ratio below is its own, not the other one's.

     It is now the third appearance of bfly-white-open-2 on the site, after the
     club hero pair. Normally that repeat would be the reason to pick something
     else; here she asked for this specific drawing, and the menu is a surface
     you only ever see on its own.

     Deliberately smaller than the ::before (250 against 340) and bled off the
     OPPOSITE edge. Two white butterflies at one size on one panel would read as
     a pair of stickers; different sizes entering from opposite corners read as
     one drifting past the other.

     ::after is the element's LAST child, so unlike ::before it paints ON TOP of
     the anchors rather than behind them. That is fine only because it is up in
     the empty top-left and the links are centred — measured, they do not meet.
     If this is ever moved down, it will start sitting over the menu text, and no
     opacity is low enough to make that read as behind. */
  .main-nav::after {
    content: "";
    position: absolute;
    left: -13%;
    top: 6%;
    width: min(250px, 64vw);
    aspect-ratio: 300 / 217;
    background: url("../images/art/bfly-white-open-2.webp") no-repeat center / contain;
    opacity: 0.28;
    pointer-events: none;
  }

  .nav-toggle:checked ~ .main-nav { transform: translateX(0); }

  .main-nav .nav-song { display: none; }

  .nav-toggle:checked ~ .nav-toggle-label span { background: transparent; }
  .nav-toggle:checked ~ .nav-toggle-label span::before { top: 0; transform: rotate(45deg); }
  .nav-toggle:checked ~ .nav-toggle-label span::after { top: 0; transform: rotate(-45deg); }
}

@media (max-width: 760px) {

  /* Phone only — the tablet block above already has the burger, but keeps the
     full-size wordmark and Jam pill. See the note there for why 34px is not
     simply "smaller": the asset carries a transparent border. */
  /* 28 -> 25, the phone's share of the same reduction: Calistoga drew 147px
     across at 28px, and Averia draws 148 at 25. */
  .logo-link { --logo-h: 25px; }

  .nav-song-mobile {
    padding: 0.38rem 0.72rem !important;
    font-size: 0.644rem !important;
    letter-spacing: 0.08em;
  }

  .hero { padding-top: 7rem; padding-bottom: 10rem; }
  .hero .wrap { grid-template-columns: 1fr; }
  /* `width`, not `max-width` alone, and a top margin that used to come free.
     The figure moved OUT of .wrap on 2026-08-12 so the split layout could reach
     the window edge, and it lost two things the wrap was giving it down here:
     the 32px side padding (at 375 the photo went edge to edge) and the grid's
     3rem gap from the copy above it. Both are restored explicitly. */
  .hero-figure {
    width: min(420px, calc(100vw - 64px));
    max-width: 420px;
    margin: 2.6rem auto 0;
  }

  /* ---------- The hero butterfly crosses the tear, on phones ----------
     Lauren, 2026-08-10, in two steps: first "move the teal and purple butterfly
     so it rests where the sections meet under it", then "i want it so it
     overlaps but the teal and white section". It now straddles the seam.

     Which butterfly: .hero-corner-bfly is the ONLY teal/purple one a phone ever
     shows — .remember-bfly, .who-corner-bfly and .club-corner-bfly are all
     display:none down here.

     It could not do this from the hero. .hero is masked by .torn-bottom AND set
     to overflow:hidden, so the half that should land on the cream is erased
     twice. The phone piece is therefore a separate element hanging off
     .remember, the section below, reaching UP over the teal — the same trick
     .vine-crossover-clip uses for the sprig, run in the opposite direction.
     Nothing about the desktop placement changes. */
  .hero-corner-bfly { display: none; }

  .hero-seam-bfly {
    display: block;
    /* Its containing block is .remember, whose top edge IS the hero's box
       bottom. -19px is where the PAINTED tear sits above that edge under this
       butterfly: --wave-h is pinned to its 30px clamp floor below ~882px wide,
       and wave-bottom.svg's curve runs y 27.4-39.1 of 80 across the x it
       occupies, so the visible edge lands 15-20px up. */
    top: -19px;
    /* Then lift it by half its OWN height, so the tear crosses through the
       middle of the drawing.

       It went 55% -> 70% on 2026-08-10 at Lauren's ask, when everything above
       the tear was flat teal and sitting high on the colour read well. The
       full-width photo changed the ground underneath it: measured at 390, 87px
       of 97 sat on the photograph, over lit foliage and shadowed trees, where a
       painted wash loses its edges — and at 90/10 it had stopped straddling
       anything. Back to an even split, which also puts the lower wing on clean
       cream and makes it rhyme with the leaves crossing the same tear beside it.

       A percentage rather than px so the split survives the width changing the
       size: 50/50 at 320 is 50/50 at 430, where a px lift would ride up as the
       butterfly shrinks. */
    transform: translateY(-50%) scaleX(-1);   /* scaleX keeps it facing left */
    /* 19.2% of the section tracks what 21% of .hero-figure used to give within
       a pixel or two across the phone range, so it is the same butterfly at the
       same size — only re-hung. */
    width: 19.2%;
    right: 8.6%;
    /* Above .hero's own decoration, which sits at z-index 2. Neither section
       opens a stacking context (both are position:relative, z-index auto), so
       these compare directly. */
    z-index: 3;
  }

  .note-copy { text-align: center; }
  /* Sunday Spark stacks: label, then the copy, then the signup — the
     three-column row has no room to be a row here. */
  .reminders { grid-template-columns: 1fr; text-align: center; row-gap: 0.9rem; }
  .reminders .signup-form { justify-content: center; }
  /* The Remember heading stays left-aligned at every width — Lauren asked for it
     explicitly, and it was only ever centred here. (This also used to centre
     `.remember .script`, a selector that stopped existing when the script
     subhead became the small-caps .remember-sub.) */
  .pillar-grid { grid-template-columns: 1fr; }
  .pillar { max-width: 340px; margin: 0 auto; }

  /* Center the "What I Believe" heading and list as a centered block */
  .believe { text-align: center; }
  .believe ul { display: inline-block; text-align: left; }
  /* Same for the "Who Lumi Libra Is For" column and its closing quote */
  .who-list, .who-quote { text-align: center; }
  .who-for ul { display: inline-block; text-align: left; }
  .who-quote { margin-inline: auto; }

  .club-banner .wrap { justify-items: center; }
  .club-copy { border-radius: 40px 22px 34px 26px / 32px 38px 26px 34px; }

  .note { grid-template-columns: 1fr; justify-content: stretch; }
  .note figure { justify-self: center; }
  .note .polaroid { width: 200px; }

  .inside-grid { grid-template-columns: 1fr; }
  .how-steps { grid-template-columns: 1fr; }
  .footer-grid { grid-template-columns: 1fr; }
}

/* ==========================================================================
   Self-Love Club — additional sections (from club mock)
   ========================================================================== */

/* What is the club? + Every month you'll receive */
.club-about {
  padding: 5.5rem 0;
  background:
    radial-gradient(ellipse 45% 55% at 100% 0%, rgba(var(--c-lav), 0.48), transparent 72%),
    var(--cream);
}

.club-about-grid {
  display: grid;
  grid-template-columns: 1fr 1.15fr;
  gap: clamp(2.5rem, 6vw, 5rem);
  align-items: start;
}

.about-intro p { font-size: 1.132rem; margin-bottom: 1.1rem; }
.about-intro .script { display: block; margin-top: 1.5rem; font-size: 1.215rem; }

.receive-grid {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2rem 1.4rem;
  margin-top: 0.5rem;
}

.receive-grid li {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 0.75rem;
  font-size: 0.999rem;
  color: var(--forest);
  line-height: 1.4;
}

.receive-grid .ri {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: var(--white);
  box-shadow: 0 5px 16px rgba(31, 94, 92, 0.07);
  color: var(--teal);
}

.receive-grid .ri svg { width: 25px; height: 25px; }

/* How it works — 4 steps */
.how-steps-4 { grid-template-columns: repeat(4, 1fr); }

/* What a week looks like */
.club-week {
  padding: 5.5rem 0;
  background:
    radial-gradient(ellipse 40% 60% at 0% 30%, rgba(var(--c-blue), 0.48), transparent 72%),
    var(--white);
}

.club-week-grid {
  display: grid;
  grid-template-columns: 0.8fr 1.7fr;
  gap: clamp(2rem, 5vw, 4rem);
  align-items: center;
}

.week-intro .script { display: block; margin-top: 1rem; font-size: 1.215rem; }

.week-card {
  background: var(--cream);
  border-radius: calc(var(--radius) * 1.6);
  box-shadow: var(--shadow-soft);
  padding: 2.4rem clamp(1.5rem, 3vw, 2.6rem);
}

.week-card-head { text-align: center; margin-bottom: 1.8rem; }
.week-card-head .eyebrow { margin-bottom: 0.4rem; }
.week-title { font-size: 2.4rem; display: block; line-height: 1; }

.theme-pill {
  display: inline-block;
  margin: 0.7rem 0 1.1rem;
  padding: 0.4rem 1.1rem;
  border-radius: 999px;
  background: rgba(var(--c-blue), 0.4);
  color: var(--forest);
  font-size: 0.866rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.week-lead { max-width: 32rem; margin: 0 auto; font-size: 1.088rem; }

.week-items {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1.2rem;
}

.week-item {
  background: var(--white);
  border-radius: var(--radius);
  padding: 1.5rem 1rem;
  text-align: center;
  box-shadow: 0 4px 14px rgba(31, 94, 92, 0.05);
}

.week-item img { width: 66px; height: 66px; object-fit: contain; margin: 0 auto 0.7rem; }

.week-item h4 {
  font-family: var(--font-body);
  font-size: 0.799rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--teal);
  margin-bottom: 0.5rem;
}

.week-item p { font-size: 0.91rem; line-height: 1.55; }

.week-foot { text-align: center; margin-top: 1.8rem; color: var(--teal); font-size: 1.054rem; }

/* Meet your guide */
.club-guide {
  padding: 5.5rem 0;
  background:
    radial-gradient(ellipse 45% 60% at 100% 100%, rgba(var(--c-lav), 0.48), transparent 72%),
    var(--cream);
}

.club-guide-grid {
  display: grid;
  grid-template-columns: 0.9fr 1.5fr 0.85fr;
  gap: clamp(2rem, 4vw, 3.2rem);
  align-items: center;
}

.guide-photo img {
  width: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  border-radius: 50%;
  box-shadow: var(--shadow-soft);
}

.guide-copy .eyebrow { margin-bottom: 0.3rem; }

.guide-hi {
  display: block;
  font-size: 1.9rem;
  margin-bottom: 1.1rem;
}

.guide-copy p { font-size: 1.088rem; margin-bottom: 1.1rem; }
.guide-copy > .script { display: block; margin-top: 0.6rem; font-size: 1.215rem; }

.guide-quote {
  background:
    radial-gradient(ellipse 70% 70% at 70% 25%, rgba(var(--c-blue), 0.5), transparent 72%),
    rgba(var(--c-blue), 0.1);
  border-radius: calc(var(--radius) * 1.6);
  padding: 2.2rem 1.8rem;
  text-align: center;
}

.guide-quote .script {
  font-size: 1.256rem;
  line-height: 1.5;
  color: var(--forest);
}

/* Features strip */
.club-features-strip {
  background: var(--white);
  padding: 2.6rem 0;
  border-top: 1px solid rgba(44, 122, 120, 0.1);
}

.club-features-strip .wrap {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 2rem;
}

.feature {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  font-size: 1.021rem;
  color: var(--forest);
}

.feature svg { width: 27px; height: 27px; color: var(--teal); flex-shrink: 0; }

/* Club-page responsive */
@media (max-width: 1000px) {
  .club-about-grid { grid-template-columns: 1fr; }
  .how-steps-4 { grid-template-columns: repeat(2, 1fr); row-gap: 2.6rem; }
  .club-week-grid { grid-template-columns: 1fr; }
  .club-guide-grid { grid-template-columns: 1fr 1fr; }
  .guide-quote { grid-column: 1 / -1; }
  .club-features-strip .wrap { grid-template-columns: repeat(2, 1fr); gap: 1.4rem; }
}

@media (max-width: 760px) {
  .how-steps-4 { grid-template-columns: 1fr; }
  .week-items { grid-template-columns: repeat(2, 1fr); }
  .club-guide-grid { grid-template-columns: 1fr; }
  .guide-photo { max-width: 320px; margin: 0 auto; }
}

@media (max-width: 460px) {
  .receive-grid { grid-template-columns: repeat(2, 1fr); }
  .week-items { grid-template-columns: 1fr; }
  .club-features-strip .wrap { grid-template-columns: 1fr; }
}

/* ==========================================================================
   Self-Love Club — content v2 (two-column hero, receive-7, feeling)
   ========================================================================== */

/* Two-column hero */
.club-hero-split { text-align: left; padding: 9rem 0 5rem; }

.club-hero-grid {
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  gap: clamp(2rem, 5vw, 4rem);
  align-items: center;
}

/* ---------- The two inner-page hero titles ----------
   Lauren, 2026-08-07: "i want to increase the text size of self love club and
   also about lauren on the about lauren page."

   These two H1s carry ONE size between them and always have — `.about-hero-title`
   further down holds the identical clamp on purpose, so About and the Club read
   as the same tier of page. Change one and change the other, or the pages stop
   matching. Both went 4.86vw/3.726rem -> 6.075vw/4.6575rem, a straight x1.25.

   THE MIN IS DELIBERATELY NOT SCALED. clamp's floor is what governs phones —
   2.268rem beats 6.075vw below a 622px viewport — so leaving it at 2.268 means
   nothing changes at or under the 700px breakpoint where every decor placement
   on both pages is separately tuned. Only desktop grows.

   Then "lets make it a little bigger" — another x1.1 on top, so 4.86vw/3.726rem
   -> 6.683vw/5.123rem overall, x1.375 from where these started. 82px at 1440.

   On the Club page this heading is centred, and it grows into the butterfly
   beside it from BOTH sides at once. See .hero-wordmark-bfly for what each step
   costs there — the 14px gap to the "S" has to be bought back every time. */
.club-hero-copy h1 { font-size: clamp(2.268rem, 6.683vw, 5.123rem); margin-bottom: 0.4rem; }
.club-hero-copy .script { display: block; margin: 0.7rem 0 1.4rem; }
.club-hero-copy p.lead { max-width: 34rem; margin: 0 0 1.9rem; }
.club-hero-copy .small-print { font-size: 0.944rem; color: rgba(74, 74, 74, 0.75); margin-top: 0.9rem; }

.club-hero-figure { position: relative; }

/* Centered section title (serif, understated) */
.section-title {
  text-align: center;
  font-size: clamp(1.377rem, 2.43vw, 1.863rem);
  letter-spacing: 0.02em;
  margin-bottom: 3rem;
}

/* Inside the Self-Love Club — six watercolour patches.

   Lauren's own icons, imported 2026-08-05, replacing the pale receive-*.webp set
   from July. Same construction as the home page's pillar patches — white line
   art already drawn onto the paint, one complete piece — so this row is built
   the same way, and the two pages read as one system.

   Bare paper: `main` carries the continuous ground and this section adds nothing
   of its own. The wrap widens like .pillars .wrap does, because six columns in
   the standard 1160 leaves each one ~177px and the titles start wrapping to
   three lines. */
/* NO PHOTOGRAPH IN THIS SECTION. It was proposed twice on 2026-08-24 — it is the
   page's one full-width centred band with no imagery, so a portrait photo beside
   the list was the obvious answer to the layout reading as horizontal — and
   Lauren declined: "i dont want to add a pic to inside the self love club". The
   horizontality was addressed on .club-quote and .faq-card instead. Don't
   re-suggest it. */
.club-receive { padding: var(--section) 0; }
.club-receive .wrap { width: min(1260px, 94%); }

/* Staggered rather than ruled into a straight row, like the pillars — and for
   the same reason it works there: the lifts rise and fall SYMMETRICALLY, here
   about the gap between items 3 and 4, so the row still scans as one gesture
   instead of reading as a broken grid. Keep any adjustment patterned. */
.receive7 {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 1.2rem;
  align-items: start;
}

.receive7 .item { text-align: center; margin-top: var(--lift, 0); }

.receive7 .item:nth-child(1) { --lift: 0rem;   --tilt: -4deg; --patch: 1;    }
.receive7 .item:nth-child(2) { --lift: 3rem;   --tilt:  3deg; --patch: 0.93; }
.receive7 .item:nth-child(3) { --lift: 0.9rem; --tilt: -2deg; --patch: 1.04; }
.receive7 .item:nth-child(4) { --lift: 0.9rem; --tilt:  2deg; --patch: 1.04; }
.receive7 .item:nth-child(5) { --lift: 3rem;   --tilt: -3deg; --patch: 0.93; }
.receive7 .item:nth-child(6) { --lift: 0rem;   --tilt:  4deg; --patch: 1;    }

/* Only the patch tilts and rescales. Rotating the whole item would tip the
   caption with it, and slanted paragraphs stop being playful immediately. */
.receive7 .ri-img {
  display: block;
  width: calc(min(132px, 100%) * var(--patch, 1));
  aspect-ratio: 340 / 325;
  object-fit: contain;
  margin: 0 auto 0.9rem;
  transform: rotate(var(--tilt, 0deg));
}

/* ---------- The patches dance on hover ----------
   Lauren, 2026-08-06: "some fun little pop motion when you hover the icons on
   both the home page and the self love club page … like they dance is the vibe
   i want." One block for both rows — the home pillars and the club's six
   patches are the same object with two class names, and they should move the
   same way.

   THE RESTING TILT IS THE WHOLE PROBLEM. Both patches already sit on
   `transform: rotate(var(--tilt))`, and every pillar has a different --tilt
   (-4deg to +5deg, the staggered row). A `transform` in a keyframe REPLACES the
   element's transform outright rather than adding to it, so a naive
   `scale(1.06)` would snap all eleven patches upright at 0deg the instant the
   dance began and drop them back on mouseout. Every keyframe below therefore
   restates `rotate(calc(var(--tilt) + …))` — the sway is expressed relative to
   each patch's own resting angle, so they dance from where they stand.

   transform-origin sits at the bottom so the sway pivots around where the patch
   meets its caption. Rotating about the centre reads as a spin; about the foot
   it reads as weight shifting, which is the difference between a wobble and a
   dance.

   The step is asymmetric on purpose — a bigger swing one way, a smaller
   recovery the other, with the lift peaking off-beat from the rotation. A
   symmetric sway is a metronome, not a dance.

   Infinite while hovered, not a one-shot: "like they dance" is a state, not a
   pop. It stops the moment the pointer leaves. */
@keyframes patch-dance {
  0%,
  100% { transform: rotate(var(--tilt, 0deg))                translateY(0)     scale(1);    }
  15%  { transform: rotate(calc(var(--tilt, 0deg) + 6deg))    translateY(-7px)  scale(1.06); }
  35%  { transform: rotate(calc(var(--tilt, 0deg) - 5deg))    translateY(-2px)  scale(1.03); }
  55%  { transform: rotate(calc(var(--tilt, 0deg) + 4.5deg))  translateY(-7px)  scale(1.06); }
  78%  { transform: rotate(calc(var(--tilt, 0deg) - 3deg))    translateY(-1px)  scale(1.02); }
}

.pillar-blob,
.receive7 .ri-img {
  transform-origin: 50% 88%;
  /* Carries the patch back down gently when the pointer leaves — without it the
     animation just stops dead wherever it happens to be in the cycle. */
  transition: transform 0.35s ease;
}

/* BOTH RULES BELOW ARE GATED ON `hover: hover`, and that gate is load-bearing.

   Lauren, 2026-08-07: "the 'dancing' icons, on mobile. you have to click instead
   of hover for them to move. and then the one you click will just continuously
   move until you click again."

   That is the sticky-:hover trap on touch. A phone has no pointer to leave, so
   the browser fakes one: a tap applies :hover and LEAVES IT APPLIED until the
   user taps something else. Paired with `infinite` — chosen deliberately above,
   because "like they dance" is a state rather than a pop — the patch dances for
   as long as it stays "hovered", which on a phone is until the next tap
   somewhere. Exactly the two symptoms she describes, and both follow from the
   same line.

   `hover: hover` asks whether the device's primary input can actually hover.
   Mice and trackpads say yes; touchscreens say no, so on a phone neither rule is
   ever declared and a tap does nothing at all. That is the correct resting state
   for an effect whose entire brief was "when you hover" — the motion is not lost
   on mobile so much as it was never reachable there, it was just leaving a patch
   stuck on instead of doing nothing.

   Not `pointer: fine`: that asks about precision, not hover, and would also rule
   out a stylus, which does hover. Hover is the thing being tested, so test it.

   If the icons should move on phones too, that needs a real touch interaction —
   a ONE-SHOT dance on tap that ends on its own — not this rule with the gate
   removed. Removing the gate brings back the stuck patch. */
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .pillar-blob:hover,
  .receive7 .ri-img:hover {
    animation: patch-dance 1.15s ease-in-out infinite;
  }
}

/* Reduced motion still gets an acknowledgement of the hover, just a still one.
   Same gate, and for the same reason — this one sticks on a tap too, just
   silently: the patch stays scaled up until you tap elsewhere. */
@media (hover: hover) and (prefers-reduced-motion: reduce) {
  .pillar-blob:hover,
  .receive7 .ri-img:hover {
    transform: rotate(var(--tilt, 0deg)) scale(1.05);
  }
}

/* ---------- The touch half: one tap, one dance ----------
   Lauren asked for the patches to move on phones too, so this is the other side
   of the gate above. Same @keyframes, one crucial difference: it runs ONCE
   (iteration count 1) instead of `infinite`.

   That is the entire fix for what she reported. The bug was never that :hover
   sticks on touch — it does, always, and no CSS can stop it. The bug was that an
   INFINITE animation was hung off it, so a stuck :hover meant a patch that never
   stopped. Driven by a class the script removes on `animationend`, the dance
   ends by itself no matter how long the tap state lingers.

   `hover: none` so it is declared only where the :hover rules are not. The two
   blocks are mutually exclusive by construction — a device gets exactly one of
   them, never both, so the infinite version can never reach a touchscreen.

   Still behind no-preference: on a reduced-motion phone this rule is not
   declared, the class lands on nothing, and a tap does nothing. That is
   deliberate — there is no still "acknowledgement" fallback here the way there
   is for hover, because a tap on a non-interactive patch has nothing to
   acknowledge. */
@media (hover: none) and (prefers-reduced-motion: no-preference) {
  .pillar-blob.is-dancing,
  .receive7 .ri-img.is-dancing {
    animation: patch-dance 1.15s ease-in-out 1;
  }
}

/* Each title takes its own patch's colour, exactly as the pillar titles do —
   that is what ties caption to icon. */
.receive7 h4 {
  font-family: var(--font-body);
  font-size: var(--t-xs);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  margin-bottom: 0.5rem;
  line-height: 1.35;
}

.receive7 .item:nth-child(1) h4 { color: var(--club-welcome); }
.receive7 .item:nth-child(2) h4 { color: var(--club-experiences); }
.receive7 .item:nth-child(3) h4 { color: var(--club-movement); }
.receive7 .item:nth-child(4) h4 { color: var(--club-creative); }
.receive7 .item:nth-child(5) h4 { color: var(--club-reflection); }
.receive7 .item:nth-child(6) h4 { color: var(--club-playlist); }

/* --t-sm, the caption size. These are one-line grid captions, not paragraphs —
   but they were at 0.888rem, well under even that. */
.receive7 p { font-size: var(--t-sm); line-height: 1.55; }

/* Below this the row wraps, and the stagger fights the wrap: an item meant to
   sit high ends up butted under the one above it. Flat rows from here. */
@media (max-width: 1000px) {
  .receive7 .item { margin-top: 0; }
}

/* Is This For You? — a torn blue scrap with the photo straddling its right edge.

   Was a flat --seafoam band ruled off top and bottom, with two mirrored copies
   of the same green-leaf drawing draped into opposite corners at
   mix-blend-mode: screen. Both are gone: the band is a floating scrap now, and
   repeating one drawing twice in a single section is the thing the decoration
   brief rules out most plainly.

   The photo laps OUTSIDE the card on the right rather than sitting in a second
   grid column, so the section breaks the run of rectangles — the same move as
   the home page's heart rock, but on the side rather than the corner, so the two
   don't read as the same composition twice. */
.club-feeling {
  position: relative;
  z-index: 3;
  padding: var(--section) 0;
}

.club-feeling .wrap { width: min(1080px, 90%); position: relative; }

/* Light teal since 2026-08-05 — swapped with the FAQ scrap, which took the blue. */
.feeling-card {
  background-color: var(--panel-teal);
  background-image: url("../images/art/paper-wash.png");
  background-size: cover;
  background-position: center;
  background-blend-mode: soft-light;
  /* The right padding is what keeps the list clear of the photo overlapping it. */
  padding: calc(var(--space-xl) + 0.5rem) clamp(1.8rem, 3.4vw, 3rem) calc(var(--space-xl) + 0.5rem);
  padding-right: clamp(1.8rem, 30%, 20rem);
}

.feeling-card .eyebrow { color: var(--teal-label); }
.feeling-card .feeling-intro { color: var(--navy); }

.feeling-list { list-style: none; margin: 1.2rem 0 0; }

.feeling-list li {
  position: relative;
  padding-left: 1.9rem;
  margin-bottom: 0.8rem;
  font-size: var(--t-base);
  color: var(--ink);
}

/* Filled, and purple because this card is --panel-teal — the site rule, see the
   heart note on .believe. */
.feeling-card { --heart: var(--blob-purple); }
.feeling-list li::before { content: "\2665"; position: absolute; left: 0; color: var(--heart, var(--bullet-blue)); font-size: 0.92em; }

.feeling-copy > p { font-size: var(--t-md); margin-top: 0.6rem; }

/* ---------- Torn coloured mounts behind the blob-masked photos ----------
   Lauren, 2026-08-05, after the chalk row: "i want to do this with the other
   picture in this for you, as well as the photos on the about page" — then
   "in fact keep the photos the way they are just add the border."

   So unlike the chalk row, which lost its mask entirely, these three keep their
   own blob and gain a coloured scrap behind them. The mount is the SAME outline
   at the same seed with the wobble raised to 0.075, drawn into a box 7% larger
   on each side — see photo_rim() in make-photo-masks.py. Same phases means the
   two edges rise and fall together, so the visible border varies without ever
   pinching shut against the photograph.

   inset is a percentage rather than a length because these photos are three
   different sizes and resize besides; a fixed 26px that looks right on the
   380px About photo is half again as thick on the club's 330px one.

   The photo needs its own z-index. Without it the positioned pseudo-element
   paints over the picture, and the fix is not `z-index: -1` on the mount — with
   no stacking context on the figure that drops it behind the section's own
   background and it disappears. */
.feeling-photo::before,
.about-photo::before,
.club-photo::before,
.closing-photo::before {
  content: "";
  position: absolute;
  z-index: 0;
  /* `inset` is deliberately NOT set here. It is per-axis, for the reason spelled
     out at .hero-figure::after — a percentage inset resolves against height
     top/bottom and width left/right, so a single value gives a fat rim on the
     narrow axis — and so it depends on each photo's own aspect. Every one of the
     selectors above declares it, at ~7% of that element's WIDTH with the
     vertical figure scaled by its aspect.
     It cannot live here with per-photo overrides: those rules are all (0,1,1)
     too and three of the four sit EARLIER in the file, so a default here would
     simply beat them. */
  pointer-events: none;
  background-color: var(--mount);
  background-image: url("../images/art/paper-wash.png");
  background-size: cover;
  background-position: center;
  background-blend-mode: soft-light;
  -webkit-mask: var(--rim) center / 100% 100% no-repeat;
          mask: var(--rim) center / 100% 100% no-repeat;
}

/* Masked, not rounded — and blob -c, so it isn't the silhouette either About
   photo uses. Framed near the source's own aspect so the crop doesn't cut the
   subject. */
.feeling-photo {
  position: absolute;
  right: -3%;
  top: 50%;
  width: min(330px, 32%);
  transform: translateY(-50%);
  z-index: 2;
  margin: 0;
}

.feeling-photo img {
  position: relative;
  z-index: 1;
  width: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  -webkit-mask: url("../images/art/photo-blob-c.svg") center / 100% 100% no-repeat;
          mask: url("../images/art/photo-blob-c.svg") center / 100% 100% no-repeat;
}

/* The dark teal, like the heart rock and the About tree rays — Lauren took all
   three off pale mounts. It has enough weight to hold against the blue card,
   which the pale lavender it started on did not. */
.feeling-photo::before {
  --mount: var(--teal-deep);
  --rim: url("../images/art/photo-rim-c.svg");
  inset: -5.6% -7%;        /* 4/5 */
}

/* Responsive */
@media (max-width: 1000px) {
  .club-hero-grid { grid-template-columns: 1fr; }
  .club-hero-figure { max-width: 420px; margin: 0 auto; order: -1; }
  .club-hero-split { text-align: center; }
  .club-hero-copy p.lead { margin-inline: auto; }
  .receive7 { grid-template-columns: repeat(3, 1fr); row-gap: 2.4rem; }
}

/* Below 900 the card has no room to hold a photo lapping its side, so the photo
   returns to the flow ABOVE it, centred and overlapping the card's torn top.

   Three things have to be cleared explicitly, all learned on the home page's
   heart rock: `position: static` would kill the z-index and let the card paint
   over the photo's base; `right` and `top` still offset a relatively positioned
   box, so they have to go or auto margins can't centre it; and the negative
   bottom margin is what pulls the card up under the photo. */
@media (max-width: 900px) {
  .feeling-photo {
    position: relative;
    right: auto;
    top: auto;
    transform: none;
    z-index: 2;
    width: min(300px, 62%);
    margin: 0 auto -3.5rem;
  }
  .feeling-card { padding-right: clamp(1.8rem, 3.4vw, 3rem); padding-top: calc(var(--space-xl) + 2.5rem); }
}

@media (max-width: 700px) {
  .receive7 { grid-template-columns: repeat(2, 1fr); }
  .feeling-card { padding-inline: 2.2rem; }
}

/* ==========================================================================
   Self-Love Club — v2 refinements (arched hero, butterfly fix, creative gallery)
   ========================================================================== */

/* Let the floating butterfly sit outside the image without being clipped */
.club-hero-split { overflow: visible; }

/* Chalk affirmations send-off (bottom of the club page). Both blurred glow
   pseudo-elements removed with the others. */
.chalk-band {
  position: relative;
  padding: 1rem 0 var(--section-airy);
  text-align: center;
}
.chalk-band .wrap { position: relative; z-index: 1; }

.chalk-intro { display: block; font-size: 1.377rem; margin-bottom: 2.2rem; }

/* Two across, not four. At four they came out 282px on a 1280 viewport and the
   lettering — which is the whole point of the drawing — was too small to read;
   two across doubles that to ~557px. Lauren, 2026-08-05: "i need the pictures on
   the bottom of the self love club page to be bigger." */
.chalk-grid {
  display: grid;
  /* Narrower than the wrap, so the scraps come down to ~440px from 529 and the
     band gives back ~150px of page height — Lauren, on the club page feeling
     airy. Constrained here rather than on .chalk-band .wrap, which the intro
     line shares and which should stay full width. 440 is still 56% up on the
     282px they were at four-across, where the lettering was the original
     complaint, so there is room to come down again if the page wants it. */
  width: min(1010px, 100%);
  margin-inline: auto;
  grid-template-columns: repeat(2, 1fr);
  /* Tightened from 2.6rem/3rem. The floor is the TILTS, not taste: each figure is
     rotated up to 2.5deg, which grows its footprint to w(cos+sin) — 588px on a
     580px scrap — so ~8px a side is gone before the gap starts. Measure the
     rotated boxes, not the layout boxes; that is the whole trap here.
     1.5rem row left only 4px between the giraffe and the zebra, because those two
     also carry opposite --lift values, so the left column is always the tight one.
     At 2rem every clearance is 11px or better. Don't go below it. */
  gap: 2rem;
  align-items: start;
}

/* Four scraps pinned to a page, not a filmstrip: each photo is mounted on its own
   torn square of coloured paper, at its own slight angle and height. The
   rotations alternate and the lifts are symmetric about the middle, so it still
   scans as one block.

   The mount replaced the photo-blob masks these used to carry. Lauren, after
   seeing them bigger: "can we add some torn paper border like the home page, but
   make them colored." It also fixes what she reported first — a blob is a
   superellipse, and its diagonal comes in ~27% of the half-width, which on
   drawings that letter the affirmation into their own bottom corners was eating
   "YOU WERE BORN TO" and the end of "UNSTOPPABLE". Nothing masks the photograph
   now; the tear happens out in the mount.

   5% padding against a 3.6% tear, so the deepest bite still lands in the colour
   and the border never closes up. */
.chalk-grid figure {
  margin: 0;
  margin-top: var(--lift, 0);
  transform: rotate(var(--tilt, 0deg));
  padding: 5%;
  background-color: var(--mount, var(--panel-teal));
  background-image: url("../images/art/paper-wash.png");
  background-size: cover;
  background-position: center;
  background-blend-mode: soft-light;
  -webkit-mask: var(--card-tear) center / 100% 100% no-repeat;
          mask: var(--card-tear) center / 100% 100% no-repeat;
}

/* Colours are Lauren's, 2026-08-05: "put the purple on the elephant, the pink on
   the zebra, and the blue on the dolphin." The giraffe keeps the teal. */
.chalk-grid figure:nth-child(1) {       /* giraffe */
  --tilt: -2.5deg; --lift: 0.9rem;
  --mount: var(--panel-teal);
  --tear: url("../images/art/torn-paper-chalk-a.svg");
}
.chalk-grid figure:nth-child(2) {       /* dolphin */
  --tilt:  1.8deg; --lift: 0;
  --mount: var(--panel-blue);
  --tear: url("../images/art/torn-paper-chalk-b.svg");
}
.chalk-grid figure:nth-child(3) {       /* zebra */
  --tilt: -1.6deg; --lift: 0;
  --mount: var(--pink);
  --tear: url("../images/art/torn-paper-chalk-c.svg");
}
.chalk-grid figure:nth-child(4) {       /* elephant */
  --tilt:  2.4deg; --lift: 0.9rem;
  --mount: var(--panel-lav);
  --tear: url("../images/art/torn-paper-chalk-d.svg");
}

.chalk-grid img {
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
}

/* One per row on the phone. Two 160px thumbnails would put the lettering back
   where it started. */
@media (max-width: 640px) {
  .chalk-grid { grid-template-columns: 1fr; gap: 2rem; }
}

/* Hero photo = clean oval (rounded), full image */
.club-hero-figure .club-hero-photo {
  width: 100%;
  border-radius: 46% 54% 52% 48% / 44% 46% 54% 56%;
  box-shadow: var(--shadow-soft);
  -webkit-mask-image: radial-gradient(ellipse 92% 92% at 50% 50%, #000 62%, transparent 100%);
          mask-image: radial-gradient(ellipse 92% 92% at 50% 50%, #000 62%, transparent 100%);
}

/* Watercolor illustration variant — no photo frame, shadow, or crop */
.club-hero-figure .club-hero-illustration {
  width: 100%;
  border-radius: 0;
  box-shadow: none;
  -webkit-mask-image: none;
          mask-image: none;
}

/* "Is this for you?" intro line */
.feeling-intro { font-size: var(--t-md); margin-bottom: 1.1rem; color: var(--navy); }

/* Four further `.feeling-photo` / `.club-feeling-grid` rules used to sit here,
   from when this section was a two-column grid with the photo in the second
   cell. They are gone with that layout — and the last of them,
   `.feeling-photo { position: relative }`, came AFTER the main rule in the file
   and would silently have cancelled the absolute positioning the overlap
   depends on. */

/* ==========================================================================
   About Lauren page
   ========================================================================== */
/* Section headings. These were teal Fraunces ITALIC — the pull-quote voice —
   which put every heading on this page in the one style the rest of the site
   reserves for quotes, and in an accent colour the home page dropped from
   headings entirely. They are ordinary display headings now: navy, upright,
   on the site's own h2 step. Held a little under the home h2's top end because
   this page stacks far more of them. */
.about-title,
.oto-title {
  font-family: var(--font-heading);
  font-variation-settings: var(--display-vars);
  color: var(--forest);
  font-weight: 600;
  font-size: clamp(1.72rem, 2.98vw, 2.36rem);
  line-height: 1.16;
  letter-spacing: -0.005em;
  margin-bottom: 1.2rem;
}
.about-title.center,
.oto-title.center { text-align: center; }

.about-note { color: var(--forest); font-weight: 500; }

/* No section paints its own ground any more — `main` carries one continuous
   sheet and the bands that DO carry colour say so with a torn edge. */
.about-section { padding: var(--section) 0; }

/* The teal band. Built like the home hero rather than like the old dark card:
   the same baked paper texture blended soft-light over uneven radial pools, so
   a full-bleed colour field still reads as pigment on a sheet. Torn top AND
   bottom, so it floats in the page instead of being ruled off it.

   Deeper than the hero's wash on purpose — this is the one dark moment on the
   page and the copy over it is reversed out. */
/* DEEPENED 2026-08-25, when the close moved onto this band and its copy was
   measured properly for the first time.

   THE COPY HERE IS REVERSED OUT AND IT WAS FAILING BEFORE ANYTHING MOVED. The
   19px body ran 3.55-4.21 against the 4.5 it needs; only the lead line passed,
   and only because at 26px its bar is 3.0. It was never the gradient's fault —
   the bare stops measure 4.58 and 5.99 — it was THE TWO WHITE POOLS. They exist
   to keep the band from reading as a flat slab, and where they land they lift
   the ground by 20 levels, which is the whole margin and more.

   So the pools stay and the ground goes under them: both alphas roughly halved,
   and both gradient stops taken down about 15%. Measured on the real composite
   under each line's own rectangle, with the type hidden so the ground is
   actually visible — NOT at the gradient's corners, which report the two values
   the copy never sits on. */
.about-section.bg-teal {
  position: relative;
  padding: calc(var(--section) + var(--wave-h)) 0;
  background:
    url("../images/art/paper-wash.png"),
    radial-gradient(ellipse 46% 52% at 10% 10%, rgba(255, 255, 255, 0.10), transparent 66%),
    radial-gradient(ellipse 40% 46% at 88% 84%, rgba(255, 255, 255, 0.07), transparent 68%),
    radial-gradient(ellipse 38% 42% at 74% 4%,  rgba(18, 74, 80, 0.34), transparent 70%),
    linear-gradient(158deg, #246967 0%, #17565B 100%);
  background-size: cover, auto, auto, auto, auto;
  background-blend-mode: soft-light, normal, normal, normal, normal;
}
.about-section.bg-teal .wrap { position: relative; z-index: 1; }
/* Full --cream, not 0.94 of it. The alpha bought nothing but a 2% contrast
   penalty on copy that had none to spare. */
.about-section.bg-teal .about-copy p { color: var(--cream); }

/* This band has no heading — Lauren asked for its first sentence to open the
   section instead. So it is a LEAD SENTENCE, not a title standing in for one:
   it stays in the body face and only takes size and weight, which is what keeps
   it reading as her voice starting to speak rather than as a label. Sized
   between the body copy and an .about-title so it opens the band without
   claiming the rank of the headings on either side of it. */
.about-lead-line {
  font-size: clamp(1.35rem, 2.1vw, 1.62rem);
  font-weight: 700;
  line-height: 1.35;
  margin-bottom: 1.15rem;
}
.about-section.bg-teal .about-copy p.about-lead-line { color: var(--cream); }
.about-section.bg-teal .about-copy p.about-note { color: var(--seafoam); }

/* The stack of short lines that follows the lead sentence — one paragraph with
   <br> between the lines, so this is the only way to reach it without giving it
   a class it doesn't otherwise need.

   Added 2026-08-14 with her rewrite. Four of the five lines fit the 630px column
   at 1280; "Finding a connection with nature that felt deeper than just spending
   time outside." needs 675px and wraps, and the default wrap left a 65px orphan
   ("outside.") alone on its own line under a full one. text-wrap: pretty moves
   the break back to 564/106 so the tail carries a phrase instead of one word.

   Only desktop is affected. On a phone the column is 345px, three of the lines
   already wrap, and pretty measures identically to the default there — nothing
   to undo at narrow widths. text-wrap: balance does NOTHING here: the forced
   <br> breaks opt the block out of balancing, measured, not assumed. */
.about-section.bg-teal .about-copy p.about-lead-line + p { text-wrap: pretty; }

/* Green leaves rising from the bottom-left corner, partially behind the photo */
.finding-leaves {
  position: absolute;
  left: -3%;
  bottom: -12%;
  width: min(460px, 46%);
  z-index: 0;
  opacity: 0.8;
  mix-blend-mode: screen;
  transform: rotate(22deg);
  pointer-events: none;
}
/* Desktop: stem emerges from the bottom-left corner and the foliage sweeps up around the photo */
@media (min-width: 901px) {
  .finding-leaves {
    left: max(-423px, -34.5vw);
    bottom: max(-238px, -18.7vw);
    width: min(660px, 52%);
    transform: rotate(48deg);
    transform-origin: 55% 81%;
  }
  /* Raise the photo (top-align it) so more of the leaves show below */
  .bg-teal .about-photo { align-self: start; }
}

@media (min-width: 901px) and (max-width: 1100px) {
  .finding-leaves {
    left: -38%;
    width: 48%;
    transform: rotate(42deg);
  }
}

.about-copy p, .about-narrow p, .about-col p { margin-bottom: 1.05rem; }

/* Hero — full-bleed photo with just the page title.
   Carries .torn-bottom in the markup, so the photograph itself ends in a torn
   watercolour edge and the paper below shows straight through it. The bottom
   padding has to clear the tear: the wave bites up to 0.81 * --wave-h into the
   band, and the title is bottom-aligned, so at the old 1.2rem it sat inside the
   torn edge and lost its descenders.

   A split version of this was tried on 2026-08-12 — teal wash left, photograph
   masked onto the right half, torn seam running down the middle — and Lauren
   turned it down on sight: "i want the about section to remain how it was."
   Don't rebuild it. Two things it turned up that are worth keeping if it ever
   comes back: a vertical seam needs its own generated tile (the wave tiles are
   480x80 and repeat on X, and a CSS mask layer cannot be rotated), and the nav
   over the photo's bright sky measured 1.4:1 against the cream links, so any
   design that puts the header over an unfrosted photograph needs a scrim. The
   full-bleed frosted layer below is what buys that here. */
.about-hero {
  position: relative;
  display: flex;
  align-items: flex-end;
  min-height: clamp(540px, 80vh, 760px);
  padding: 7rem 0 calc(1.2rem + var(--wave-h));
  overflow: hidden;
  background:
    linear-gradient(180deg, rgba(17, 78, 88, 0.32) 0%, rgba(17, 78, 88, 0.1) 18%, rgba(17, 78, 88, 0.08) 70%, rgba(17, 78, 88, 0.42) 100%),
    url("../images/about-hero-me4.webp") center 22% / cover no-repeat;
}
/* Teal frosted-glass layer over the photo */
.about-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  background: rgba(20, 86, 94, 0.34);
  -webkit-backdrop-filter: blur(1px);
  backdrop-filter: blur(1px);
  pointer-events: none;
}
.about-hero > .wrap { position: relative; z-index: 1; }
.about-hero-grid {
  display: grid;
  grid-template-columns: 1fr;
}
.about-hero-title {
  font-family: var(--font-heading);
  color: var(--cream);
  font-weight: 500;
  /* Tied to .club-hero-copy h1 — see the note there for why these two move
     together and why the clamp's min is left alone. This one is the easy half:
     left-aligned from the wrap edge, so it only grows rightward into 768px of
     empty hero. */
  font-size: clamp(2.268rem, 6.683vw, 5.123rem);
  letter-spacing: 0.03em;
  line-height: 1.05;
  text-align: left;
  margin: 0;
  text-shadow: 0 2px 18px rgba(10, 38, 44, 0.6);
}
.about-hero-welcome { display: block; margin: 0.3rem 0 1.4rem; }

@media (max-width: 820px) {
  .about-hero { min-height: 74vh; padding: 8rem 0 4rem; }
}

/* Split text + image */
.about-split {
  display: grid;
  grid-template-columns: 1.15fr 0.85fr;
  gap: clamp(2rem, 5vw, 4rem);
  align-items: center;
}
/* THE PHOTO COLUMN IS THE WIDER ONE ON THIS ROW — 2026-08-26. Lauren, of the
   butterfly photograph: "why are we making the frame smaller?" She was right and
   it was my error. She asked to widen the frame; I changed its RATIO to
   landscape but left the column at 0.85fr, so the box went 466x621 -> 466x388 —
   wider in shape and a third smaller in area. Widening a frame that is already
   capped by its column just makes it shorter.

   So the split flips on this row only: the photograph gets the larger share.
   1fr/1fr was the first step (548 each) and Lauren asked for bigger again, so it
   is now the MIRROR of the default 0.85/1.15 — the photo takes the share the
   copy has on every other row. At the 1160 wrap with its 64px gap that is
   630 x 525 against the 466x621 it replaced: wider, and larger in area, which
   the landscape ratio had cost on its own.

   630 IS THE CEILING HERE. Past it the copy falls under ~460px, which on this
   band is reversed-out white text on teal — the one place a short measure hurts
   most, because every line break costs more when the contrast is already
   working hard. The mount also bleeds -4.5%, so at 630 it reaches 28px past the
   column into a 64px gap; much wider and it starts crowding the text.

   The other .about-split rows are untouched. */
.about-split.reverse { grid-template-columns: 1.15fr 0.85fr; }
.about-split.reverse .about-photo { order: -1; }

/* Photos are MASKED, never rounded. A percentage border-radius always resolves
   to four elliptical quadrants meeting tangentially, so however mismatched the
   eight values are it reads as an oval — which is exactly what both of these
   photos were doing. The generated blob paths have real torn contours.

   Two different blobs, so the page doesn't repeat one silhouette: -a for the
   upright My Story photo, -b for the reversed teal-band one. A box-shadow is no
   use on a masked element (it follows the element box and gets sheared off), so
   the depth comes from .painted-halo pooling behind it instead. */
/* `:not(.deco)` matters here and is not defensive tidying — a bare
   `.about-photo img` also matches any decoration placed inside the figure, and
   .teal-band-bfly duly rendered at `width: 100%` of the figure WITH the photo's
   blob mask cut out of it: a 330px butterfly lying across the picture. Same
   family of trap as the `> *` rules that capture a .deco and drag it back into
   flow. Any broad descendant selector on a figure that holds art needs this. */
.about-photo img:not(.deco) {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 380px;
  margin-inline: auto;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  -webkit-mask: url("../images/art/photo-blob-a.svg") center / 100% 100% no-repeat;
          mask: url("../images/art/photo-blob-a.svg") center / 100% 100% no-repeat;
}
/* SQUARE, and lower — 2026-08-26. Lauren, of the butterfly photograph that
   replaced the forest one here: "move that photo down a little and maybe change
   the shape so it fits better."

   THE SHAPE IS THE REAL FIX. This picture is as wide as it is tall — arms out,
   wings out, symmetrical — and the 4:5 portrait it inherited was cutting the
   ends off both. It is the only photo on the site shaped like this, so it gets
   its own ratio rather than the page's default.

   The 4:5 is still the default and still load-bearing for the OTHER About photo,
   which is why this is scoped to `.reverse` and not written on `.about-photo`.
   Two things have to move together with it, and forgetting either shows
   immediately:
     · the mount's inset below, which is derived from the aspect;
     · the file itself. `object-fit: cover` would otherwise centre-crop the 4:5
       source to square and take 20% off the height — and in this frame that is
       her head and the dog's feet. images/about-butterfly.webp is authored 900
       square, cut head-to-paws, because the subject spans 0.15 to 0.82 of the
       original: the square could not be made SMALLER than that without losing an
       end, so the crop width was set by the height rather than chosen.

   MARGIN-TOP, not `align-self`. The photo is deliberately top-aligned on this
   band at >=901px so the sweep of `.finding-leaves` shows below it — see that
   rule. Centring it would undo that. This nudges it down and leaves the leaves
   alone. */
.about-split.reverse .about-photo img:not(.deco) {
  /* 3:4 — THE SOURCE'S OWN RATIO, so this photograph is not cropped at all.
     It went 4:5 (inherited) -> 1:1 -> 4:5 -> here across four rounds of "more of
     the pic", and this is the end of that road: 3024x4032 IS 3:4, so the frame
     now shows the entire frame the camera took. There is nothing left to zoom
     out to. If it still wants to read smaller, the lever is the shape or the
     column, not the crop.

     Square was the wrong turn in the middle of that. This photograph is as wide
     as it is tall, so a square box looked like the right fit — but fit was never
     the ask; it shows only 75% of the source height. The SHAPE is what makes
     this not-a-rectangle. The ratio does not have to help. */
  /* 6:5 LANDSCAPE — "lets widen the frame so the butterfly wings fit".
     The right move, and for a reason worth writing down: the wings are
     HORIZONTAL and everything expendable in this frame is VERTICAL — sky above,
     grey platform below. A portrait frame spends its crop on the wings and keeps
     the waste; a landscape one does the opposite. Nothing about the export or
     the mask could fix that, because the wings run to the edge of the camera
     frame.

     This has been 4:5 -> 1:1 -> 4:5 -> 3:4 -> here. 3:4 was the whole uncropped
     photograph and was still wrong, which is the tell that "show more of it" was
     never really the ask — the SHAPE of what is shown was.

     The crop is baked into the file, centred at 36% of the height rather than
     the middle, which is what keeps her hands and the dog's head in while the
     platform goes. Keep it in the file rather than reaching for
     `object-position`: every other photograph on this site is cut by its own
     export, and the two ways of doing it drift apart. */
  aspect-ratio: 6 / 5;
  /* A LITTLE ZOOMED OUT, without touching the frame — "are we able to zoom out
     a little but still keep the frame".
     
     The frame is fixed at 6:5 and the picture already runs the full width of the
     source, so there is nothing left to uncrop sideways. What is croppable is
     HEIGHT: at 6:5 the box was taking 62% of the frame's height.
     
     Insetting the picture at the SIDES ONLY makes its content box narrower —
     554x525, a ratio of 1.056 — and a taller box out of the same source crops
     less height: 71% now. So the zoom-out is bought with width that was only
     ever cream anyway.
     
     AND IT DOES NOT READ AS A MAT, which is what killed the last attempt at
     this: 6% at the sides lands inside the torn deckle, so it shows up as the
     border being slightly wider left and right, not as a photograph sitting on a
     card. Push it past ~8% and it separates — 60px was tried and the deckle goes
     visibly fat, which undoes "the border a bit thick".
     
     THE FILE MUST MATCH 1.056, not 6:5. It is exported at that ratio so `cover`
     is an exact fit; leave it at 6:5 and the browser crops it a second time,
     inside a box that only exists to stop cropping. */
  padding: 0 6%;
  background-color: var(--cream);
  /* BIGGER — Lauren: "make the shape bigger." The shared rule caps every About
     photo at 380px, and this one's grid column is 466 wide at the 1160 wrap, so
     it was leaving 86px of its own column empty. `100%` fills the column and
     goes on filling it at any width, rather than pinning a second magic number
     next to the first.

     The mount bleeds -7% horizontally, so at 466 it now reaches ~33px past the
     column — the grid gap is 64px, so it still clears the copy by ~31px. Check
     that if the gap or the column split ever changes.

     The FILE had to grow with it: 466 x 2 for retina is 932, and the old export
     was 820 wide, so it would have softened on a good screen. It is 940x1175
     now, from the 3024x4032 original, which has plenty of headroom. */
  max-width: 100%;
  /* THE MAT CAME OFF, 2026-08-26 — "lets do normal size photo". For one round
     this img carried `padding: 12% 9%` and a cream background, so the photograph
     sat inset on a torn mat and the blob stopped cutting it. It worked, and it
     is worth knowing why it is gone: it turns a blob-cut photograph into a
     rectangular print, because no padding can hide a rectangle's corners behind
     a shape whose narrowest radius is 0.36 of the box. Widening the frame solves
     the same complaint without that trade — see the ratio below. */
  /* photo-blob-D, not -b — Lauren: "lets make the shape more abstract." The
     other four masks on the site are rough circles (wobble 0.03 on a power-2.4
     superellipse); this one is a few big lobes on a power-1.7 one, generated by
     the same script. The seed was picked by compositing six candidates over this
     photograph: her hands reach almost to both edges and four of the six put a
     notch through one. See the note at the foot of .claude/make-photo-masks.py.

     IT IS ONLY FOR THIS PHOTO. A shape this irregular works because the subject
     is centred and symmetrical with room around it; on the other photos, which
     are framed tighter, it would eat them. */
  -webkit-mask-image: url("../images/art/photo-blob-d.svg");
          mask-image: url("../images/art/photo-blob-d.svg");
}

.about-split.reverse .about-photo { margin-top: clamp(1rem, 3.5vw, 3rem); }

/* My Story — the DARK teal, to match the heart rock on the home page, on
   Lauren's call. It sits on bare paper, so the pale --panel-teal it started on
   barely registered against the ground. */
.about-photo::before {
  --mount: var(--teal-deep);
  --rim: url("../images/art/photo-rim-a.svg");
  inset: -5.6% -7%;        /* both About photos measure 4/5 */
}
/* White, not a colour, on Lauren's call — this is the one mount that sits on a
   dark ground, and the teal band is where every other reversed-out element on
   the page is cream too. */
.about-split.reverse .about-photo::before {
  --mount: var(--cream);
  /* Same seed as the blob above, so the mount traces THIS shape rather than a
     second unrelated one — that is the whole convention of the -rim files. */
  --rim: url("../images/art/photo-rim-d.svg");
  /* THINNER, and the 7% the other photo uses is not the right number for this
     one — Lauren: "the border on that frame a bit thick". Two reasons it reads
     heavier here even though it is the same percentage: this photo is 466px wide
     against the other's 380, so 7% is 33px rather than 27; and the torn rim's
     wobble is deliberately larger than the blob's, so the border BREATHES rather
     than sitting at its mean. Measured across the full outline at 466x621:

        inset   border min / mean / max
         7.0%    15.5 / 27.5 / 38.1 px      <- was this
         4.5%     6.2 / 16.8 / 26.0 px      <- is this
         3.5%     2.6 / 12.5 / 21.2 px
         2.5%    -1.1 /  8.2 / 16.4 px      <- mount vanishes behind the photo

     4.5% is about as thin as this pair goes before the deckle pinches shut
     somewhere, which reads as a mistake rather than as a hand-torn edge. If it
     needs to go thinner than this, lower the RIM'S WOBBLE first (photo-rim-d in
     make-photo-masks.py) so the min and the mean converge — do not just keep
     cutting the inset.

     The vertical figure is still the horizontal one divided by the aspect, as in
     the rule above: at 3:4 that was 4.5 / (4/3) = 3.4, and at 6:5 it is
     4.5 / (5/6) = 5.4. It goes UP when the frame goes landscape, which is easy
     to get backwards — the divisor is height-over-width, and that is now less
     than one. This derivation has to be re-run every time the ratio moves. */
  inset: -5.4% -4.5%;
}

/* My Story — was an even 50/50 split with the tree photo filling its half. The
   photograph moved to "Why I Started Lumi Libra" on 2026-08-24, so the grid is a
   single column and the copy is centred: "center the text for the my story
   section perhaps".

   .about-split-solo carries a MEASURE, and that is the part that matters. Left
   at one full-width column the paragraphs run the whole 1260px wrap — about 150
   characters a line, roughly twice a comfortable measure — and centring makes
   that worse rather than better, because every line then starts at a different
   x. 780px matches .about-origin, which is the page's other centred block. */
.about-mystory { position: relative; }
.about-mystory .about-split { position: relative; z-index: 1; grid-template-columns: 1fr 1fr; }

.about-split-solo {
  grid-template-columns: 1fr;
  justify-items: center;
}
.about-mystory .about-split.about-split-solo { grid-template-columns: 1fr; }
.about-split-solo .about-copy {
  max-width: 780px;
  margin-inline: auto;
  text-align: center;
}
.about-split-solo .about-copy .about-title { text-align: center; }
/* `:not(.deco)` is not tidying — a bare `.about-photo img` also matches any
   decoration placed inside the figure. Without it the corner butterfly was
   forced to the photograph's own 620px height and rendered as a 315x630 smear
   across the copy. Same family of trap as the `> *` rules that capture a .deco
   and drag it back into flow. */
.about-mystory .about-photo img:not(.deco) { max-width: none; }

/* 620 from 560 on 2026-08-05, Lauren's "a little bigger". The ceiling is its own
   grid column: at 620 the photo is 496 wide against ~550 of column at 1280, so
   there is room, and the height is what drives it because the width follows from
   `aspect-ratio: auto` on a fit-content figure. */
@media (min-width: 901px) {
  .about-mystory .about-photo img:not(.deco) {
    height: 620px;
    aspect-ratio: auto;
    object-fit: cover;
  }
}

/* The eight `.about-fly` butterflies were removed on 2026-08-05. They were
   `big-butterfly.webp` — the watercolour Style 1 art — repeated eight times down
   one page at opacity 0.16 behind the copy, which is three things the decoration
   brief rules out at once: one drawing reused throughout, large faded shapes
   sitting under text, and a style the site moved away from when Lauren's own
   `new decor/` set arrived. The page's decoration is `.deco` pieces now, placed
   individually below. */

.about-thankyou .wrap { position: relative; z-index: 2; }

/* Narrow text blocks */
.about-narrow { max-width: 680px; }
.about-narrow.center { margin-inline: auto; text-align: center; }
.about-narrow.center .about-title { text-align: center; }

.about-origin {
  max-width: 780px;
  position: relative;
  z-index: 1;
}

/* BARE PAPER — the page's quiet moment between the teal band above it and the
   scrap below. The continuous ground is all the colour it needs, and whitespace
   is part of the design.

   IT SPENT PART OF 2026-08-24 AS A PHOTO BAND, carrying the tree-rays picture
   from My Story, and came back. Not because it looked wrong on its own but
   because of what it did to the page: About ended up with THREE full-bleed photo
   bands — the hero, this, and the closing — and a stack of full-width bands is
   what makes a layout read as horizontal stripes. This was the newest of the
   three and the one whose section had a reason to stay quiet.

   TO PUT IT BACK, everything is here:
     - asset images/about-origin-bg.webp already exists (2000x1333, cropped off
       `tree rayy.jpeg` at y995-3011, brightness 0.72, q72)
     - add `torn-top torn-bottom` to the section in the markup
     - padding: calc(var(--section) + var(--wave-h) + 2.5rem) 0
                calc(var(--section) + var(--wave-h) + 1.5rem)
     - overflow: hidden
     - background: a smooth bell 0.30 -> 0.55 -> 0.66 -> 0.68 -> 0.66 -> 0.50 ->
       0.32 of rgba(14, 52, 60, a) over the asset at `center 50% / cover`
     - .about-title { color: var(--cream) }
     - .about-origin p { color: rgba(250,250,248,0.96); font-weight: 700 }
       with the two text-shadows
   That combination measured 3.83:1 worst case, which clears the 3.0 that 19px
   BOLD needs — the weight is load-bearing, at 600 the same scrim failed. Do not
   re-derive the scrim by eye if it goes back; it was fitted to that photograph
   and to this section's copy. */
/* THE TOP PADDING IS SHORTER THAN THE BOTTOM ON PURPOSE, 2026-08-25. Lauren:
   "can you move why i started lumi just a little higher in that section". The
   heading carries no margin of its own, so this padding is the only thing
   holding it down — 4.5rem put 72px between the teal band's edge and the "W".

   ONLY THE TOP MOVED. The bottom keeps the full --section, because it is what
   separates this section from the Beyond panel below it, and that gap is doing a
   different job. Written longhand rather than as `var(--section) 0` so the two
   can differ.

   There is no wave to clear here: the band above is `torn-bottom`, so its wave
   is masked out of ITS OWN box and bites upward, not down into this one. That is
   why this can come down where the sections that follow a torn TOP edge cannot. */
.about-origin-section {
  position: relative;
  padding: 3.2rem 0 var(--section);
}

/* RESTORED 2026-08-24 after being lost in an edit — this rule sat between the
   section rule above and the `p + p` below, and a replacement that spanned both
   took it with it. The heading rendered left-aligned with no bottom margin for
   one round. */
.about-origin .about-title { text-align: center; margin-bottom: 1.6rem; }

/* Centred, 2026-08-24: "can you center why i started lumi libra". The BLOCK was
   already centred — 780px with 250px either side — so this is the text inside
   it, which was left-aligned under a centred heading.

   It matches My Story at the top of the page, which was centred earlier the same
   day when its photograph moved out. Those are now the page's two full-width
   prose sections and they read as a pair. The 780px measure is what makes this
   safe: centred text needs a short line or every line starts at a different x,
   and 780 is about 95 characters — the same measure My Story kept. */
.about-origin { text-align: center; }

.about-origin p + p { margin-top: 0.95rem; }

/* RESTORED 2026-08-24 — "i also want to add back the decor i had in that
   section". These came off earlier the same day and went back when the section
   returned to bare paper: they are teal line art, which reads on paper and
   disappears on a photograph, so the two changes belong together. Recovered from
   commit bffaccf rather than rewritten, so the measured values below are the
   originals rather than a re-derivation.

   THE VINE STAYS OUT. The section's third piece was the lower half of the
   band-foot crossover, the leaves overlapping down from the dark teal band. It
   was raised when these two went back, because it cannot return alone — its
   white half in that band above was removed separately — and Lauren's answer was
   "we can leave that out". So the crossover is retired on this page, both halves,
   and this section's decoration is the butterfly and its trail only. */

/* ---------- Why I Started Lumi Libra — blue sketch butterfly ----------
   Lauren: "a blue sketch bfly, facing right, tilted up to the left on the right
   side… at an angle from the text 'matters'."

   `bfly-blue-side.webp` is drawn facing RIGHT — head and antennae at the right,
   wings sweeping up and back to the left — so facing it left takes a scaleX(-1).

   Order matters: scaleX is written AFTER rotate, which means it applies FIRST.
   The drawing is mirrored, and the rotation then reads in screen space. Written
   the other way round the rotation would happen first and the mirror would flip
   the angle's sense with it, tipping the butterfly the opposite way.

   The tilt is negative because rotation is about the element's CENTRE, so an
   anticlockwise angle lifts the LEFT end and drops the right. Mirrored, the left
   end is now the HEAD — so -10deg lifts its head and nose up to the left, which
   is the gesture asked for.

   It lives out in the section's right margin, which is 250px of clear paper
   beside a 780px column, so it needs no room from the copy at all. */
.origin-matters { position: relative; }

/* ---------- Why I Started Lumi Libra — blue sketch butterfly ----------
   Lauren: "a blue sketch bfly, facing right, tilted up to the left on the right
   side… at an angle from the text 'matters'."

   `bfly-blue-side.webp` is drawn facing RIGHT — head and antennae at the right,
   wings sweeping up and back to the left — so facing it left takes a scaleX(-1).

   Order matters: scaleX is written AFTER rotate, which means it applies FIRST.
   The drawing is mirrored, and the rotation then reads in screen space. Written
   the other way round the rotation would happen first and the mirror would flip
   the angle's sense with it, tipping the butterfly the opposite way.

   The tilt is negative because rotation is about the element's CENTRE, so an
   anticlockwise angle lifts the LEFT end and drops the right. Mirrored, the left
   end is now the HEAD — so -10deg lifts its head and nose up to the left, which
   is the gesture asked for.

   It lives out in the section's right margin, which is 250px of clear paper
   beside a 780px column, so it needs no room from the copy at all. */
.origin-matters { position: relative; }

.origin-matters-bfly {
  /* Negative right: the paragraph ends at x1030 and this sits beyond it, out in
     the page margin, up and to the right of the word. */
  right: -19.5%;
  /* 38 -> 5, i.e. 33px DOWN, 2026-08-17. Not a nudge: the copy edit "We know
     moving our bodies is good for us" -> "can be good for us" pushed this
     paragraph from two lines to three, and "matters." now sits ALONE at the
     start of line 3. The butterfly is anchored off the paragraph's bottom so it
     tracks the last line, but the last line moved a line further down while the
     drawing kept the same offset, and it ended up beside lines 1-2 with 65px of
     air between it and the word it was placed against.

     Re-derived from the painted geometry rather than guessed. Before the
     reflow the butterfly's painted centre sat 32px ABOVE the word's centre,
     which is the "up and to the right" the comment above describes. Measured
     after: word centre y3641, painted centre y3576, so 33px down restores the
     same 32px lift. The trail below moves by the same 33 or the pair separates.

     A widow is the real cause and it is still there — "matters." on its own
     line. Raised with Lauren. If that line ever fills again, this constant and
     the trail's both go back to 38 and -192. */
  bottom: 5px;
  /* 130px where the blue side-view took 105. bfly-teal-open is a wide, shallow
     drawing (360x246 against 320x355), so an equal WIDTH would have read as a
     much smaller butterfly — matched on painted area instead. */
  width: min(130px, 17%);
  opacity: 0.9;
  /* Positive angle = tilted right. No mirror: this drawing is a symmetric
     open-winged butterfly, so the tilt alone gives it direction, where the
     side-view it replaces needed a scaleX to face left at all. */
  transform: rotate(12deg);
}

/* The flight path below it, stood on end so it descends the margin.

   -90deg rather than +90: the drawing runs left-to-right with its loop near the
   RIGHT-hand end, so turning it anticlockwise brings the loop to the TOP, right
   under the butterfly, and lets the plain trail fall away beneath it. Rotated
   the other way the loop would end up at the bottom, 300px from the butterfly it
   belongs to.

   Kept at 300px and 0.75. A dotted line is the record of a butterfly's
   movement, so it is a supporting mark and never a feature — but it does NOT get
   quiet by fading. A thin dashed line loses its colour to transparency far
   faster than a leafy sprig: this teal reads as pale grey below about 0.6.
   Restraint here comes from size. */
.origin-matters-path {
  /* Aligned on the butterfly's PAINTED axis, not its box centre. The two boxes
     already agreed to within 3px, but neither drawing sits centred in its own
     frame — the butterfly's body is over to one side and the trail's dots to the
     other — so matching boxes left the trail visibly hanging off to the left. */
  right: -40%;
  /* -192 -> -225, the SAME 33px down the butterfly moved on 2026-08-17. These
     two are one drawing in two files; move either alone and the trail stops
     meeting the butterfly's tail. */
  bottom: -225px;
  width: min(300px, 38.5%);
  opacity: 0.75;
  transform: rotate(-90deg);
}


/* DELETED 2026-08-25 — `.about-copy .story-turn` and `.about-copy .story-turn + p`.
   About has no script pull-quote left. "Why I Started" lost both of its own on
   2026-08-19 when Lauren rewrote it, and "Joy is a compass." — the last one, in
   My Story — was cut on 2026-08-25, her call: the phrase was carrying three
   placements and she kept the home band and the 1:1 heading instead.

   The rules went with the markup rather than being left behind, which is the
   standing rule this same block spelled out in August: a rule with no markup is
   what silently captures a later class of the same name.

   IF A TURN EVER COMES BACK ON THIS PAGE, the two things that took two passes to
   get right were: the container is `.about-copy`, NOT `.about-col` (the
   two-column panel further down) — written against `.about-col` the selector
   matched nothing and the line rendered on the generic `.script` margins, 0 top
   and 1.05rem bottom, for two months without anyone noticing it had never had
   the air it was written to have. And the margin below has to be declared for
   the FOLLOWING paragraph too, or `.about-copy p`'s own 1.05rem bottom margin is
   all the air the beat gets on that side. It was `margin: 1.9rem 0` with
   `line-height: 1.35`, plus `1.9rem` margin-top on the adjacent paragraph. */

.about-origin-butterfly {
  position: absolute;
  right: -2%;
  top: 8%;
  width: min(230px, 22vw);
  opacity: 0.12;
  transform: rotate(-14deg);
  pointer-events: none;
}

.about-origin-butterfly-left {
  display: none;
}

@media (min-width: 761px) {
  .about-origin-butterfly-left {
    display: block;
    position: absolute;
    left: -5%;
    bottom: -14%;
    width: min(300px, 28vw);
    opacity: 0.12;
    transform: rotate(18deg);
    pointer-events: none;
  }
}

@media (max-width: 760px) {
  .about-origin-section { padding: 2.8rem 0 3.8rem; }
  .about-origin-butterfly {
    right: -5%;
    top: -2%;
    width: 180px;
    transform: rotate(-20deg);
  }
}

/* Heart list */
.about-list { list-style: none; margin: 1.2rem 0 1.4rem; }
.about-list li { position: relative; padding-left: 1.9rem; margin-bottom: 0.55rem; font-size: 1.132rem; }
/* DORMANT — no page carries .about-list any more. Kept in step with the others. */
.about-list li::before { content: "\2665"; position: absolute; left: 0; color: var(--heart, var(--teal)); font-size: 0.92em; }

/* Pillars row */
.about-pillars {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: clamp(1.5rem, 4vw, 3rem);
  margin-top: 2.6rem;
}
.about-pillars figure { margin: 0; text-align: center; width: 110px; }
.about-pillars img { width: 92px; height: 92px; object-fit: contain; margin: 0 auto 0.5rem; }
.about-pillars figcaption { font-family: var(--font-script); color: var(--teal); font-size: 1.013rem; }

/* A few things cards */
.about-cards {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1.4rem;
  margin-top: 2.6rem;
}
.about-card {
  background: var(--white);
  border-radius: var(--radius);
  padding: 1.6rem 1.3rem;
  box-shadow: 0 5px 18px rgba(31, 94, 92, 0.06);
}
.about-card .ac-ic { display: block; color: var(--teal); margin-bottom: 0.7rem; }
.about-card .ac-ic svg { width: 30px; height: 30px; }
.about-card p { font-size: 0.999rem; line-height: 1.65; }

/* WAS BARE PAPER. On 2026-08-24 Lauren asked for me10 behind this closing
   section — her lying in the pine needles looking up, which suits a sign-off
   better than anything else in the library.

   THE ASSET is images/about-thanks-bg.webp, 2200x1242 off `me9.jpg` cropped
   y1150-2858 — her lying in the pines with the sun flaring through them.

   NOTE THE FILENAME. There are two me9 files in the repo root and they are
   different photographs: `me9.jpeg` is her standing in an autumn wood with an
   arm raised, and `me9.jpg` is this one. Both are 3024x4032 portrait files with
   no EXIF rotation, so nothing but opening them tells them apart — but in THIS
   one she is lying down, so the SUBJECT runs horizontally and a wide band holds
   her whole figure. That is what makes it the one for this section; the standing
   shot had to be cut off at the waist to fit.

   Two earlier attempts, both recorded in case either is wanted back:
     - me9.jpeg  crop y620-2328, resize 2200x1242, brightness 0.92, q70
     - me10.jpeg crop y300-2578, resize 2400x1356, brightness 0.92, q72

   230KB, against 620 for the standing shot — this crop is mostly soft bokeh and
   shadow rather than the dappled backlit foliage that made the other one so
   expensive. */
.about-thankyou {
  position: relative;
  text-align: center;
  padding: calc(var(--section-airy) + var(--wave-h)) 0 calc(var(--section-airy) + 1rem);
  /* `clip`, NOT `hidden`, AND THIS IS WHAT MADE THE PARALLAX WORK. Found
     2026-08-24: the drift below was measured, guarded and shipped, and it never
     ran once. `overflow: hidden` makes an element a SCROLL CONTAINER — a
     scrollport that simply cannot be scrolled — and `animation-timeline: view()`
     resolves against the subject's nearest ancestor scroll container. That was
     this section, which never scrolls, so the timeline sat at exactly 50%
     progress at every scroll position and the photograph held still.

     Nothing reported a fault. `getComputedStyle` returned the right
     animation-name and timeline, `document.getAnimations()` found the animation
     and called it running, and every contrast measurement passed. The only
     symptom was a progress that read 0.4999859 at the top of the page and
     0.4999859 at the bottom.

     `overflow: clip` clips identically and does NOT create a scroll container,
     so the timeline resolves against the document and the drift runs. The
     `hidden` above it is the fallback for browsers without `clip`; they lose the
     drift to the @supports guard anyway, so they only need the clipping. */
  overflow: hidden;
  overflow: clip;
  /* WEIGHTED TO THE FOOT, not a bell — and that is the difference between this
     band and the other three. Here the reversed-out copy is not in the middle:
     "Thanks for stopping by." and the signature sit at 77-90% of the band, BELOW
     the card, so the darkness has to be spent down there instead.

     Measured on the real composite, worst pixel under those two lines:

       0.30 -> 0.56 -> 0.72   7.84:1              54% of the photo
       0.24 -> 0.40 -> 0.54   5.70:1              66%
       0.20 -> 0.32 -> 0.46   4.92:1   <- here    72%
       0.16 -> 0.26 -> 0.38   4.36:1   FAILS      77%

     THIS IS THE LIGHTEST SCRIM ON THE SITE and it is earned rather than a
     relaxation of the standard. Where this band's copy sits — 77-90% down, below
     the card — the picture is her dark hair and shadowed ground, so very little
     veil buys a lot of contrast. The bands that need 0.5-0.7 have bright foliage
     or pale flowers under their type.

     4.5 IS THE BAR HERE, not the 3.0 the other bands got away with. Checked
     rather than assumed: `.thanks-lead` is 21.1px at weight 500, which clears
     neither the 24px nor the 18.66px-and-bold route to "large text", so it needs
     full AA. (`.about-sign` beside it is 25.9px and would have passed at 3.0 —
     the stricter of the two sets the value.)

     RE-MEASURE WHENEVER THE PHOTOGRAPH CHANGES. This section has had three now,
     and the same stops gave 4.63, then 4.20, then 7.84 across them — a scrim is
     fitted to its picture, not to its section.

     The card's own copy is unaffected throughout: 5.22 to 5.28 across every
     option, because 72% white swamps whatever is behind it. */
  /* NO BACKGROUND ON THE SECTION ITSELF. The photograph and the scrim are two
     separate layers below, because the photograph has to MOVE and a background
     layer cannot be transformed on its own. Order is fixed by the painting
     rules: an element's own background paints beneath its pseudo-elements, so
     putting the scrim here would bury it under the picture. */
}

/* The photograph, on a picture file cut TALLER than the band rather than on an
   enlarged copy of a shorter one. That distinction is the whole third pass.

   THE FIRST TWO PASSES BOUGHT TRAVEL BY OVERSIZING THIS LAYER, WHICH IS ZOOM.
   `cover` fits the image to this box, so making the box taller scales the
   picture up and crops it in from the sides — the drift got longer and the
   photograph got tighter in exactly the same move. Lauren, looking at three
   sizes side by side: "i dont want zoomed in, i want the scroll effect". She is
   right, and it was the wrong trade to have made twice.

   THE ASSET is images/about-thanks-bg-tall.webp, 2200x1490 — the same crop as
   about-thanks-bg.webp, extended symmetrically. Recipe, and it reproduces:

     me9.jpg  ->  crop (0, 980, 3024, 3028)     2048 rows, centred on 2004
              ->  resize 2200x1490              (0.72751, same as the original)
              ->  GaussianBlur(6.0)
              ->  brightness 0.9154
              ->  WEBP quality 72               55KB, against 46 for the short one

   The blur and brightness were not guessed; they were solved by fitting the
   shipped file against the preserved crop in images-original/, and land within
   1.2 grey levels. The 1708-row original crop is the middle 1242 rows of this
   one, so THE BAND AT REST IS THE SAME PICTURE AT THE SAME SIZE: 81.2% of the
   source width is visible either way, and the worst pixel under the closing
   copy is 7.20:1 with this file against 7.17 with the old one.

   150px OF SLACK EACH WAY, in real pixels rather than a percentage, because the
   throw is now a real pixel count too and the two have to match exactly. The
   script never exceeds it, so no edge is ever exposed.

   Measured across the whole 300px of travel, worst pixel under `.thanks-lead`:

     at rest              7.20:1
     +/-120px  (240px)    4.88:1
     +/-150px  (300px)    4.88:1     <- here, against the 4.5 this band needs

   The two are equal because the worst pixel is found well inside the range
   rather than at its ends. Past 150 the margin does start to close, and the
   next thing to give would be the scrim rather than the crop. */
.about-thankyou::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  /* THE FULL EFFECT, RESTORED. `fixed` pins the photograph to the viewport, so
     the band scrolls over a picture that stays put — the whole height of the
     window's worth of relative movement, not the 300px a transform could buy.
     No oversize and no transform: the background is sized to the VIEWPORT here,
     so there is nothing to enlarge and nothing to drift.

     THIS WAS REMOVED EARLIER ON 2026-08-24 AND THE NOTE SAID NOT TO RE-TRY IT.
     That note was right about the contrast and wrong about the conclusion: see
     ::after below, where 20% more scrim buys the whole effect back. Lauren, on
     the small-drift versions that replaced it: "i dont understand this isnt
     workig at all, and in my other chat it was full blowin working before it
     switched over". This is the one she is describing. */
  background: url("../images/about-thanks-bg-tall.webp") center 50% / cover no-repeat fixed;
}

/* THE SAME SWAP AS `.home-joy::before`, 2026-08-26 — a composited fixed LAYER in
   place of a fixed background, because the latter repaints on the main thread
   every frame and that is the shakiness Lauren reported. Scoped to the pointer
   query rather than written into the rule above, so every narrower width and
   every touch device keeps exactly the box it had: this ::before is not
   media-gated up there, and `position: fixed` leaking down to the phone rules
   would pin a picture that is supposed to scroll. */
@media (min-width: 761px) and (hover: hover) and (pointer: fine) {
  .about-thankyou { clip-path: inset(0); }

  .about-thankyou::before {
    position: fixed;
    inset: 0;
    background: url("../images/about-thanks-bg-tall.webp") center 50% / cover no-repeat;
  }
}

/* BELOW THE PARALLAX WIDTH, THE OLD FILE AND THE OLD SLACK. The script does not
   drive a band under 1101px, so a phone needs no room to move — and it must not
   get any, because the crop is what the scrim was fitted to. This keeps every
   width below the breakpoint pixel-identical to what it was before the tall
   asset existed. Only one of the two files is ever fetched: a browser does not
   download a background image for a rule whose media query does not match. */
/* NOT ON A TOUCH DEVICE. `background-attachment: fixed` is either ignored or
   badly janky on iOS Safari and Android Chrome, so wherever the pinned rule does
   not apply the band goes back to a plain scrolling background — the short asset
   at the same 8% box it has always had, which is what the mobile measurements
   were taken against. `scroll` has to be stated; it would otherwise inherit
   `fixed` from the base rule above.

   THIS BAND IS THE ONE THAT NEEDS A NEGATIVE QUERY, because it is the only one
   whose BASE rule carries `fixed` — the other four declare it inside their gate
   and simply fall back to their own base. So this list has to be the exact
   opposite of `(min-width: 761px) and (hover: hover) and (pointer: fine)`, and a
   comma list is an OR: narrow, OR no hover, OR a coarse pointer. Written this
   way rather than as `not (...)` because a Level 3 comma list is understood
   everywhere and this rule failing open means the photograph disappears on
   phones. Keep it in step with the `::after` gate above. */
@media (max-width: 760px), (hover: none), (pointer: coarse) {
  .about-thankyou::before {
    /* LONGHAND, NOT `inset`. The desktop rule above uses `inset: 0`, so this one
       has to put the oversize back — and `inset: auto 0` written AFTER `top` and
       `bottom` silently resets them, because a shorthand sets every one of its
       longhands whether you name them or not. That shipped for one edit and
       collapsed this layer to zero height: the photograph vanished, the scrim on
       ::after had nothing behind it, and the whole band rendered as a flat grey
       blob on every phone. Nothing errored. Never mix the two here. */
    top: -8%;
    right: 0;
    bottom: -8%;
    left: 0;
    background-image: url("../images/about-thanks-bg.webp");
    background-attachment: scroll;
  }
}

/* A PORTRAIT CUT FOR PHONES, 2026-08-24. Lauren: "i also want the mobile view to
   be zoomed out so more of the pic is visible". `cover` fills the box, so a
   landscape file in a 390x914 band showed a narrow vertical slice of it — 24% of
   the picture's width, mostly out-of-focus pines. This crop is cut to roughly
   the shape of a phone band, so 91% of its width survives: the sun flare, her
   whole figure, and the forest floor, instead of a sliver.

     me9.jpg  ->  crop (700, 0, 2600, 4032)      1900x4032, full height
              ->  resize 1400x2971
              ->  GaussianBlur(6.0)
              ->  brightness 0.9154
              ->  WEBP quality 72                79KB

   THE WHOLE FRAME WAS TRIED AND IS WORSE, which is not obvious from the numbers.
   A full-frame cut (3024x4032 -> 1400x1867) shows 70% of the picture's width
   against this one's 63%, so on paper it is the more zoomed-out of the two. But
   its aspect makes `cover` fit by HEIGHT, which centres the vertical window —
   and this photograph has Lauren across its middle, exactly where the card sits.
   The visible strips came back as treetops and forest floor with no subject in
   either. This crop is taller than the band, so `cover` fits by WIDTH instead:
   100% of its width survives AND the window sits low enough that her hair and
   dress show under the card. What matters is what lands in the strips the card
   leaves, not the percentage.

   760, NOT 1100, because between those widths the band is wide again and wants
   the landscape file. Same split `.home-joy` uses. */
@media (max-width: 760px) {
  .about-thankyou::before {
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    background-image: url("../images/about-thanks-bg-portrait.webp");
  }
}

/* ---------- PINNING ON PHONES ---------- 2026-08-25, second attempt, and this
   one holds. Tested on Lauren's iPhone: "that worked!". The first attempt is
   written up below; it failed two ways and this changes the mechanism to answer
   both:

     SHAKE was JavaScript. A rAF loop cannot keep pace with iOS momentum
     scrolling, so the layer landed a frame behind the finger. There is no script
     here — `animation-timeline: view()` is scroll-driven, run on the compositor,
     the same thread that makes native scrolling smooth.

     ZOOM was `cover` re-fitting when Safari resized the viewport under the URL
     bar. Nothing here is sized from a live measurement: the photo box is
     `100lvh`, the LARGE viewport, which is defined with the bar retracted and
     does not change while scrolling.

   TWO NESTED BOXES, AND THAT IS WHY IT IS REAL MARKUP. The outer is the BAND's
   height and carries the animation; the inner is the WINDOW's height and carries
   the picture. Travel has to be exactly (window + band), and `translateY(100%)`
   on the outer box is the only way to say "the band's height" in CSS. A
   pseudo-element cannot hold a child, and one box alone would travel
   (window + window) — which overshoots and uncovers a strip at the top of the
   band near the end of the pass. Checked before building: at 390 that gap
   reaches 92px.

   VERIFIED, not assumed: the picture's top edge measures 0 against the window at
   every scroll position while the band travels +844 to -742.

   Each band supplies its own file through `--pin-img` and turns off whatever
   paints its photograph normally, so the picture is painted once. */
.pin-photo { display: none; }

@keyframes pin-to-window {
  /* -100lvh at entry, when the band's top edge is at the bottom of the window,
     and +100% (of the BAND) at exit, when its bottom has left the top.

     --pin-shift IS ADDED TO BOTH ENDS, so it slides the whole travel without
     changing its length or speed — the parallax is identical, the picture just
     sits higher or lower throughout. Defaults to 0px, so every band that does
     not set it is byte-for-byte unaffected. Inherited, so a band sets it on
     itself and it reaches `.pin-photo` from there. */
  from { transform: translateY(calc(-100lvh + var(--pin-shift, 0px))); }
  to   { transform: translateY(calc(100% + var(--pin-shift, 0px))); }
}

@supports (animation-timeline: view()) {
  @media (max-width: 760px) and (prefers-reduced-motion: no-preference) {
    .pin-photo {
      display: block;
      position: absolute;
      inset: 0;
      z-index: 0;
      animation: pin-to-window linear both;
      animation-timeline: view();
      animation-range: entry 0% exit 100%;
    }

    .pin-photo > i {
      display: block;
      height: 100lvh;
      background: var(--pin-img) center 50% / cover no-repeat;
    }

    /* --- Home. Its ::before is the photograph at this width; it steps aside. --- */
    .home-joy { --pin-img: url("../images/home-joy-dark-tall.webp"); }
    .home-joy::before { display: none; }

    /* --- The club quote. Its photograph is on the SECTION, together with the
       scrim above it, so both come off and the scrim is rebuilt on ::after —
       otherwise the pinned layer would paint over the wash rather than under it.

       ITS OWN PHONE CROP, and this is worth as much as the pinning. `cover` in a
       390x844 window showed 23% of the landscape file's width, a slot through
       the middle of the wings. `monarch on flower.JPG` is a 1008x1792 PORTRAIT
       original and the shipped crop uses only 496 of its rows, so the whole
       frame at native size fits a phone almost exactly: 82% of its width
       survives. Written at 1008x1792, brightness 0.8762 to match the others, no
       upscale at all.

       Wash up 15%: pinned, the copy passes over the whole picture and comes back
       3.21:1 against the 3.0 it needs. x1.15 gives 3.88 for six points. --- */
    .club-quote {
      --pin-img: url("../images/club-quote-bg-phone.webp");
      background-image: none;
    }
    .club-quote::after {
      content: "";
      position: absolute;
      inset: 0;
      z-index: 1;
      pointer-events: none;
      background: linear-gradient(180deg,
        rgba(46, 30, 58, 0.28) 0%,
        rgba(46, 30, 58, 0.46) 22%,
        rgba(46, 30, 58, 0.55) 45%,
        rgba(46, 30, 58, 0.55) 62%,
        rgba(46, 30, 58, 0.41) 82%,
        rgba(46, 30, 58, 0.28) 100%);
    }
    .club-quote .wrap { z-index: 2; }

    /* --- The 1:1 middle section's share of this lives further down the file,
       beside its own rules: `.oto-do` is declared at the same specificity down
       there and would simply win. Search for "pin-photo" in the .oto-do
       block. --- */

    /* --- About's closing band lives further down, beside its own `::after`,
       which is declared later in the file and would otherwise win. Search for
       "pin-photo" in the .about-thankyou block. --- */
  }
}


/* ---------- DO NOT TRY TO PIN THESE ON PHONES ---------- 2026-08-25, tried and
   reverted after testing on Lauren's own iPhone over the local network.

   `background-attachment: fixed` is what pins the four bands above 1100px, and
   Safari on iOS has never supported it. The obvious workaround is to do it by
   hand: make the photo layer a window tall and shift it back by the band's own
   offset every frame. That was built (js/pin-photo.js, now deleted), it was
   correct — verified to the pixel, the layer's transform exactly cancelled the
   band's offset — and on a real iPhone it was unusable. Lauren: "ok yeah its
   shaky, and it also zooms in and out".

   TWO SEPARATE iOS BEHAVIOURS, neither of them fixable from CSS or a rAF loop:

     - SHAKE. iOS throttles frame callbacks during momentum scrolling, so the
       layer lands a frame or more behind the finger and the torn edges wobble.
       Rounding the transform to whole pixels helps the shimmer and does nothing
       for the lag.
     - ZOOM. Safari resizes the viewport as the URL bar hides and shows, so
       "a window tall" changes mid-scroll and `cover` re-fits the picture to a
       new box. `100lvh` was used precisely to avoid this and did not, because
       the LAYOUT viewport moves too.

   If this is ever wanted again the honest route is not another attempt at
   pinning — it is a different effect for phones, or none. Phones keep a plain
   scrolling photograph, which is what every band below 1101px does. */



/* THE CARD GOES TO THE TOP AND GETS TIGHTER, PHONES ONLY. Lauren: "for the
   mobile could we maybe make the text box more condensed and so it sits at the
   top of section". With the portrait crop above, the photograph finally fills
   the band — and a 520px card sitting in the middle of a 914px band covered the
   part worth seeing. Everything the card gives back is handed to the padding
   BELOW it rather than taken off the section, so the band stays about as tall
   and the reclaimed space becomes visible photograph.

   Roughly: card 520 -> 415 and its top moves 169 -> 100, so the picture below
   the sign-off goes from ~104px to ~290px, a third of the band instead of a
   ninth. Nothing here touches the desktop layout, where the card is not in the
   way of anything. */
@media (max-width: 760px) {
  .about-thankyou {
    padding-top: calc(var(--wave-h) + 0.2rem);
    /* The card is a fixed height, so this padding IS the photograph — every rem
       here is picture below the sign-off. Raised from 6rem on 2026-08-25 when
       Lauren asked to see more of the pictures on phones. */
    padding-bottom: calc(var(--wave-h) + 9rem);
  }

  /* The wrapper's own top margin is 3.2rem on desktop and it is the single
     biggest thing holding the card down the page. The butterfly is anchored to
     `top: 0` of this box and straddles it — half of it sits ABOVE the card — so
     this cannot go to nothing. At 1rem the card starts 76px down and the
     butterfly's top edge lands at 41, clear of the 30px torn wave above it.
     Any less and the two collide. */
  .about-thankyou .thanks-panel-wrap { margin-top: 1rem; }

  /* The card's own condensing is NOT here — it has to come after the base
     `.thanks-spark` rule further down the file to win the cascade, and it did
     not the first time. Same specificity means source order decides. */
}

/* The scrim, over the photograph. Same stops as before — see the long note
   above for how they were measured and why this band needs 4.5 rather than 3.0. */
.about-thankyou::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(180deg,
    rgba(14, 52, 60, 0.30) 0%,
    rgba(14, 52, 60, 0.28) 34%,
    rgba(14, 52, 60, 0.40) 62%,
    rgba(14, 52, 60, 0.54) 100%);
}

/* THE DEEPER WASH IS ONLY FOR THE PINNED EFFECT. `fixed` is what needs it —
   the copy passes over the whole picture, so the scrim has to cover the worst
   of it. Where the picture scrolls with the band the copy stays over the pixels
   the stops above were fitted to, so those widths keep the lighter wash and a
   brighter picture. Measured on the portrait crop at 390: 8.39:1 against the 4.5
   this band needs, so there is nothing to buy by going darker.

   The gate is a pointer and not a width — see `.home-joy::before`. It must stay
   in step with the `::before` fallback below, which is written as the OR of the
   same three terms; change one and change the other. */
@media (min-width: 761px) and (hover: hover) and (pointer: fine) {
  .about-thankyou::after {
    background: linear-gradient(180deg,
      rgba(14, 52, 60, 0.36) 0%,
      rgba(14, 52, 60, 0.34) 34%,
      rgba(14, 52, 60, 0.48) 62%,
      rgba(14, 52, 60, 0.65) 100%);
  }
}

/* ---------- The phone pinning, for this band ---------- The shared `.pin-photo`
   rules are earlier in the file; only the band-specific part is here, because
   `.about-thankyou::after` is declared just above at the same specificity and
   source order would otherwise win. That has now cost a round twice — once here
   and once on `.oto-do` — so: when adding a band to the pinned set, put its
   overrides AFTER its own rules, not beside the shared ones. */
@supports (animation-timeline: view()) {
  @media (max-width: 760px) and (prefers-reduced-motion: no-preference) {
  /* --- About's closing band. It was held back at first for a good reason and
     then fixed at the source rather than paid for.

     Pinned, the copy passes over the sunlit top of the frame instead of only
     the shaded ground, and "Thanks for stopping by." fell to 2.99:1. At
     17.9px and weight 500 that line needed the full 4.5, so buying it back
     took x1.5 on the wash — the photograph down from 63% to 44%, undoing the
     lightening Lauren had asked for the day before.

     THE LINE GOT BIGGER INSTEAD. At 24.8px it clears WCAG's large-text
     threshold and needs 3.0, not 4.5, which turns a 19-point bill into an
     8-point one:

       line 17.9px, wash x1.5   5.04:1   44% of the photograph
       line 24.8px, wash x1.1   3.14:1   59%   too thin a margin
       line 24.8px, wash x1.2   3.46:1   55%   <- here

     And it is the direction this site wants anyway; see
     [[lumilibra-type-legibility]]. The size change is in the phone block
     above, next to the card. --- */
  .about-thankyou {
    --pin-img: url("../images/about-thanks-bg-portrait.webp");
  }
  .about-thankyou::before { display: none; }
  .about-thankyou::after {
    background: linear-gradient(180deg,
      rgba(14, 52, 60, 0.36) 0%,
      rgba(14, 52, 60, 0.34) 34%,
      rgba(14, 52, 60, 0.48) 62%,
      rgba(14, 52, 60, 0.65) 100%);
  }
  }
}

/* PARALLAX, the SMALL-DRIFT version. Lauren: "you scroll and the picture kinda
   moves with the scroll, like it isnt stagnat".

   `background-attachment: fixed` was tried first and reverted. It pins the photo
   to the viewport, which means a line of text passes over the FULL viewport
   height of the picture as the page scrolls — so the scrim, whose stops are
   fitted to where the words are, no longer covers what is under them. Measured
   across the whole scroll range it took the two lines below the card from 6.26:1
   to 3.97, under the 4.5 this band needs. (The frosted card was fine at 5.17;
   72% white does not care what is behind it. It is reversed-out copy that
   breaks.)

   What is here instead moves the picture by a few hundred pixels rather than
   pinning it — 150px each way, 300px of travel end to end, spread over the
   (viewport height + band height) of scrolling that `entry 0% exit 100%` covers.
   The copy stays over pixels the scrim was measured against, and it was
   re-measured over the whole range rather than assumed: 4.88:1 against the 4.5
   this band needs.

   IT WAS 27px, THEN 53px, AND BOTH READ AS NOTHING. 54px of travel spread over
   ~1670px of scrolling is a rate of 3.2%, where parallax normally runs 20-50%;
   300px is 18% and is the first value that actually reads as movement. The two
   earlier attempts were held back by a mistaken belief that contrast was the
   limit here — it is not, and never was; see the table on ::before. The real
   limit was that travel was being bought with zoom, which capped it long before
   contrast did. A taller asset removes the cap entirely.

   NEITHER THE CSS SCROLL-TIMELINE NOR THE JAVASCRIPT THAT REPLACED IT SURVIVED.
   Both drove a small transform, and a small transform was never what was wanted.
   `background-attachment: fixed` is on ::before above; there is no script.
*/
/* THREE MECHANISMS LIVED HERE IN ONE DAY AND ALL THREE ARE GONE: an
   `animation-timeline: view()` keyframe, then the same motion driven by a small
   rAF script, then nothing. Keep the history, because each was ruled out for a
   different reason and it would be easy to walk back into any of them.

     - `animation-timeline: view()` never ran. `overflow: hidden` on the band made
       it a scroll container and the timeline resolved against a box that never
       scrolls, so progress sat at 0.4999859 forever. `overflow: clip` fixes that
       and is still in the file. Its other problem is unfixable here: it is newer
       than some browsers this site is read in, and its failure mode is silent.
     - The rAF script ran correctly everywhere and was still wrong, because the
       thing it drove — a few hundred pixels of transform — is not the effect.
     - What Lauren wanted, and had, is `background-attachment: fixed`.

   The real mistake underneath all three was buying travel by oversizing the
   photo layer, which is zoom: `cover` fits the picture to that box, so a taller
   box scales it up and crops it in from the sides. "i dont want zoomed in, i
   want the scroll effect." Under `fixed` the question disappears — the picture
   is sized to the viewport and never moves at all. */


/* The closing lines sit on the photograph rather than on the card, so they
   reverse out. This is the difference from .oto-do, where every word is on the
   paper and the type keeps its navy. */
.about-thankyou .thanks-lead,
.about-thankyou .about-sign {
  color: var(--cream);
  text-shadow:
    0 1px 2px rgba(18, 22, 30, 0.6),
    0 2px 16px rgba(18, 22, 30, 0.42);
}

/* The closing vine is teal line art on what is now a photograph. Knocked to
   white, the same device .hero uses on the home page. */
.about-thankyou .deco {
  filter: brightness(0) invert(1);
  opacity: 0.55;
}
/* 112px. It went 76 -> 88 when the drawing was swapped for the wider, shallower
   teal-and-purple one (400x248 against 480x347), where matching on width alone
   would have read as a smaller butterfly; 112 is Lauren's later call to make the
   closing mark bigger outright. */
/* Straddling the panel's torn top edge from 2026-08-17, at Lauren's ask: "move
   the butterfly so it overlaps the top of the box now". It used to sit in flow
   above the block with a 1.2rem margin under it.

   Positioned against `.thanks-panel-wrap` rather than against `.wrap`, so it
   tracks the PANEL. Anchored to the wrapper's top, which is the panel's top,
   because the panel's own margin is on the wrapper now — measure from anything
   further out and the piece drifts the moment the copy above it reflows.

   `translate(-50%, -50%)` with `top: 0` puts its centre exactly on the panel's
   box top. The box top is where the tear's CRESTS are and the wave bites down
   from there, so slightly more than half the drawing ends up on bare paper —
   which is the right way round for a piece that should look like it is landing
   on the panel rather than sinking into it. */
.about-thankyou .thanks-panel-wrap {
  position: relative;
  /* The panel's top margin lives here, not on the panel. It would collapse
     through this wrapper and land in the same place either way, but the
     butterfly is anchored to `top: 0` of this box — so making the margin
     explicit here keeps "the wrapper's top" and "the panel's top" the same
     thing by construction rather than by a collapsing rule. */
  margin-top: 3.2rem;
  /* SHRUNK TO THE CARD, 2026-08-24 — "move the teal and purple butterfly so it
     lays center". The butterfly was not off-centre on the page; it was at x640,
     dead centre. What moved was the CARD, which went to 37rem anchored left when
     the photograph came in, taking its centre to x356 — so a butterfly still
     centred on the full-width wrapper had drifted off the panel it is supposed
     to perch on, and sat over bare photograph instead.

     Fixing it on the wrapper rather than on the butterfly is deliberate: the
     butterfly is `left: 50%` of THIS box, so matching the box to the card makes
     the two track each other by construction. Give the card a different width or
     alignment again and the butterfly follows on its own. Setting an explicit
     `left` on the butterfly instead would have to be re-derived every time. */
  width: min(37rem, 100%);
}

.about-thankyou .thankyou-butterfly {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 112px;
  margin: 0;
  opacity: 0.95;
  pointer-events: none;
}
.about-thankyou h2 { font-size: clamp(1.539rem, 3.24vw, 2.106rem); margin-bottom: 1rem; }
.about-thankyou p { max-width: 40rem; margin: 0 auto 0.8rem; }

/* ---------- The Sunday Spark invitation under the sign-off, 2026-08-17 ----------
   Lauren: "i do want to make that a new little section with a button to click,
   but not replacing the thanks for stopping by. or maybe they get combined? and
   thanks for stopping by is smaller?"

   Combined, and the demotion is the thing that makes combining work. The
   section reads thanks -> signature -> invitation -> button, so the signature
   has to be the largest thing in it; leaving the h2 at its old
   clamp(1.539rem, 3.24vw, 2.106rem) put a heading above the invitation that
   competed with "Lauren ♡" and made the block read as two stacked sections
   rather than one close.

   It has to come AFTER `.about-thankyou h2` in the file, not just be more
   specific: `.about-thankyou h2` is one class plus a type, and
   `.about-thankyou .thanks-lead` is two classes, so specificity already wins —
   but the ordering is what keeps that true if either selector is ever
   simplified. */
.about-thankyou .thanks-lead {
  /* THE FLOOR AND THE CEILING BOTH GO ABOVE 24px, 2026-08-25, and this is the
     third time the same fix has been needed on this site — see the phone rule
     further down and `.spark-closing-script`. Under 24px a line at weight 500
     needs the full 4.5; at or above it, 3.0.

     It became load-bearing when the sign-off moved to sit under the card rather
     than under the page. That carried it 284px to the LEFT, onto the side of the
     photograph the sun flares through, and "Thanks for stopping by." fell from
     4.63:1 to 3.80. At 21.1px that failed; at 24.8 the bar is 3.0 and 3.80 has a
     real margin.

     It was also the odd one out: the phone rule already sets 1.55rem, so this
     line was SMALLER on a 1280 desktop than on a 390 phone. Now both are 24.8px
     and the clamp has nothing left to interpolate — kept as a clamp rather than
     a bare size so the shape matches every other type rule in this file. */
  font-size: clamp(1.55rem, 1.9vw, 1.55rem);
  font-weight: 500;
  margin-bottom: 0.35rem;
}

/* The rule above sets the size; this sets the ORDER. The signature is a
   `.script` span, which is inline, so it needs to become a block to sit on its
   own line under the smaller thanks. */
.about-thankyou .about-sign { display: block; }

/* A torn paper panel, not a wash. Lauren asked for "a little colored water
   color spot... like the other sectons we have", then clarified: "i meant the
   torn paper sections". So this is built exactly like My Story's two columns and
   the Beyond card — a flat panel colour with paper-wash.png over it in
   soft-light, and .torn-paper carrying the mask. Light teal is --panel-teal,
   the same fill .about-col-left uses at the top of this page.

   Its own tear file, because the two panels nearest it must not share an edge:
   .beyond-card directly above takes the default `a`, and .about-col-right takes
   `c`, so this one takes `b`.

   Top padding runs over the nominal --space-xl for the reason every panel here
   does: the torn edge bites up to ~42px into the box, so ordinary padding would
   let the wave reach the first line. */
/* FROSTED WHITE AND TRANSLUCENT since 2026-08-24, when the photograph went in
   behind this section — "make the text box thats over it the frosted white".
   Same values as .oto-do-card, which is the site's other frosted panel: 72%
   white over an 8px backdrop blur. The picture reads through as soft colour with
   no detail sharp enough to fight the type, and the copy keeps its navy.

   PULLED LEFT rather than centred, and the photograph decided that. Her face is
   in the right half of the frame; anchored left the card ends at x652 and leaves
   it clear, sitting instead over the pines and the sun flare.

   It also gives this page the off-centre moment the Club
   page got — see the note on .club-quote .wrap.
   The paper wash and --panel-teal came off with the change; a texture blended
   under a translucent card just muddies whatever is behind it. */
.thanks-spark {
  --panel-tear: url("../images/art/torn-paper-b.svg");
  width: min(37rem, 100%);
  margin: 0;
  background-color: rgba(255, 255, 255, 0.72);
  -webkit-backdrop-filter: blur(8px);
          backdrop-filter: blur(8px);
  padding: calc(var(--space-xl) + 0.5rem) clamp(1.8rem, 4vw, 3.4rem) calc(var(--space-xl) + 1rem);
}

.thanks-spark p { color: var(--ink); }

/* No divider any more. It was a hairline separating the invitation from the
   sign-off while both sat on bare paper; now the invitation is a torn panel and
   the panel's own edge does that work. A rule underneath it would have run a
   straight line a few px below a deliberately ragged one, which is exactly the
   effect the torn edges exist to avoid. */
.thanks-signoff {
  margin-top: 3rem;
  /* CENTRED UNDER THE CARD, NOT UNDER THE PAGE, 2026-08-25. Lauren: "center
     thanks for stopping by, lauren under the text box in the last section".

     The section is `text-align: center`, so these two lines were already
     centred — but centred inside `.wrap`, which is the full 1160px measure,
     putting them at x640 while the card above sits at x356. They read as
     belonging to the band rather than to the card.

     The same `min(37rem, 100%)` the card and `.thanks-panel-wrap` use, so all
     three share one width and one left edge by construction. Give the card a
     different width and the sign-off follows on its own; there is no second
     number to keep in step. On a phone 37rem is wider than the viewport, so
     this resolves to 100% and nothing moves — it was already under the card
     there. */
  width: min(37rem, 100%);
}

.thanks-spark .thanks-invite {
  font-weight: 500;
  margin-bottom: 0.45rem;
}

/* The form is the same embed as the home page's, but that one sits in a wide
   band and this one sits in a centred column, so it needs its own measure or
   the field runs the full width of the wrap. */
.thanks-spark .ml-form-embedContainer {
  max-width: 30rem;
  margin: 1.4rem auto 0;
}

/* The form is `display: flex` and its parent is centred text, which centres the
   ROW but not the row's own contents — without this the field and button sit
   left inside a centred column. */
.thanks-spark .signup-form { justify-content: center; }

/* The field has to change colour inside this panel, and this is not a taste
   call: `.signup-form input[type="email"]` is filled with --panel-teal, which
   is exactly the colour the panel became. On every other page that field sits
   on paper and the tint reads as a field; here it was teal on teal, visible
   only by its border. Paper-white, with the same wash and border it has
   everywhere else so it still belongs to the family. */
.thanks-spark .signup-form input[type="email"] {
  background-color: var(--white);
  /* Centred with the rest of the panel — Lauren, 2026-08-17: "also cneter the
     text in there as well". Every line of prose here was already centred; the
     placeholder was the one piece of visible text still reading left. */
  text-align: center;
}

/* Shrink-to-fit so the field and button centre as a PAIR. At a fixed 30rem the
   row's content came to 448px inside a 480px box and the leftover all fell on
   the right, leaving the pair sitting 16px left of the panel's centre line. */
.thanks-spark .ml-form-embedContainer {
  width: fit-content;
  max-width: 100%;
}

@media (max-width: 700px) {
  /* Stacked, exactly as `.spark-hero` does it on the Sunday Spark page, so the
     same form does not behave differently on two pages. The `flex` reset on the
     field is not tidying: `.signup-form input` is `flex: 1 1 200px`, and once
     the row becomes a COLUMN that 200px basis is read as a HEIGHT and the email
     box grows into a slab. Measured at 390 before this rule, the button sat
     16-221 against a full-width field. */
  .thanks-spark .signup-form { flex-direction: column; align-items: stretch; }
  .thanks-spark .signup-form input[type="email"] { flex: 0 0 auto; }
  .thanks-spark .signup-form .btn { width: 100%; }
}

/* THE CARD CONDENSED FOR PHONES — the other half of the change made up in
   `.about-thankyou`'s phone block above, which reclaims the section padding.
   It lives down HERE rather than beside that block because `.thanks-spark`'s
   base padding is declared further up the file at the same specificity, so a
   copy placed earlier simply lost. Source order, not specificity. */
@media (max-width: 760px) {
  /* THE TOP PADDING IS SET BY THE BUTTERFLY, NOT BY TASTE. `.thankyou-butterfly`
     is `translate(-50%, -50%)` off the card's top edge, so half its height hangs
     INTO the card — at 112px wide that is 34px of overlap, and the first line of
     the invitation ran straight under its lower wings when this padding went to
     1.25rem. Shrinking the butterfly to 84px on a phone drops the overlap to
     ~26px, and 1.85rem of padding clears it with a little air. Change one and
     re-check the other. */
  .about-thankyou .thankyou-butterfly { width: 84px; }

  .thanks-spark {
    padding: 1.85rem clamp(1rem, 4.2vw, 1.5rem) 1.4rem;
  }

  /* NO TYPE GETS SMALLER ANYWHERE IN HERE — see [[lumilibra-type-legibility]],
     she has read this copy as too small more than once. Every pixel below comes
     out of SPACING, and the biggest single saving is the line-height: the card
     holds seven lines of 19px, so 1.75 -> 1.45 is worth about 40px on its own
     without changing a single letterform.

     Where the 433px went, roughly:
       line-height on the two paragraphs   -40
       the field and the button            -16
       the card's own top and bottom       -16
       the three margins between blocks    -10 */
  .thanks-spark .thanks-invite,
  .thanks-spark p { line-height: 1.45; }

  .thanks-spark .thanks-invite { margin-bottom: 0.25rem; }
  .thanks-spark p { margin-bottom: 0.45rem; }
  .thanks-spark .ml-form-embedContainer { margin-top: 0.6rem; }

  /* The two controls are 57 and 55 tall, which is generous for a phone and the
     only place left with real slack once the type is off limits. Still well over
     the 44px minimum touch target. */
  .thanks-spark .signup-form input[type="email"] { padding-top: 0.7rem; padding-bottom: 0.7rem; }
  .thanks-spark .signup-form .btn { padding-top: 0.72rem; padding-bottom: 0.72rem; }

  .thanks-signoff { margin-top: 1.1rem; }

  /* 24.8px, UP FROM 17.9, AND THE SIZE IS DOING TWO JOBS. Lauren has read copy
     on this site as too small more than once, so bigger is the right direction
     anyway — but it is also what makes the pinned photograph affordable here.
     Under 24px this line needs the full 4.5; at 24.8 it clears WCAG's large-text
     threshold and needs 3.0. That is the difference between a wash at x1.5,
     which would take the picture down to 44%, and one at x1.1 that leaves it at
     59%. See the pinning block below. */
  .about-thankyou .thanks-lead { font-size: 1.55rem; }
}
.about-sign { display: block; font-size: 1.62rem; margin-top: 1rem; }

/* Responsive */
@media (max-width: 900px) {
  .about-hero-grid { grid-template-columns: 1fr; }
  .about-hero-figure { max-width: 420px; margin: 0 auto; order: -1; }
  .about-hero-copy p { max-width: none; }
  .about-split, .about-split.reverse { grid-template-columns: 1fr; }
  .finding-leaves { display: none; }
  /* My Story uses a higher-specificity 2-col rule; collapse it to a single column too */
  .about-mystory .about-split { grid-template-columns: 1fr; }
  .about-split.reverse .about-photo, .about-photo { order: -1; }
  .about-cards { grid-template-columns: repeat(2, 1fr); }
  /* Thank you section — right butterfly higher in the corner, tilted left; bottom-left nudged up */
  .about-fly-5 { top: -5%; right: 0%; transform: rotate(-24deg); }
  .about-fly-4 { bottom: -30%; }
}
@media (max-width: 560px) {
  .about-cards { grid-template-columns: 1fr; }
}

/* About — two floating torn scraps (Coming Home | Art Was My Outlet).
   The page's structural echo of the home page's Believe / Who-For pair, and
   built the same way: not one band ruled into two cells, but two pieces of torn
   paper laid down at different heights, each lapping over its neighbour.

   Deliberately NOT the home page's colourway. That pair is teal + blue; this
   one is teal + lavender, so the two pages read as the same hand without the
   About page looking like the home page repeated. The blue turns up further
   down instead, on .beyond-card.

   z-index descends left to right so the overlap stacks one way — without it the
   later panel always paints on top and the lapping reads in a single direction
   no matter which one is meant to be in front. */
.about-twocol {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1.04fr;
  /* start, not stretch: they are two separate scraps at two heights, not a row. */
  align-items: start;
  padding: 2rem 0 3.5rem;
}

/* Same baked paper as the hero and the home panels — these are washes on a
   sheet, not flat fills. The PNG carries lightness only, so the colour stays in
   background-color underneath and one file serves every panel on the site. */
.about-col {
  position: relative;
  background-image: url("../images/art/paper-wash.png");
  background-size: cover;
  background-position: center;
  background-blend-mode: soft-light;
  /* Extra top padding over the nominal --space-xl for the same reason the home
     panels take it: the torn top edge bites up to ~42px into the panel. */
  padding: calc(var(--space-xl) + 1rem) clamp(1.6rem, 2.6vw, 2.8rem) calc(var(--space-xl) + 2rem);
}

.about-col-left  { background-color: var(--panel-teal); margin-top: 0;      z-index: 2; }
.about-col-right { background-color: var(--panel-lav);  margin-top: 4.5rem; margin-left: -3%; z-index: 1; }

/* On colour, the headings go navy and the copy to the panel ink — the same
   treatment the home panels take. */
.about-col .about-title { color: var(--navy); }
.about-col p { color: var(--ink); }

/* The lapping only works while the two sit side by side; stacked, a negative
   inline margin just drags the panel off the page edge. They still need a real
   gap, though — butted at margin-top: 0 the first panel's torn base interlocks
   with the next one's torn top and the boundary reads as a hard colour change.
   Paper between them is what makes a tear visible at all. */
@media (max-width: 900px) {
  .about-twocol { grid-template-columns: 1fr; padding-bottom: 2rem; }
  .about-col-right { margin-left: 0; margin-top: 3rem; }
  /* The side tear is ~14px on a full-width panel and the clamp bottoms out at
     1.6rem, which leaves too little clearance to the text. */
  .about-col { padding-inline: 2.2rem; }

  /* The white half of the My Story crossover comes OFF while the columns are
     stacked — 2026-08-12, found by sweeping the page at ten widths.

     Its horizontal is the sage half's converted by a fixed ratio ("the grid is
     1fr 1.04fr, so this panel is 52.5% of the section at every width"), and that
     conversion is only true WHILE THERE ARE TWO COLUMNS. This is the breakpoint
     where they stack, and from here down the two halves measure against boxes of
     the same width but with values derived for different ones: the pair reads
     dx 0 / dy 0 at 960 and above, and 125-159px apart horizontally with 405-585px
     of vertical split below.

     Split is not the visible symptom, though. The white half is a child of the
     LAVENDER panel, which stacks ~500px below the sage half down here, so all
     that ever painted was the 86px of it that happened to fall inside that
     panel's mask — a white fragment on the lavender with no drawing attached to
     it. On a phone the number is 0 and it was invisible, which is why the mobile
     pass never caught it.

     The colour change itself is rebuilt for phones as .twocol-teal-leaf-white
     (≤699). Between 700 and 900 there is no white partner at all now, so the
     sage sprig simply crosses the teal panel in sage. That band has never been
     designed — flagged to Lauren with the rest of the 700-1100 findings. */
  .twocol-top-leaf-white { display: none; }
}

/* About — feature image beneath My Story */
.about-feature { margin: 3rem auto 0; text-align: center; }
.about-feature img {
  width: 100%;
  max-width: 460px;
  border-radius: var(--radius);
  box-shadow: var(--shadow-soft);
  margin-inline: auto;
}

/* About — floating butterfly beside the "My Story" heading */
.about-photo { position: relative; width: fit-content; margin-inline: auto; }
.about-title .about-butterfly {
  display: inline-block;
  width: 46px;
  height: auto;
  vertical-align: middle;
  margin-left: 0.5rem;
  border-radius: 0;
  box-shadow: none;
  max-width: none;
  transform: rotate(-8deg);
  animation: flutter 5s ease-in-out infinite;
}

/* About — "Beyond Lumi Libra…" as a torn scrap inset from the page edges.

   Was a flat --seafoam band running the full width with a ruled edge top and
   bottom. As a single centred scrap it becomes the one element on the page whose
   torn edge is visible the whole way round — the two panels above are full-bleed
   and get cropped by the viewport on their outer sides, so nothing there shows a
   complete tear. Same reasoning as the home page's club card.

   The section keeps its padding; the SCRAP is what carries the colour, so the
   surrounding paper is what the tear is torn against. */
/* position:relative so decoration in this section resolves against the section
   and not against the initial containing block — without it .beyond-path
   measured from the top of the document and landed off the top of the page. */
.about-section.bg-sage { position: relative; padding-block: calc(var(--section) - 0.5rem); }

/* Blue, so the page's three scraps are three different colours — the teal panel,
   the lavender one beside it, and this. Repeating the teal here would have put
   the same wash twice on one page with only bare paper between. */
.beyond-card {
  width: min(1000px, 92%);
  margin-inline: auto;
  background-color: var(--panel-blue);
  background-image: url("../images/art/paper-wash.png");
  background-size: cover;
  background-position: center;
  background-blend-mode: soft-light;
  padding: calc(var(--space-xl) + 0.5rem) clamp(1.8rem, 4vw, 3.4rem) calc(var(--space-xl) + 1rem);
}
.beyond-card .about-title { color: var(--navy); }

/* About — "Beyond Lumi Libra…" lists.
   These were eight 27px watercolour butterflies used as bullets, which is the
   same mistake the home page's Believe list made and had corrected: at that size
   they stop reading as marks and become a column of illustrations running down
   the panel, and the drawing repeats eight times in one block — the one thing
   the butterfly set is never supposed to do. Small hearts instead, matching both
   panel lists on the home page. */
/* The line that used to be the list's eighth item and is now its close.
   Centred on the heading above rather than set to the list's left edge: the
   two columns start at two different x, so there is no left edge to agree
   with. The top margin is wider than the list's own row gap so it sits away
   from the columns rather than reading as a stray ninth entry.

   A `.beyond-sub` sat under the heading for one revision on 2026-08-12 ("When
   I'm not here, you can usually find me doing one of these") and Lauren cut it
   the same day. Rule removed with the markup — don't leave it behind for a
   later class to inherit by name. */
.beyond-close {
  max-width: 54ch;
  margin: 2.2rem auto 0;
  text-align: center;
  color: var(--ink);
}

/* The butterfly under that closing line — Lauren, 2026-08-13. Centred on the
   same axis as the sentence above it, which is centred within the card rather
   than within the page, so this centres the same way instead of carrying its own
   idea of the middle.

   1.6rem against the closing line's body size: big enough to read as a mark
   rather than as a typo in the paragraph, small enough not to compete with the
   painted butterfly that opens the Thanks section below. The 1.1rem of top
   margin is half the gap the paragraph itself takes from the list, so it reads
   as belonging to the sentence rather than as a new block. */
.beyond-close-mark {
  margin: 1.1rem auto 0;
  text-align: center;
  font-size: 1.6rem;
  line-height: 1;
}

.things-cols {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(2rem, 5vw, 3.4rem);
  margin: 2.4rem auto 0;
}
.things-list { list-style: none; }
.things-list li {
  position: relative;
  padding-left: 1.9rem;
  margin-bottom: 1.15rem;
  font-size: var(--t-base);
  line-height: 1.7;
  color: var(--ink);
}
/* Filled, and pale mint because this card is the panel blue — the site rule, see
   the heart note on .believe. */
.beyond-card { --heart: var(--aqua-mist); }
.things-list li::before {
  content: "\2665";
  position: absolute;
  left: 0;
  top: 0;
  color: var(--heart, var(--bullet-blue));
  font-size: 0.92em;
}
@media (max-width: 760px) {
  .about-title,
  .about-thankyou h2 { text-align: center; }
  .things-cols { grid-template-columns: 1fr; gap: 0; }
}

/* ==========================================================================
   About Lauren — decoration
   Rebuilt 2026-08-05 (second pass). Lauren asked for the home page to be used
   as the visual LANGUAGE for the other two pages rather than as a template:
   the same balance, the same density, the same size relationships between big
   and small pieces, the same feeling of movement — but reinterpreted, so that
   flipping between the three reads as one site and never as a repeated section.

   The system, taken off the home page and measured rather than eyeballed:

   1. THE VINE DESCENDS THE PAGE SIDE TO SIDE. On the home page it steps
      right-left-right-left down the sheet roughly every 540px, entering from the
      page margins. Here it steps LEFT first, so the two pages are out of phase
      with each other from the first screen.
   2. WHITE LEAVES ON THE COLOUR, COLOURED LEAVES ON THE PAPER. Where the vine
      crosses a torn edge it changes colour on the line — one drawing, two
      colourways, two copies at pixel-identical positions.
   3. SIZE RELATIONSHIPS. Off the home page: a crossover sprig is the biggest
      botanical event (445-509px), a plain vine segment 280-430, a dotted flight
      229-360, a butterfly 88-221. Roughly vine : flight : butterfly = 3 : 2 : 1.
   4. DENSITY. The home page carries 26 pieces over 4510px — one per ~173px, but
      unevenly: 3-5 around a feature, 1-2 beside long reading. This page runs a
      little sparser (one per ~240px) because it is mostly long-form prose, which
      is exactly the distinction the home page itself makes.

   Where a home-page piece has an opposite number here it is deliberately NOT in
   the same place or at the same angle — the hero sprig enters left instead of
   right, the tear crossover happens on the right instead of the left, the
   photograph is cupped at its bottom corner instead of its top.
   ========================================================================== */

/* Layout helper, not decoration: .beyond-wrap shares the scrap's exact left and
   width, so anything measured from it is measured from the card itself — and it
   is a plain sibling, so a corner piece is not cropped by the card's torn mask. */
.beyond-wrap { width: min(1000px, 92%); margin-inline: auto; position: relative; }
.beyond-wrap .beyond-card { width: 100%; }

/* ---------- The gap between the two panels and the dark teal band ----------
   Both pieces are children of .about-twocol, not of the band. The band is
   .torn-top, and a mask crops its children — so anything placed inside it is cut
   off at the tear, which is precisely the line these two are meant to cross.
   z-index 3 puts them above the band: .about-col-left carries z-index 2 and
   .about-col-right z-index 1, and the band itself is a later positioned sibling
   at z-index auto, so a .deco's default 0 would be buried under all three.

   The usable gap is bigger than the boxes suggest and that is what makes these
   fit. The panels' bottom edges measure y2319 and y2325, but both are torn
   paper, so their colour actually stops 30-40px higher; the band's box starts at
   y2381, but .torn-top means its colour starts up to --wave-h lower in the
   troughs. The white channel is therefore about 100px tall, not 56. */

/* Sage sprig in the band above the lavender scrap, on the RIGHT.

   The pocket is real and generously sized, which is unusual on this page: the
   My Story photo ends at y1337 and the lavender panel does not begin until
   y1601 (it carries margin-top: 4.5rem), leaving 672 x 264 of clear paper. The
   rotated drawing is taller than that, and the overhang is deliberate — the
   panel is a later positioned sibling, so it paints over the tail and the vine
   reads as passing behind the scrap rather than stopping at it.

   "Stem on the right, leaves flowing down" is ONE rotation, no mirror. The stem
   is at the drawing's foot and the leaves fan up off it, so at -110deg the foot
   swings up to the RIGHT and the leafy end falls away to the left and below —
   which is the cascade asked for. */
/* White open-winged butterfly, sitting at the FAR END of the dotted trail — the
   end away from the nav — so the two read as one flight leaving the menu and
   arriving here. It used to be levelled against Lauren's elbow and offset in
   percentages for that reason; it is now pinned to the trail instead, so it
   takes the trail's anchoring with it.

   The numbers are measured off the two drawings, not eyeballed. The trail's
   painted tail sits at (50% + 404, 401), and this drawing's painted centre is
   62px right of and 37px below its own element box's top-left.

   Set at the tail first, which put the two in contact — Lauren: "i dont want
   them touching" — then stepped down and right along the flight's own
   direction, which descends at about (0.54, 0.84). The clearance is measured
   between painted pixels, not boxes: at y385 the gap was 0, at 405 it is 8px,
   at 420 it is 21. Re-derive if either piece's width or angle changes. */
.hero-white-bfly {
  right: auto;
  left: calc(50% + 425px);
  /* px, matching the trail. The old 57% resolved against a vh-sized hero, so on
     a shorter window the butterfly slid up the photograph while the trail —
     which is pinned to the header — stayed put, and the pair came apart. */
  top: 420px;
  width: min(110px, 9%);
  opacity: 0.9;
  /* Positive = tilted right. Symmetric open-winged drawing, so no mirror is
     involved and the angle alone gives it direction. */
  transform: rotate(12deg);
}

/* The trail it flew in on: a white dotted line running near-vertically up and
   away to the left of the big butterfly, so the two read as one flight.

   -101deg puts the drawing's start at the butterfly and carries it up and
   slightly left. Kept entirely inside the hero on purpose — this is white art,
   so the moment it crossed the tear onto paper it would simply vanish. */
.hero-white-path {
  /* Pinned to the "b" at the end of "Self-Love Club" in the nav — Lauren wanted
     the trail to start from under that letter, as if the flight had left the
     menu.

     Both offsets are calc'd rather than percentages, because the two things
     being lined up scale differently. The nav sits inside .wrap, which caps at
     1160px and then centres, so the "b" stops moving right once the window
     passes 1160; `right: 12%` kept moving with the viewport. They agreed to
     within 4px at 1280 and were 84px apart at 1512.

     The arithmetic, all measured rather than guessed:
       - the "b" ends 398px in from .wrap's right edge, at every width, so its
         x is (50% + 580) - 398 = 50% + 182.
       - turned -142deg, this drawing's painted trail begins 91px right of its
         own element box's left edge, and 103px ABOVE the box's top.
     So left: 50% + 182 - 91, and top: nav baseline (56) + 103 + a 1px gap.

     top is in px, not the old 24%: that percentage resolved against a hero
     sized in vh, so the trail slid down the photograph as the window got
     shorter while the header it points at stayed put. */
  right: auto;
  left: calc(50% + 91px);
  top: 160px;
  width: min(400px, 31.3%);
  /* FULL strength, and a soft shadow under it. A thin dashed line loses itself
     far faster than a leafy sprig does, and this one is white hairline art lying
     on a high-key photograph of sunlight through trees — there is no contrast to
     spend, so it gets none taken away. The drop-shadow is what actually makes it
     read: it separates the dots from the bright patches behind them without
     tinting the art itself. Restraint here comes from size, not from fading. */
  opacity: 1;
  filter: drop-shadow(0 1px 2px rgba(18, 38, 48, 0.5));
  /* Leaning further left than the arm it echoes. Lauren's raised right arm runs
     from her shoulder at roughly (623, 429) up to her hand at (507, 180) — 65deg
     off horizontal — and -142deg lays the trail well off that line, so the two
     diverge sharply instead of running parallel and reading as one. Held
     well to the RIGHT of her, clear of the figure entirely. */
  transform: rotate(-142deg);
}

/* Small white butterfly out to the left of Lauren's raised hand. */
.hero-hand-bfly {
  left: 21.4%;
  top: 21%;
  width: min(58px, 5%);
  opacity: 0.85;
  transform: rotate(-10deg);
}

/* ---------- The sprig that changes colour at the HERO's tear ----------
   Lying under "About Lauren": white while it is on the photograph, teal once it
   reaches the paper below. Same construction as the teal band's crossover, and
   worth repeating exactly because it cannot drift — both halves derive their
   offset from ONE shared value, and both resolve their percentages against
   full-bleed sections that share left and width.

   White's box-bottom sits at (hero bottom + drop). Teal's is at
   clip_bottom - (clip_h - wave_h - drop), and clip_bottom is
   clip_top + clip_h = hero_bottom - wave_h + clip_h — the same point. They
   coincide by construction, not by measurement.

   Anchoring to the hero's BOTTOM is what keeps it under the title at any window
   height: this hero is sized in vh, so the title's absolute position moves, but
   the gap between the title's baseline and the tear is fixed padding.

   Placed under the title's RIGHT half rather than centred on it. Below the tear
   the left of the page is taken by "My Story" (x60-221) — out at x300+ the paper
   is clear all the way down to the first paragraph, which is what lets the teal
   half be long enough to read as a vine rather than a stub. */
.hero-tear-white,
.hero-tear-teal {
  /* Sized and dropped so the sprig lies in the band BETWEEN the wordmark's
     baseline (y657) and the "My Story" heading below the tear (y792) — it reads
     as something "About Lauren" is resting on.

     Turned on its side this drawing is 1.45:1, so its length and its height are
     locked together — a longer flourish is necessarily a taller one, and the
     budget below the tear is set by whatever sits there. Directly under the "A"
     that is the "My Story" heading, which leaves only 135px and caps the sprig
     at a 179px stub. Started just PAST that heading's text (it ends at x221)
     the floor drops to the first paragraph instead, which buys 188px — enough
     for a 240px sprig that spans "bout Laur" and reads as something the
     wordmark is resting on. */
  /* 7.6 -> 7.0rem, 2026-08-13. At 7.6 the sprig put 10 painted pixels on the
     "My Story" heading at 1024 — clean at 390 and at 1280, so it only showed in
     the tablet band, where `width: min(230px, 18%)` starts resolving to the
     percentage and the heading below the tear sits closer.

     NARROWING IT MAKES THIS WORSE, NOT BETTER, which is the counter-intuitive
     part: 16% took the hits from 10 to 47. A shorter sprig ends further LEFT,
     back over the heading, and the whole reason the drawing can be this long is
     that it starts past that heading's text. Raise it instead of shrinking it.

     Set on the SHARED selector, so both halves move together and the crossover
     cannot step sideways at the tear. */
  --hero-drop: 7.0rem;
  /* Stem at the "A" of About: at 96deg the drawing's foot maps to the LEFT, so
     the left edge of the rotated box is where the stem lands. */
  /* Negative, so the stem runs off the left edge of the page and the sprig
     reads as entering from the margin. Moving it out there is also what buys the
     size: at x60 the drawing had to clear the "My Story" heading below the tear
     and was capped at 133px. */
  left: 0.9%;
  width: min(230px, 18%);
  opacity: 0.55;
  /* Exactly 90deg, so the sprig lies FLAT under the wordmark — stem at the A,
     leaves running away horizontally to the right with no dip. 90 is also the
     flattest this drawing can ever be: rotated, its painted height is the
     element's own width, so any other angle is taller for the same length.

     scaleX BEFORE rotate in source order, so it applies FIRST. Note what a
     HORIZONTAL mirror does to a piece turned almost on its side: it reads on
     screen as a VERTICAL flip, so the arc inverts. The stem stays at the left,
     by the A, either way — at 96deg the drawing's foot maps to the left. */
  transform: rotate(90deg) scaleX(-1);
}

.hero-tear-clip {
  --hero-clip-h: 280px;
  position: absolute;
  left: 0;
  right: 0;
  top: calc(-1 * var(--wave-h));
  height: var(--hero-clip-h);
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
}

.hero-tear-white { bottom: calc(-1 * var(--hero-drop)); }
.hero-tear-teal  { bottom: calc(var(--hero-clip-h) - var(--wave-h) - var(--hero-drop)); }

/* ---------- The teal band -> "Why I Started" crossover, PHONES ONLY ----------
   2026-08-25, Lauren: "a white leaves turning to teal once its off the teal
   space, above why i started lumi libra on the mobile only. the left side. stem
   coming from the left, leaves coming down."

   Same technique as the hero->My Story pair above and the club card's: ONE
   drawing, two colourways, pixel-identical positions, each clipped to its own
   side of the tear. leaf-vine-white and leaf-vine-teal are two colourways of the
   SAME source, which is the only reason they can align — the sage drawing is a
   different shape and cannot be substituted at any offset.

   THE UPPER HALF NEEDS NO CLIP: it is a child of a `.torn-top.torn-bottom`
   section, so that mask crops it.

   THE LOWER HALF IS MASKED WITH --wave-bottom-inv, NOT the plain overflow
   wrapper the hero pair uses, and this is the one real difference. That wrapper
   starts a whole --wave-h ABOVE the tear so the halves overlap rather than risk
   a gap in the stem — which paints the LOWER colourway up into the wave's peaks.
   It is invisible on the hero because the lower half is teal and the band it
   overlaps is teal. Here the band is DARK teal and the lower half is the light
   teal drawing, so it would show as the club page's bug did: "the sage is in the
   purple instead of being white and you cant see." --wave-bottom-inv is
   wave-bottom's own seed closed downward, so the two halves tile exactly — no
   overlap to show the wrong colour, and no gap. */
.origin-tear-white,
.origin-tear-teal { display: none; }

@media (max-width: 760px) {
  .origin-tear-white,
  .origin-tear-teal {
    /* EVERY VALUE HERE IS SHARED ON PURPOSE. Width, transform and opacity must
       match or the sprig steps sideways at the tear; --origin-drop is declared
       here rather than on either section so one number moves both halves. */
    /* SIZED TO THE GAP, NOT TO TASTE. Measured at 375: the band's last line ends
       119px above the tear and the heading below starts 45px under it, so the
       whole window this sprig can live in is 163px. Rotated, its painted box is
       `width * sin(t) + width * 1.448 * cos(t)` tall — at the first attempt,
       200px wide at 118deg, that was 305px, and it sat straight through "But I
       keep coming back to what makes me feel like me." A narrower, flatter sprig
       is the only way to fit: 130 at 104deg measures 172.

       THE DROP IS SET FROM WHERE THE INK IS, NOT FROM THE BOX. Sampling the
       asset under this exact transform: the painted rows fill 0.007-0.953 of the
       rotated box, but the MASS is low in it — the ink median sits at 0.641 of
       the box height, because `scaleX(-1)` inverts the arc and drops the leaves
       into the lower half. Placing the box's centre on the tear therefore puts
       most of the drawing below it and the colour change never reads. 4.8rem
       lands the tear at ~0.67 of the box, just past the ink median, which is the
       even split.

       The model was calibrated against a render rather than trusted: at 200px
       and 118deg unflipped it predicts an ink median of 0.377 — high in the box
       — and that is exactly where the first attempt sat, straight through the
       band's last line. */
    /* 4.8rem -> 4.3rem, 2026-08-31. Lauren: "move those leaves in that section on
       mobile up just a tiny bit." 8px, and ONE number does it: the white half is
       at `-1 * --origin-drop` and the teal at `--origin-clip-h - --wave-h -
       --origin-drop`, so both halves move together and the pair cannot drift out
       of register by editing this. Verified after: identical ink boxes.

       IT BUYS CLEARANCE BELOW AND SPENDS THE COLOUR SPLIT. The leafy end used to
       reach 13px past the top of "Why I Started Lumi Libra"; it now stops 5px
       short of it. The cost is the ratio the 4.8 was tuned for: the tear crossed
       the ink at 70.1% of its painted height, an even-ish split of white above
       and teal below, and now crosses at 74.2%. Still a clear crossover, but the
       teal quarter is what runs out if this goes much higher &#8212; measure the split,
       not the box, before the next step up.

       THE 119px FIGURE BELOW IS STALE and is left for its reasoning, not its
       numbers: the band's copy has been rewritten twice since, so the window this
       sprig lives in is not the one that was measured. Re-measure at 390 rather
       than trusting it. */
    --origin-drop: 4.3rem;
    display: block;
    position: absolute;
    left: -2%;
    width: min(155px, 42%);
    opacity: 0.62;
    /* Stem in from the left margin, leaves falling to the right. At 90deg this
       drawing lies flat with its foot at the LEFT; past 90 the far end tips
       down, which is the "leaves coming down" part. Kept close to 90 because
       every degree past it costs height this gap does not have. */
    /* scaleX IS LISTED LAST SO IT APPLIES FIRST. On a drawing turned nearly on
       its side a horizontal mirror reads on screen as a VERTICAL flip: the arc
       inverts and the leaves fall the other way, while the stem stays at the
       left. That is what makes this one travel down the page the way the vine
       does everywhere else, rather than against it. Same construction as the
       hero pair, which is `rotate(90deg) scaleX(-1)`. */
    transform: rotate(104deg) scaleX(-1);
    z-index: 0;
    pointer-events: none;
  }

  .origin-tear-clip {
    --origin-clip-h: 240px;
    position: absolute;
    left: 0;
    right: 0;
    /* Its top IS the tear: `.torn-bottom` puts its wave in the band's last
       --wave-h, and a clip starting one --wave-h above this section begins on
       that same line. Alignment is by construction, not by measurement. */
    top: calc(-1 * var(--wave-h));
    height: var(--origin-clip-h);
    overflow: hidden;
    pointer-events: none;
    z-index: 0;
    -webkit-mask-image: var(--wave-bottom-inv), linear-gradient(#000, #000);
            mask-image: var(--wave-bottom-inv), linear-gradient(#000, #000);
    -webkit-mask-size: var(--wave-tile) var(--wave-h), 100% calc(100% - var(--wave-h) + var(--wave-overlap));
            mask-size: var(--wave-tile) var(--wave-h), 100% calc(100% - var(--wave-h) + var(--wave-overlap));
    -webkit-mask-position: 0 0, 0 100%;
            mask-position: 0 0, 0 100%;
    -webkit-mask-repeat: repeat-x, no-repeat;
            mask-repeat: repeat-x, no-repeat;
  }

  /* The white half hangs --origin-drop BELOW the band's box; the teal half is
     placed so its own bottom lands on the same page line. Derived, not measured:
     the clip's bottom sits (--origin-clip-h - --wave-h) below the band's, so the
     teal half's offset is that minus the same drop. */
  .origin-tear-white { bottom: calc(-1 * var(--origin-drop)); }
  .origin-tear-teal  { bottom: calc(var(--origin-clip-h) - var(--wave-h) - var(--origin-drop)); }
}

/* ---------- My Story — painted butterfly on the photo's teal border ----------
   Sitting at the BOTTOM-RIGHT of the tree-rays photo, tilted left, straddling
   the mount's edge so it laps onto both the picture and the paper. Lauren,
   2026-08-11, in four steps: smaller, "add it to the right side of the photo",
   "have it overlap the pic and the white space", then "move it to the bottom
   right of the photo and tilt it to the left". It was 186px across the
   top-LEFT corner, wholly on the mount. The class name still says "corner"; it
   is referenced by name in the phone rule below, so it was left alone.

   THE CORNERS OF THIS FIGURE ARE NOT WHERE THE BOX SAYS. Placed at the
   top-right corner on the way here, and against the boxes it measured right —
   73px over the figure, 35px over the rim, 17px on paper. It was floating in
   white with NOTHING under it: the mount is a torn blob whose corners are cut
   away, and at that height its painted edge was 170px inside the box. Every
   value below was read off the MASKS instead (see the sampler at the end).

   `bottom: 6.5%` puts the drawing's centre 88% of the way down, where the
   blob's edge has curved in to 0.89 of the figure's width — so the same
   overhang that was a sliver at the top is a real straddle here. Between 0.85
   and 0.95 of the height that edge moves 76px left, which is why this piece is
   anchored from the BOTTOM: a `top` percentage would slide it along a rapidly
   moving edge if the figure's height ever changed.

   z-index 2 is load-bearing. `.about-photo img:not(.deco)` gives the picture
   `position: relative; z-index: 1`, so a .deco at the default 0 would sit
   BEHIND the photograph and only the sliver outside the mount would show — it
   reads as a fragment rather than as a mistake, which is what makes that one
   hard to spot.

   The `:not(.deco)` on that rule is why this can live inside the figure at all:
   a bare `.about-photo img` selector would give this butterfly the photo's own
   width and blob mask.

   Negative tilt = tilted left, at her ask. This drawing is a symmetric
   open-winged butterfly, so no mirror is involved and the angle alone gives it
   direction.

   Rotation arithmetic, which any resize of this needs: the asset is painted
   edge to edge (measured — its alpha bbox IS its 400x248 box), so the declared
   width is the drawing's width, but an 18deg tilt of either sign opens the
   on-screen box to `W*cos18 + H*sin18` with `H = 0.62W`. At 110px that is
   125px, so each side reaches 7.5px past where `right` puts the layout box.
   Re-derive that term before changing either the width or the angle.

   THE EDGE IT STRADDLES IS NOT THE FIGURE'S BOX, AND BOXES CANNOT MEASURE IT.
   The picture is masked with `photo-blob-a.svg` and the teal mount behind it
   with `photo-rim-a.svg` (`::before`, inset -34.72px a side), both torn
   shapes — so the painted edge is nowhere near the rectangle, and it moves
   with y: at the top of the figure the blob reaches only x954, 240px inside
   its own box, and it does not reach x1180 until 210px further down.

   Measure it by hitting the masks, not by comparing rectangles. Build a
   Path2D from each SVG's `d`, map page px into the 520x520 viewBox through
   each element's own box (`preserveAspectRatio="none"`, so x and y scale
   independently), and sample a grid over the butterfly's ROTATED quad with
   `isPointInPath` — its bounding box is mostly empty corners at this tilt.
   The percentages recorded under the rule are that sampler's, and it is what
   caught the top-corner placement reading 0% on the mount while the box
   arithmetic said it lapped 108px onto it. */
.mystory-corner-bfly {
  /* An even straddle, sampled: 31% of the drawing on the photograph, 38% on
     the teal rim between, 31% out on the paper. */
  right: 4px;
  bottom: 6.5%;
  width: min(110px, 22%);
  z-index: 2;
  transform: rotate(-18deg);
}

/* `right` needs no override at any width — sitting INSIDE the box, it clears
   everywhere: page margin 82px at 1280, 40 at 1100, 36 at 900, 27 at 760.
   (The earlier top-edge placement hung 44px past the box and needed two.)

   `bottom` does, and the reason is NOT the aspect ratio — that is 0.8 at every
   width (496x620, 699x874, 820x1025). It is that `width: min(110px, 22%)` caps
   at 110px while the figure keeps growing, so stacked, the drawing is 13% of
   the photo's width instead of 22% and no longer reaches across the same edge.
   Sampled at 760, the desktop value left it 3% on the photograph and 81% on
   paper — adrift, with nothing in the CSS looking wrong. Lifting it to 14%
   walks it back up the curve to where the blob is wider: 47% on the photograph
   against 16% on paper at 760, and 32/32 at 900. It comes off entirely at 700.

   (Dropping the px cap so the width stayed 22% everywhere would make the
   straddle scale-free and delete this rule — but it would also put a 154px
   butterfly on the stacked layout, and 154px is the size that was judged too
   big for a near-full-bleed photo when this piece was hidden on phones.) */
@media (max-width: 1000px) {
  .mystory-corner-bfly { bottom: 14%; }
}

/* Shared: the two halves must stay identical copies or the colour change stops
   reading as one drawing. Opacity counts as alignment. */
.twocol-top-leaf,
.twocol-top-leaf-white {
  opacity: 0.5;
  /* -103 rather than -110: 7deg clockwise, which leans the whole sprig to the
     right without changing which end the stem is on. */
  transform: rotate(-103deg);
}

.twocol-top-leaf {
  right: 3%;
  top: -175px;
  width: min(230px, 18%);
}

/* The white half, cropped to the lavender by the panel's own tear.

   Its offsets are the sage half's, converted — the two halves live in different
   boxes, so they cannot share raw values. Two conversions, both stable:

   - VERTICAL is px against px. The panel's top sits a FIXED 104px below the
     section's (.about-twocol's 2rem padding plus the panel's 4.5rem margin,
     both in rem), so -175 becomes -279 and stays correct at any width.
   - HORIZONTAL is scaled by a known ratio. The grid is `1fr 1.04fr` with a -3%
     pull, which fixes this panel at 52.5% of the section at every width, so the
     sage half's 3% / 18% become 5.714% / 34.29% here. Recompute both if the
     grid ratio ever changes.

   The panel's right edge coincides with the page's, which is what lets a
   right-anchored pair line up at all. */
.twocol-top-leaf-white {
  right: 5.714%;
  top: -279px;
  width: min(230px, 34.29%);
}

/* Phone-only third copy of that drawing — see the media query at the foot of
   this block. Off by default so it costs the desktop layout nothing. */
.twocol-teal-leaf-white { display: none; }

/* Phone-only seam anchor and the butterfly it carries. Off by default, so on
   desktop the section is back to exactly two grid items. */
.twocol-seam-anchor { display: none; }

/* Phone-only, above the sage sprig's leaf tips. See the media query below. */
.twocol-tips-bfly { display: none; }

/* Phone-only, in the paper above the Beyond scrap. See the media query below. */
.beyond-top-flight { display: none; }

/* The climbing trail, on the right. Worth knowing what this drawing is before
   sizing it: read off its alpha, `path-dotted-noloop` is not a flat line but a
   shallow arc at the bottom-left that turns and climbs steeply to the top-right,
   filling its whole 900x400 frame. So its height is real height, and the piece
   has to be sized against the channel rather than against the other trails. */
.twocol-gap-path {
  /* Across the SEAM, lapping the light teal panel and the lavender one at once —
     which is what the z-index 3 is really for: the two panels carry z-index 2
     and 1, so anything meant to lie across both has to clear the higher of them.
     Both panels run their copy out of the way at this height, so it sits in the
     clear band at their feet rather than over any writing. */
  /* Shifted right so the WHOLE trail reads: it now emerges from behind the
     butterfly and runs out to the right, instead of the butterfly sitting over
     its middle and cutting it in two. Still behind — both carry z-index 3, so
     the one later in the DOM wins, and the butterfly is written second. */
  /* Anchored to the butterfly's MIDSECTION — the line where its teal upper wing
     meets its purple lower one. That point was measured off the drawing rather
     than eyeballed: classifying bfly-teal-purple.webp's painted pixels by hue,
     teal gives way to purple at 61.5% of its height, which on the rendered
     butterfly lands at about page (595, 2165). */
  left: 46.8%;
  /* 19px -> 4px on 2026-08-24, with the rotate below. Lauren reads this pair as
     guiding the eye down into the teal band, and it was doing that with only the
     butterfly: measured, the butterfly laps 26px past the tear while the trail's
     lowest painted point stopped 12px SHORT of it. Now the trail crosses too, by
     21px, so the two go over the edge together. */
  bottom: 4px;
  width: min(180px, 15%);
  opacity: 0.75;
  z-index: 3;
  /* No scaleY: the drawing as exported already CLIMBS from bottom-left to
     top-right, so left unmirrored the trail points UP and away from the
     butterfly — which is right, because the butterfly is descending to the LEFT
     and the trail is what it flew in on. A vertical mirror was tried here and
     reversed — it made the trail dive instead of lift.

     6deg -> -12deg on 2026-08-24. SIGN MATTERS AND THE OLD ONE FOUGHT THE ART:
     positive is clockwise, which pushes the right end DOWN and flattens the very
     climb the drawing is there to provide. Sampled off painted alpha, the rise
     from the trail's left third to its right third went 37px at +6 to 82px at
     -12 — the descent into the band reads about twice as hard for no change in
     size or position.

     Do not push much past this. At -16/-20 the trail crosses the tear by 36-51px
     against the butterfly's 26, so the line art outruns the piece it belongs to
     and lands well inside the dark band. */
  transform: rotate(-12deg);
}

/* Painted side-view butterfly perched where the two panels TOUCH — the corner
   at which the lavender scrap begins overlapping the teal one. PAINTED, so it
   needs no colour change as it crosses from one to the other; that is the whole
   reason a butterfly works on a join where a leaf would have needed a two-copy
   crossover.

   The spot is the only real pocket on the seam. Mapping both panels' text, the
   corridor x605-800 is clear from the top of the section down to y1737, where
   the lavender panel's own copy starts — 195 x 140. Everything below that is
   two columns of writing with only a ~75px channel between them.

   scaleX(-1) to face left: this drawing is exported facing RIGHT, the same as
   the home page's .hero-corner-bfly, which carries the identical mirror for the
   identical reason. Written before the rotate in source order so the mirror
   applies first and the tilt still reads in screen space. */
.twocol-gap-bfly {
  /* -19px, not more. .about-twocol carries 3.5rem of bottom padding, so the
     section's edge sits ~56px BELOW the panels themselves — anchoring further
     down dropped the butterfly clear of them and into the gap. */
  /* LEFT of the join, so the butterfly sits mostly on the light teal panel and
     only its trailing wing reaches the lavender. The two panels overlap at
     x608-627, so "on the seam" and "on the teal" are about 90px apart. */
  left: 42%;
  bottom: -19px;
  width: min(110px, 9%);
  z-index: 3;
  transform: rotate(-8deg) scaleX(-1);
}

/* ---------- Beyond Lumi Libra — the sprig that changes colour at the corner ----
   Lauren: "put sage leaves on the side, facing left, by the top right corner of
   beyond lumi libra section. i want them to overlap into the blue, which means
   they should switch to white."

   That is the site's crossover: ONE drawing, two colourways, two copies at
   pixel-identical positions, each showing only on its own side of a torn edge.
   Sage while it is on the paper, white the moment it crosses onto the blue.

   No clip wrapper here, unlike the crossovers pinned to full-bleed band edges.
   The card is .torn-paper, so it is position:relative with z-index auto — and
   the sage half is a positioned sibling placed BEFORE it, so the two paint in
   DOM order and the CARD ITSELF hides the sage wherever the blue is. The white
   half is a child, so the card's mask crops it to the blue. The colour therefore
   changes along the real torn contour, not along a straight line. This is the
   same construction the home page's club-card sprig uses.

   The two must stay identical copies or the effect breaks, so left / top /
   width / transform / opacity are set ONCE, on the shared selector. Opacity
   counts as alignment: letting one half inherit a different value makes the
   drawing visibly change density as it crosses the edge.

   Both resolve their percentages against boxes that share left, width and top —
   the white half against .beyond-card, the sage half against .beyond-wrap, which
   the layout rules above force to exactly the card's box. That is what stops
   them drifting apart on resize.

   MOVED TO THE LEFT-HAND CORNER, MIRRORED, on 2026-08-24 — "take that one and
   mirror flip it and put it coming down from the left side instead."

   It is an EXACT mirror, which did not have to be true: `top` below was tuned
   against the RIGHT-hand column's copy, so there was no reason to expect the same
   value to clear the left one. Sampling painted alpha at each candidate height,
   -35% comes back 59.2px clear on this side against 59.5px on the old one, and
   the paint lands 37px past the left page edge exactly as it used to sit 37px
   past the right. The card's two lists are near enough symmetrical that the
   drawing simply swaps sides. Nothing shallower is free: -30% falls to 24.5px of
   clearance and -26% is already touching the copy.

   THE ORDER OF THE TRANSFORM IS THE WHOLE TRICK, and it is the opposite of the
   convention everywhere else in this file. `scaleX(-1) rotate(-100deg)` applies
   the ROTATION first and mirrors the finished drawing, which is what produces
   the mirror image of what stood on the right. Written the usual way round —
   `rotate(-100deg) scaleX(-1)` — the artwork is mirrored before it is turned,
   and it lands somewhere else entirely.

   Originally: "put sage leaves on the side, facing left, by the top right corner
   of beyond lumi libra section", one rotation and no mirror, stem off top-right. */
.beyond-corner-sage,
.beyond-corner-white {
  /* Out from -7.5% to hide the stem — at -7.5% it cleared the viewport by only
     2px at 1280, leaving the bare stalk on the page; at -11% it is 37px past the
     edge. Anchored from the LEFT since the mirror puts the stem on that side.
     Set on the SHARED selector so both colourways move together and the
     crossover stays in register. */
  left: -11%;
  /* Lifted so the sprig's body lies straight across the card's top-right corner
     and the colour change happens ON the corner rather than below it.

     -35% is also the first height that is genuinely clear of the copy at this
     size, and that was measured by sampling the drawing's PAINTED ALPHA, not its
     box. At the original -25.8% the box overlapped "Talking to trees absolutely
     counts as therapy" and so did 157 real painted pixels of leaf. Stepping up:
     -29% still put 17px of leaf on that line; -32% is the first clean one. Never
     trust the bounding box on a rotated sprig — it is mostly empty, so it both
     invents collisions and hides real ones. */
  top: -35%;
  /* 230px. It was matched to .beyond-foot-leaf so the page's sage segments read
     at one scale; that piece came off on 2026-08-24 and this is now the page's
     only sage segment, so the number is kept rather than re-derived. */
  width: min(230px, 23%);
  opacity: 0.5;
  transform: scaleX(-1) rotate(-100deg);
}

/* ---------- Beyond Lumi Libra — the white flight inside the blue ----------
   Lauren: "lets try the white dotted butterflies in the blue. but try so the
   butterflies arent on top of text."

   That constraint is placeable only because the drawing is not uniform. Read off
   its alpha channel, `path-white-bflies.webp` (820x507) is three things: a
   butterfly in the TOP-LEFT corner (0-15% across, 0-20% down), a second one at
   the BOTTOM-RIGHT (78-98% across, 59-95% down), and a thin dotted trail looping
   between them across the middle. So the two CORNERS are what have to land in
   clear space; the hairline trail between them can pass over a line of copy the
   way the home page's trails do.

   The card's only real pocket is its bottom-left — the left list ends about
   150px above the right one. At this size and offset the top-left butterfly sits
   at x160-214 against a left column that starts at x220, and the bottom-right
   one at x441-513 / y4441-4521, below where that column ends. Only the dotted
   middle crosses anything.

   360px is what the same drawing takes on the home page, where it spans the two
   panels. Deliberately identical: this is the site's one dotted
   flight-with-butterflies, and it should read at a consistent scale wherever it
   appears — the rhyme is in the placement, not in the size. */
.beyond-flight {
  /* Moved right so the small butterfly lands in the GUTTER between the two
     lists — the one genuinely open channel through the middle of this card.

     The 20px size drop from 360 is not cosmetic and shouldn't be tuned back up.
     Sweeping every left/bottom pair in the live card at 360px unflipped returns
     exactly ONE collision-free placement, the far-left one this replaces: at
     that size, any offset that puts the small butterfly in the gutter drags the
     large one into the right-hand column. At 340 the pair fits the channel. */
  /* 30% -> 34% on 2026-08-12, and it was the copy that moved, not taste: the
     emoji Lauren added to each list line pushed "I'm a Snoopy lover for life."
     21px further right, into the small butterfly. Re-swept the way the note
     above describes — left 28-40 against bottom 16-24, painted alpha against
     the LINE rectangles rather than the <li> boxes — and 34% is the nearest
     clean column to the old value at this height. 32% is clean only at
     bottom 24%.

     Sample the glyph lines, not the elements: an <li> box runs the full column
     width, so half these pairs report a collision against empty space at the
     end of a short line. */
  /* 34% -> 38% and 20% -> 26% on 2026-08-13. Lauren: "for desktop version we
     need to move the white dotted butterflies. move to the right and up a little
     so they arent covered by text."

     It was 332 sampled points of painted alpha on the list copy at 1280, mostly
     on "Dancing around the house and belting out to throwback songs will forever
     be my jam." — the same failure this piece has had twice before, and the same
     cause both times: the copy moved, not the drawing.

     Swept the live card again the way the notes above describe — left 34-48%
     against bottom 20-32%, painted alpha against the LINE rectangles, never the
     <li> boxes. Two clean rows come back: bottom 26% is clean from left 34 all
     the way to 46, and bottom 29% only at 34-36. 38/26 sits INSIDE the wide
     clean row rather than on its edge, so there is room either side of it if the
     copy shifts again — which on this card it will. */
  left: 38%;
  /* Anchored off the card's BOTTOM rather than its top. What this piece has to
     stay clear of is the foot of the two lists and the tear, and both of those
     are measured from down there. */
  bottom: 26%;
  /* 260, and the size is set by the position rather than chosen. Sweeping the
     live card, the drawing's two butterflies both clear the copy at 340px only
     along the very bottom of the card (bottom: 6%, and only at left 46-50%).
     Every step UP costs width, because the higher the drawing sits the more of
     the right-hand column the large butterfly has to clear: 300 and 280 buy
     nothing, 260 is the first width with a clean slot up here. */
  width: min(260px, 26%);
  opacity: 0.9;
}

/* ---------- Thanks for being here — the vine's closing step ----------
   Teal on paper, per the site rule: white leaves on the coloured surfaces,
   coloured leaves on the white. On the RIGHT, running down toward the footer's
   tear, which is the same closing gesture the home page's .vine-closing-right
   makes — a rhyme, not a copy: different angle, different size, and against a
   much shorter section. */
.thanks-leaf {
  right: 0%;
  /* ANCHORED FROM THE BOTTOM since 2026-08-24 — "lets bring them so they rest in
     the bottom right corner". It was `top: 2.5rem`, which hung it in the upper
     right of the section, level with the signup panel.

     `bottom: 0` and not lower, and the footer is the reason. This section's foot
     and the footer's torn top are the SAME line (y5793 at 1280), the footer is a
     later sibling, so anything of this drawing that reaches past that line is
     painted over by the navy and shows only where the wave happens to trough —
     leaves apparently growing out of the tear, which is the exact failure the
     phone rule below already records at -78px. At `bottom: 0` the painted foot
     lands at y5748, 45px clear of it.

     Nothing to dodge on the way down: the copy it shares the section with
     ("Thanks for stopping by." and the signature) is CENTRED, so its line rects
     end at x710 while this paints x987-1320 — 251px of clearance, against 53px
     up where it used to sit. It is a freer corner than the one it left.

     Top-anchored is still right on phones, where the section is much shorter and
     the sign's line is the thing to clear; that rule sets its own bottom and is
     unaffected by this. */
  bottom: 0;
  width: min(250px, 21%);
  opacity: 0.45;
  /* Laid down almost flat with the STEM on the right, so the vine reads as
     entering from the page margin — which is the rule the whole site follows:
     teal and sage come in from the edges, white lies inside the colour.

     No mirror is needed to get the leaves hanging downward, and that is worth
     stating because the obvious move here is a scaleY. The stem is at the
     drawing's foot and the leaves fan up off it, so ONE rotation does both jobs:
     at -96deg the foot maps to the right (and 6deg above level) and the leafy
     end maps to the left and slightly below it. Adding a flip on top would only
     curl the leaflets back the other way. */
  transform: rotate(-96deg);
}


/* ---------- Narrow widths ----------
   Lauren, 2026-08-05: "i also want these to show on mobile / do the mobile
   version as we go along." That REVERSES the standing rule from the 2026-08-04
   pass, which hid everything new below 700px — decoration now carries over to
   the phone, and each piece gets a placement designed for the stacked layout
   rather than one that falls out of the desktop rule by accident.

   What changes on a phone is not the size of the pieces so much as WHERE the
   room is. At 1280 the copy is a column with clear margins either side, so a
   sprig can enter from the left or right beside the writing. At 390 the copy
   runs the full width, so the only pockets are the horizontal bands BETWEEN
   blocks — and the two sprigs have to move into different ones, or they land on
   top of each other.

   So the pair keeps its desktop relationship (sage above and on the left, teal
   below and on the right) but takes a bigger vertical step: sage into the clear
   band under the blue scrap, teal into the band above the footer's tear, with
   the "Thanks for being here" block left completely alone between them. */
@media (max-width: 700px) {
  /* The hero's dotted trail. It was OFF on a phone for a while — it is a
     hairline mark on a busy photograph and the desktop angle gave it nowhere to
     go — but Lauren brought it back with a job: "make the white dotted line
     under the small white butterfly, going vertically."

     So it is re-cut for the phone rather than un-hidden. Stood on end at 90deg
     and hung under .hero-hand-bfly, it runs down the hero's left margin, which
     is the one genuinely empty lane on this photograph: the figure is centred
     and the wordmark does not start until y519.

     Everything stays in PERCENTAGES for the same reason the butterflies do —
     the hero is sized in vh, so on a phone it restretches every time the address
     bar hides, and a px offset would slide the trail off the butterfly it hangs
     from while the butterfly itself stayed put.

     The offsets look strange because they are the ELEMENT box, and this drawing
     is turned on its side: at 240px wide the element is 240x84, and rotating it
     about its own centre leaves a painted box 84 wide by 240 tall. Working back
     from where that has to land (centred on the butterfly at x32, starting just
     below it at y180) is what puts the element's own left edge off the page. */
  .hero-white-path {
    display: block;
    right: auto;
    /* Moved right in step with .hero-hand-bfly — the trail is hung off that
       butterfly, so the two offsets have to change together or the dots stop
       reading as its flight path. Then back left 8px, and after the mirror
       right again by 14 — the flip moved the drawing's visual weight without
       moving its box, so the two ends stopped agreeing. This lands the trail's
       painted centre at x56 against the butterfly's painted centre at x52, i.e.
       hanging directly beneath it. Both centres are the PAINTED ones; the boxes
       disagree by 10px because neither drawing sits centred in its own frame.

       A PERCENTAGE ALONE CANNOT HOLD THIS. The butterfly is positioned in %, so
       it slides with the viewport; this trail is a fixed 240px, so a plain % put
       its painted centre 4px right of the butterfly's at 390 and 27px LEFT of it
       at 699, where the two had visibly come apart. The calc locks the gap.
       Turned on its side this drawing's painted centre is just its element
       centre, left + 120; the butterfly's painted centre is left + 22.75. So
       the px constant IS the offset between the two, and it holds at every
       width: 93.25 sets the trail 4px right of the butterfly, 75.25 sets it 22px
       right — which is where Lauren wanted it, the trail falling past the
       butterfly's trailing wing rather than out of its middle. Re-derive if
       either piece's width or rotation changes. */
    left: calc(7.5% - 75.25px);
    top: 41.3%;
    width: 240px;
    /* Down from the desktop 1. On a phone this trail is the longest white mark
       on the photograph and it sits in the empty left lane with nothing to
       compete with, so it carried more weight here than it does at 1280 where
       the figure fills the frame. The drop-shadow stays — it is what separates
       the dots from the bright patches behind them, and taking IT away is what
       actually loses the line, not the opacity. */
    opacity: 0.85;
    /* Clockwise, so the drawing's LEFT end — where the dots begin, finest and
       most widely spaced — maps to the TOP, right under the butterfly, and the
       trail thickens as it falls away. Turned the other way it would read as
       flying up into her.

       scaleX is written BEFORE the rotate, which means it applies LAST — so it
       is a mirror in SCREEN space, and the trail's curve swings to the other
       side while staying vertical. That is the opposite of the site's usual
       order, and deliberately: written after the rotate it would mirror the
       drawing in its own space, which on a piece stood on end reads as a
       top-to-bottom flip and would send the loop to the top instead. */
    transform: scaleX(-1) rotate(90deg);
  }

  /* Further left, and sized off the 24px the desktop rule collapsed to —
     `min(58px, 5%)` resolves against the viewport, so 5% of 390 is a speck.
     Then DOWN again to 42 at Lauren's call: it is the smaller of the hero's two
     butterflies and has to stay the smaller one once its partner grew. */
  .hero-hand-bfly {
    left: 7.5%;
    top: 17%;
    width: 42px;
    /* Lauren: "lets fade all the white images in the hero just a little." Down
       from 0.85. Kept a step below its open-winged partner, the same as at
       1280 — this one is the echo, not the feature. */
    opacity: 0.72;
  }

  /* The open-winged one, sized up. `min(110px, 9%)` had collapsed it to 35px —
     a speck out on the right of the photograph — and Lauren asked for it bigger.
     Up to 72 and then back to 62 on her eye. Either way it stays clearly the
     larger of the hero's two butterflies — this one is the feature, the side
     view by her hand is the echo — and clear of the frame's right edge. */
  /* Down from 0.9. Still the strongest white mark in the hero, which is the
     order the desktop rules set too. */
  /* Down the frame from the desktop 57%, which put it level with her elbow. 83%
     is the floor rather than a chosen number: the box lands y473-530 and the
     hero's tear starts at y547, so there are 17px left under it. Anything more
     and the butterfly is half on the paper below, where white art disappears. */
  /* Lauren, 2026-08-06: "the white butterfly is missing on mobile in the hero
     section. there should be the same one on desktop on the bottom right side
     next to about lauren."

     It WAS missing, and this is why: the desktop rule pins it with
     `left: calc(50% + 425px)`, and this block set width, opacity and top but
     never the horizontal. At 390 that resolves to x616 on a 390px page — the
     whole drawing was off the right edge, which is also why the note above,
     describing it as sitting beside the wordmark, did not match what rendered.

     `left: auto` is the part that matters; without it the desktop `left` keeps
     winning and a `right` value does nothing. 16px lines it up with the page
     gutter .wrap already uses. The wordmark ends at x262 and the painted
     butterfly runs x306-367, so it clears the type by 44px and the frame's edge
     by 23. */
  .hero-white-bfly {
    width: 62px;
    opacity: 0.78;
    top: 83%;
    left: auto;
    right: 16px;
  }

  /* Lauren's call: the teal-and-purple butterfly on the My Story photo comes off
     on a phone. At this width the photograph is nearly full-bleed, so a 154px
     painted butterfly straddling its top-left corner reads as sitting ON the
     picture rather than beside it — and the crossover sprig just above it is now
     doing that job at the tear. */
  .mystory-corner-bfly { display: none; }

  /* The crossover under the wordmark, sized to match .thanks-leaf at the foot of
     the page (150px) so the page opens and closes on the same size of vine —
     Lauren: "note the size of the leaves at the very bottom of the mobile, make
     them the same size."
     `min(230px, 18%)` had collapsed this to 70px and, with the desktop 7.6rem
     drop, parked the whole thing BELOW the tear where it was teal end to end and
     the colour change never happened.

     5.75rem is the drop, and it is the bottom of a narrow window rather than a
     free choice. The band this has to live in runs from the title's baseline
     (y564) to the top of the My Story photograph (y697), the tear wanders
     between 595 and 625 inside it, and the drawing's PAINTED area is 215x148
     once it is turned on its side — it very nearly fills its own box, so there
     is no slack to borrow.

     Measured by sampling painted alpha through the element's matrix rather than
     by its bounding box: at 5rem it sat y522-670, at 5.75rem y534-682 — Lauren
     asked for it "down some, so they overlap into the white" — and 6.5rem would
     put it at y546-694, three pixels off the photograph. Going up instead costs
     the title: 4.4rem puts 36 painted pixels on it and 3.4rem puts 97.

     At 5.75rem the tear splits it 61px of white on the photograph above and
     87px of teal on the paper below. */
  .hero-tear-white,
  .hero-tear-teal {
    width: 150px;
    --hero-drop: 5.75rem;
    /* In from the desktop 0.9%. Set on the SHARED selector like everything else
       here: the two halves are one drawing in two colourways and any value that
       moves one has to move both, or the vine visibly steps sideways as it
       crosses the tear. */
    left: 5%;
  }

  /* Both run at 145-150px, which turned on their side is a painted box ~275px
     across — over two thirds of this viewport. That is proportionally MUCH
     larger than at 1280, and deliberately so: a sprig scaled down by the same
     percentage as the layout stops reading as a drawing at all. */

  /* The sage sprig under "My Story", matched to the hero's vine at Lauren's
     call — so the two sage/teal segments in the top half of the page read at
     one size, the same way .thanks-leaf and the hero crossover do at the
     bottom. `min(230px, 18%)` had collapsed it to 70px.

     The ANGLE has to give with the size. At the desktop -103deg a 150px sprig
     measures 245x195, and the pocket here is 202px tall: the My Story copy ends
     at y2209 and the light teal panel's first line is at y2411. Flattening to
     -96deg — the same angle .thanks-leaf takes at the foot of the page — brings
     it to 252x165, and at top -120px it lands y2230-2395 with ZERO painted
     pixels on either block of copy (sampled through the element's matrix; the
     desktop angle put 1595 there and no offset cleared it).

     That also drops it across the light teal panel's torn top edge, 105px of it
     on the paper above and 60px on the colour below — the crossing the desktop
     version makes at the lavender panel further down.

     Set on .twocol-top-leaf alone rather than on the shared selector, and its
     white partner is REPLACED rather than moved. That half is a child of the
     LAVENDER panel, which on a phone has stacked ~1100px below this — it is
     cropped out of sight by its own panel's mask and can never follow the sage
     half onto the teal one. So the crossover is rebuilt here against the panel
     the sprig actually crosses: .twocol-teal-leaf-white, a phone-only copy
     inside .about-col-left, below.

     NO z-index. That is the whole construction: the panel carries z-index 2 and
     the sage half is a sibling written BEFORE it, so the panel paints over the
     sage wherever the colour is and the white copy inside the panel takes over.
     Giving the sage z-index 3 — which is what the two pieces at the panels'
     feet need — would put it on TOP of the teal and kill the colour change. */
  .twocol-top-leaf {
    width: 150px;
    /* Up and left on Lauren's eye across two rounds: -120px/6%, then
       -132px/10%, then -142px/16%, then back a touch to 13%. Both halves move
       together — see the conversion on .twocol-teal-leaf-white below.

       Painted band y2208-2373, x137-389. The box now reaches the same height as
       the last line of My Story copy (which ends y2208), so the BOX test is
       useless here — every painted pixel was sampled through the element's
       inverted matrix at 1px steps and none of them land on that line, because
       the leaves at that height sit right of x273 where the line ends. Down to
       320 and up to 699 it stays at zero. Do not "tidy" this by trusting the
       rectangle. */
    top: -142px;
    /* 13% -> 27px. Lauren, 2026-08-06: "move the sage leaves next the blue
       butterfly to the right just a tiny bit to hide the stem." Turned -96deg
       the foot maps to the RIGHT, so the stem hides by overhanging the page —
       and it was not overhanging at all: the painted tip sat at x389 on a 390px
       page, 1px INSIDE it, with the whole 17.4px stalk on show.

       17.4px is 65 asset rows of leaf-vine-sage at this 150px render, sampled up
       from the drawing's foot. 27px puts the tip 22px past the edge, the first
       value that clears it, for 22px of leaf out of 250 painted — 9%.

       PX, NOT A PERCENTAGE, and that is the substantive change. `right` here
       resolves against a full-width box while the drawing is a fixed 150px, so a
       percentage drifts against it: 7% is identical to 27px at 390, but gives
       27px of overhang at 320 and **0.4px at 699**, where the stem comes back.
       The old 13% was worse still — 41px of stalk exposed at 699. A px value
       holds the overhang at 22.3px at every width.

       BOTH HALVES TAKE THIS VALUE. .twocol-teal-leaf-white below carries the
       identical `right`, and they are only a crossover while it does — verified
       here by measuring both painted boxes and checking their left and right
       edges match exactly at every candidate. */
    right: 27px;
    transform: rotate(-96deg);
  }

  /* The white half, on the light teal. Its offsets are the sage half's,
     converted for the one box difference between them: this panel's top sits
     32px below .about-twocol's, so -142 becomes -174. Horizontally there is
     nothing to convert — stacked, the panel is the full width of the section,
     so 10% resolves against the same box either way. That is only true once
     the columns stack, which is why this piece is phone-only.

     width / transform / opacity must stay identical to the sage half or the
     drawing visibly changes shape and density as it crosses the tear. Opacity
     counts as alignment. */
  .twocol-teal-leaf-white {
    display: block;
    width: 150px;
    top: -174px;
    /* Must stay identical to .twocol-top-leaf's `right` — 13% -> 27px with it on
       2026-08-06. Both resolve against full-width boxes, so the same value lands
       both in the same place; change one alone and the colour change comes
       apart. */
    right: 27px;
    opacity: 0.5;
    transform: rotate(-96deg);
  }

  /* A small blue side-view butterfly hovering above the sage sprig's leaf tips.

     Anchored to .about-twocol's top in px, exactly as .twocol-top-leaf is, so
     the two move as one when the My Story copy above reflows. Anchoring it to
     anything else would let the gap between butterfly and leaves open and close
     with the width, which is the failure this page has already had twice.

     55px, the smallest butterfly on the phone layout after the hero's 42px
     side view — Lauren asked for it smaller than the seam butterfly, and it is
     a hovering mark rather than a feature. */
  .twocol-tips-bfly {
    display: block;
    left: 31%;
    top: -73px;
    width: 55px;
    opacity: 0.9;
    /* Unmirrored, so the drawing keeps its exported facing (right) and looks
       back along the sprig toward the stem. Negative tilt lifts its nose. */
    transform: rotate(-12deg);
  }

  /* The other sage sprig Lauren spotted in that section — and it is not really
     "in" it, it has escaped. .beyond-corner-* is pinned at top: -35% of the
     Beyond card; on a phone that card is 1162px tall, so -35% lifts the sprig
     407px clear of it and lands it 280px ABOVE the card, floating in the middle
     of "Why I Started Lumi Libra" with nothing to sit on. Both halves go, since
     they are one drawing in two colourways. */
  .beyond-corner-sage,
  .beyond-corner-white { display: none; }

  /* Lauren's call: the white dotted butterflies come off the blue card on a
     phone. That drawing is placeable at 1280 only because it is three things —
     a butterfly in each far corner and a hairline trail between them — and the
     card's copy leaves a clear pocket for each corner. Stacked into one narrow
     column the card is solid text top to bottom and there is no such pair of
     pockets left. */
  .beyond-flight { display: none; }


  /* ---------- The teal-and-purple side view and its trail, at the foot ----
     Lauren: bigger, and further left. `min(110px, 9%)` and `min(180px, 15%)`
     had collapsed the pair to 35px and 59px — specks.

     The two are ONE gesture (the trail emerges from the butterfly's wing seam),
     so the trail is rescaled by the same factor and its offsets converted, not
     re-eyeballed: at 1280 the trail's box bottom sits 38px above the butterfly's
     element bottom at 110/180px, so at 80/131px that becomes 28px, and the
     14-point leftward move is applied to both.

     80px, not more, and the ceiling is the DARK TEAL BAND below rather than
     taste. The lavender panel's last line ends y3926 and the band starts y4068,
     so the pocket is 142px; the rotated butterfly measures 114. Any bigger and
     it either lands on that copy or runs down onto the dark teal, where a
     teal-and-purple painted drawing has almost no contrast left. */
  /* 2026-08-07: both moved right 8 percentage points, 28 -> 36 and 32.8 -> 40.8.
     Lauren: "move both of those (together) to the right a bit more."

     THE 4.8pp BETWEEN THEM IS THE COUPLING and must survive any future move —
     the trail emerges from the butterfly's wing seam, so they are one gesture,
     not two pieces that happen to sit near each other. Shift both by the same
     amount or the trail detaches from the wing.

     8pp is 31px at 390. Swept to +12: nothing collides at any step, so the limit
     is taste rather than geometry. At +8 the trail's painted end reaches x291 of
     390, keeping a 99px right margin; zero painted pixels on either panel's copy.
     Vertical is untouched, so the 142px pocket above the dark teal band that
     sets this pair's SIZE (see the note above) is unaffected. */
  .twocol-gap-bfly {
    left: 36%;
    bottom: 13px;
    width: 80px;
  }

  .twocol-gap-path {
    left: 40.8%;
    bottom: 41px;
    width: 131px;
    /* Pinned on 2026-08-24, when the base rule went to -12deg to steepen the
       descent on desktop. "the mobile can stay the same" — this block already
       overrode left/bottom/width but NOT transform, so without this line the
       new angle would have reached the phone too. */
    transform: rotate(6deg);
  }

  /* ---------- The teal sketch butterfly on the panels' seam ----------
     Lauren: "add a teal sketch butterfly between the light teal box and the
     lavender box… have it overlap the purple, white, and light teal space."

     Three surfaces in one drawing, which is only possible because this is a
     PAINTED butterfly rather than a line vine — it needs no colour change as it
     crosses, the way .twocol-top-leaf does. That is the same reasoning the
     desktop .twocol-gap-bfly follows at the panels' other join.

     The anchor is the whole trick — see the note on it in the markup. Height 0,
     in flow, so it pins itself to the left panel's bottom edge no matter how far
     the copy reflows.

     z-index 3 is load-bearing: .about-col-left carries z-index 2 and
     .about-col-right z-index 1, so anything meant to lie across BOTH has to
     clear the higher of them. At the default 0 this would be buried under the
     teal panel and only the lavender half would show. */
  .twocol-seam-anchor {
    display: block;
    position: relative;
    height: 0;
    z-index: 3;
  }

  .twocol-seam-bfly {
    /* Right, toward the middle of the band rather than the page's left edge. */
    left: 24%;
    /* Set so the drawing covers all three surfaces Lauren asked for. The anchor
       sits on the teal panel's bottom edge and the lavender starts 48px below
       it, so the painted box has to straddle that whole band: at 135px wide and
       10deg it measures 149x114, and -30px lands its PAINTED band 40px up on
       the teal, across the 48px of white, and 17px down onto the lavender —
       still all three surfaces, riding high in the band where Lauren put it.
       Note painted, not box: the box reaches 10px further down than the drawing
       does, so judging this one by its rectangle overstates the lavender, and
       that last 17px is the budget. Do not raise it further without shrinking.

       This is aspect-sensitive, not just size-sensitive. The first drawing tried
       here was 320x288; bfly-teal-open is 360x246, so at the same width it is
       20px shorter and stopped 22px short of the lavender entirely. Re-measure
       the box if the drawing is ever swapped again. */
    top: -30px;
    width: 135px;
    z-index: 3;
    /* Positive = tilted right. No mirror: the drawing is a near symmetric
       open-winged sketch, so the angle alone gives it direction — and because
       the tilt is symmetric the box measures the same either way, so the three
       coverage figures above hold unchanged. */
    transform: rotate(10deg);
  }

  /* The teal flight in the clear paper above the blue scrap.

     scaleX(-1) is what makes it "facing right". As exported this drawing has
     the butterfly at its LEFT end with the dotted trail and its heart loop
     running away to the right, so it reads as flying LEFT; mirrored, the
     butterfly leads to the right and the trail follows it in from the margin.
     Written AFTER the rotate in source order so it applies FIRST and the 6deg
     still reads in screen space. Same construction as .twocol-top-flight, which
     carries the same drawing on desktop.

     Anchored to .beyond-wrap, whose top IS the card's top, so it holds its
     distance above the scrap however the origin section's copy reflows. The
     pocket is real but shallow: the copy above ends y6785 and the card starts
     y6916, and at 190px the tilted drawing measures 196x84, which leaves 23px
     of clearance above and 24 below. */
  .beyond-top-flight {
    display: block;
    /* TRIED AND REVERTED, 2026-08-06 — left at the page edge on purpose.
       Lauren asked to move it right "so it takes up more of the white space"
       (there are 201px of empty band to its right), then "thats a bit too far to
       the right" at x142-330, then "honestly keep it how it was". So it is back
       at -4%, painting x1-189. Both intermediate positions read worse than this
       one; don't re-derive them.

       If it IS ever moved right, anchor from the right in px rather than using
       `left: N%`: the offset resolves against .beyond-wrap, which grows with the
       viewport, while this drawing is a fixed 190px. A `left: 36%` that looks
       right at 390 leaves a 14px margin at 320 and puts the trail 56px off the
       page at 699. */
    left: -4%;
    /* Widened 190 -> 250 on 2026-08-06, Lauren: "expand it a little so it
       stretches across that space more". It still starts at the page edge; the
       extra 60px all goes to the right, cutting the empty band beside it from
       196px to 135px. The tilted box grows with it, 195x77 -> 257x101, and the
       pocket between "Think of me as your personal hype woman." and the blue
       scrap is only 125px tall, so `top` comes up to -100px to split the
       remaining 24px evenly above and below. Any wider and the drawing lands on
       the copy — measured, not guessed. */
    top: -100px;
    width: 250px;
    opacity: 0.8;
    transform: rotate(6deg) scaleX(-1);
  }


  .thanks-leaf {
    width: 150px;
    /* Anchored off the section's BOTTOM edge rather than its top, so it stays
       pinned above the footer tear whatever the copy above it does when it
       reflows to a narrower phone. */
    top: auto;
    /* The clear band between "Lauren ♡" (ends y8509) and the footer's tear
       (y8616) is only 107px, and this drawing's painted box is 172px tall once
       it is turned on its side. So it has to ride UP into the sign's line rather
       than down into the navy: at -78px two thirds of it was behind the footer
       and read as leaves growing out of the tear. At -18px it clears the footer
       and only its far leaf tips reach x245, where the sign's text ends at
       x252 — a 7px pass behind the very end of the line. */
    bottom: -18px;
    /* Left by 58px from -46, the mirror of the move .beyond-foot-leaf makes on
       the other side: Lauren wanted more leaf on the page and the stem still
       off it. This drawing's foot is its RIGHT end (-96deg), and it carries
       leaves to within 4px of that foot, so there is barely any bare stalk to
       hide — 12px of overhang is enough, and it recovers 58px of leaf that was
       hanging past the right edge. Past about 24px the foot itself comes onto
       the page. */
    right: 12px;
  }

  /* ---------- "Why I Started" — both pieces OFF on a phone ----------
     Lauren, 2026-08-06: "in why i started lumi libra, there should be no dotted
     line or teal butterfly on mobile."

     This is one of her by-name removals, not a return to the old blanket hide —
     the rest of the page keeps its phone placements. Worth recording why it is
     the right call here anyway: the desktop idea is a butterfly out in the right
     margin with its flight descending 300px beneath it, and neither half of that
     survives the stack. There is no margin, and the tallest clear pocket
     anywhere in this section is 69px, so the trail cannot descend at all. Laid
     flat in the band beside the paragraph's ragged last line they fit and read
     clean, but they read as a different, smaller idea than the one on desktop.

     They were ALSO broken before this: `min(130px, 17%)` resolves against the
     paragraph, so at 390 the butterfly came out 68px at x380 — one wing on the
     page, the rest clipped — and the trail started at x422, off the page
     entirely. So this is not hiding something that was working. */
}

/* The white dotted butterflies come off up to 1050 as well — 2026-08-13, found
   while moving them right and up for Lauren on desktop.

   The lists stay two columns down here, but the gutter between them narrows with
   the card while the drawing does not shrink as fast (`min(260px, 26%)` only
   starts binding below 1000), so the channel it flies through closes: 266
   painted points on the copy at 1000 and 392 at 900, against zero from 1051 up.

   Not a placement problem. Swept 45 combinations at 900 — widths 200/180/160
   against left 30-46% and bottom 8-26% — and NONE came back clean, so there is
   no offset to move it to; the card is simply full at that width. 1051 and 1060
   both measure zero, which is where the boundary is set.

   WRITTEN AS ITS OWN BLOCK, AFTER the phone block above closes. The first
   attempt put this @media opener in the MIDDLE of that block, which closed it
   early and swallowed ~200 lines of phone rules into a 701-1050 query — the
   phone lost `.twocol-gap-bfly` at 80px (it fell back to the desktop percentage
   and rendered 34px), `.twocol-gap-path`, `.beyond-foot-leaf` and
   `.thanks-leaf`. Lauren spotted it as "the teal and purple butterfly and dotted
   line... is super small". Never open a media query inside another one's body. */
@media (min-width: 701px) and (max-width: 1050px) {
  .beyond-flight { display: none; }
}

/* ---------- The tablet band, 700-1100: two pieces that fall off the page ----
   Both found on 2026-08-12 by sweeping this page at 320/390/430/699/760/900/
   1100/1280/1440/1600/1920 and measuring how much of each drawing lands outside
   the viewport. Neither was visible to a reader in this range; both LOOK fine in
   the CSS, which is exactly why they survived — a piece that is 100% off-page
   reads as "no decoration here" rather than as a bug.

   .hero-white-bfly is anchored `left: calc(50% + 425px)`, which is a fixed
   distance from the window's CENTRE. That is on the page only while the window
   is wide enough to have 425px + the drawing to the right of centre: at 1100 it
   ends 20px inside the edge, at 900 it runs to x961 on a 900px page, and at 760
   to x878 — 153% of the drawing outside the viewport. The phone rule below 700
   already fixed this the right way, with `left: auto; right: 16px`; this carries
   the same anchoring up through the band and meets the desktop rule exactly at
   1100, where both put the drawing 20px in from the right. */
@media (min-width: 700px) and (max-width: 1100px) {
  .hero-white-bfly {
    left: auto;
    right: 20px;
  }


}

/* ---------- Very narrow phones ----------
   One piece cannot hold its phone placement all the way down, and it is worth
   saying why rather than nudging it: .hero-white-bfly sits level with the
   wordmark, in the gap between the end of "About Lauren" and the right edge of
   the frame. The wordmark's width barely moves with the viewport — it ends at
   x259 on a 320 screen and x274 on a 699 one — but the frame's edge moves the
   full amount, so that gap is 60px at 320 and 425 at 699. The painted butterfly
   is 61px across. It simply does not fit beside the title down here: at 320 it
   landed 4160 painted pixels on the word "Lauren".

   Nothing horizontal fixes that — pinning it to the edge in px only makes the
   inset worse. So below 355px it steps UP out of the wordmark's line instead,
   into clear photograph, and keeps its size. 355 is where the sums stop
   working: the gap clears 61px at about vw 352. */
@media (max-width: 355px) {
  .hero-white-bfly { top: 64%; }

  /* The teal vine under "Self-Expression", 12px further left on the narrowest
     phones. Its clearance to .pillars-blue-bfly is not constant across the phone
     range, and it is not constant because the two are anchored to opposite ends
     of the wrap by different kinds of value: the vine's width is `min(190px,
     48%)`, so it narrows with the viewport, while the butterfly holds a fixed
     `right: 79px` and so tracks the wrap's right edge inward. Measured as
     painted alpha, nearest point to nearest point, the gap runs 17.7px at 390
     and 16.4 at 360 but collapses to 4.1 at 320 — near enough to touching to
     read the way Lauren called out at 390. -19px restores it to ~16.

     Specificity has to MATCH the phone rule this refines (`.pillars` plus the
     class); a bare `.vine-pillars-left` here would lose to it despite sitting
     later in the file and inside a narrower query. */
  .pillars .vine-pillars-left { left: -19px; }
}


/* ==========================================================================
   Self-Love Club — LAVENDER hero
   Lauren, 2026-08-05: "change self love club to the purple that matches the home
   pages self love club." That is --panel-lav, the colour of the club card on the
   home page — so the offer is the same colour wherever it appears, and the page
   announces itself in the club's own hue from the first screen.

   This inverts the band: it was deep teal with cream type reversed out, and
   --panel-lav is a LIGHT colour, so every one of those reversed values has to
   flip with it. The type treatment below is the home club card's exactly —
   navy heading, slate body, purple CTA.

   The site header is scoped light for this page (.page-club, further down) and
   is flipped back to dark there for the same reason.
   ========================================================================== */
.club-hero-split {
  padding-bottom: calc(5rem + var(--wave-h));
  background:
    /* Baked fractal-noise paper, blended soft-light. It carries only lightness,
       so the hue stays in the gradients below — which is why the same file
       serves the pale panels and the dark bands alike. */
    url("../images/art/paper-wash.png"),
    radial-gradient(ellipse 60% 70% at 12% 8%,   rgba(255, 255, 255, 0.34), transparent 70%),
    radial-gradient(ellipse 55% 60% at 92% 18%,  rgba(var(--c-blue), 0.26), transparent 70%),
    radial-gradient(ellipse 55% 45% at 85% 105%, rgba(var(--c-teal), 0.16), transparent 70%),
    linear-gradient(158deg, #D8CBDF 0%, var(--panel-lav) 54%, #C6B4CF 100%);
  background-size: cover, auto, auto, auto, auto;
  background-position: center, 0 0, 0 0, 0 0, 0 0;
  background-blend-mode: soft-light, normal, normal, normal, normal;
}

.club-hero-split .club-hero-copy h1 { color: var(--navy); }
.club-hero-split .club-hero-copy p.lead { color: var(--ink); }
.club-hero-split .club-hero-copy .script { color: var(--script-blue); }
.club-hero-split .club-hero-copy .small-print { color: rgba(64, 73, 78, 0.78); }
.club-hero-split .club-hero-copy .club-hero-note {
  color: var(--navy);
  font-weight: 700;
  max-width: 34rem;
  margin: 0 auto 1.9rem;
}

/* The lavender pill badge is gone — a lavender pill on a lavender band is
   invisible, and the home page's club eyebrow is plain letterspaced type with no
   capsule around it. Matching that also takes one more rounded box off the page. */
.club-hero-split .eyebrow {
  display: block;
  color: var(--teal-label);
  background: none;
  padding: 0;
  border-radius: 0;
  letter-spacing: 0.24em;
  margin-bottom: 1.2rem;
}

/* Solid teal CTA. It has been lavender-on-teal, then purple when the band went
   lavender, and is teal from 2026-08-05 — Lauren wants every club CTA teal. On
   the lavender band the pill reads at 2.3:1 against its own ground, which is
   under the 3:1 that non-text UI wants; the label carries it. */
.club-hero-split .btn-primary {
  background: var(--teal);
  color: #FFF;
  border-color: var(--teal);
}
.club-hero-split .btn-primary:hover {
  background: var(--teal-deep);
  border-color: var(--teal-deep);
}

/* Centered hero layout — art on top, copy centered below */
.club-hero-split .club-hero-grid {
  grid-template-columns: 1fr;
  justify-items: center;
  text-align: center;
  gap: 0;
  max-width: 720px;
  margin-inline: auto;
}
.club-hero-split .club-hero-figure {
  order: -1;
  width: min(540px, 90%);
  margin: 0 auto 1.2rem;
  background: radial-gradient(ellipse 36% 60% at 50% 50%, rgba(238, 248, 244, 0.45), rgba(238, 248, 244, 0.16) 45%, transparent 72%);
}
.club-hero-split .club-hero-copy p.lead { margin-inline: auto; }

/* The home hamburger was left on the global navy when the hero band was pale
   teal. On the brand-teal band it measures 2.3:1 and all but vanishes, so it
   joins the About page's light-chrome rule. Only the burger needs it — the home
   nav links and the mobile Weekly Song pill were already set for a teal ground. */
.page-home .nav-toggle-label span,
.page-home .nav-toggle-label span::before,
.page-home .nav-toggle-label span::after,
.page-spark .nav-toggle-label span,
.page-spark .nav-toggle-label span::before,
.page-spark .nav-toggle-label span::after { background-color: var(--cream); }

/* Light header over a photographic hero. About has always been in here; the
   1:1 page joined it on 2026-08-23 when its band went from a pale watercolour
   to Lauren's butterfly photograph. The two pages have the same problem — a
   bright sky under the nav — and take the same answer, which is why they share
   these rules rather than each carrying a copy. The page also swaps to
   `logo-white.webp` in its own markup, exactly as About does. */
.page-about-hero .main-nav a,
.page-oto .main-nav a { color: var(--cream); }
.page-about-hero .main-nav a:hover,
.page-oto .main-nav a:hover { color: var(--seafoam); }
.page-about-hero .nav-song,
.page-oto .nav-song { color: var(--cream) !important; border-color: rgba(248, 245, 239, 0.6); }
.page-about-hero .nav-song:hover,
.page-oto .nav-song:hover { background-color: rgba(248, 245, 239, 0.14); }
.page-about-hero .nav-toggle-label span,
.page-about-hero .nav-toggle-label span::before,
.page-about-hero .nav-toggle-label span::after,
.page-oto .nav-toggle-label span,
.page-oto .nav-toggle-label span::before,
.page-oto .nav-toggle-label span::after { background-color: var(--cream); }

/* DARK header over the club hero, 2026-08-05. The club page was in the rule
   above until its band went from deep teal to lavender — cream chrome on
   --panel-lav measures about 1.3:1 and the whole nav disappeared.

   The logo is the same file the other pages use, `logo-white.webp`, which is
   white artwork with transparency: `brightness(0)` alone would knock it to flat
   black, so the sepia/hue-rotate chain repaints it to the navy the nav sits in
   rather than to a colour the palette doesn't own. */
.page-club .main-nav a { color: var(--navy); }
.page-club .main-nav a:hover { color: var(--teal-deep); }
.page-club .nav-song { color: var(--navy) !important; border-color: rgba(33, 46, 57, 0.45); }

/* ---------- This Week's Jam on hover, 2026-08-17 ----------
   Lauren asked for lavender, then for light teal on the Self-Love Club page
   specifically. So: lavender everywhere, light teal on the club, and the two
   are written in that order because the club rule has to be able to win.

   Scoped to `.main-nav`, so this is the DESKTOP pill only — `.nav-song-mobile`
   is a child of the header's .wrap, not of the nav, and keeps the quiet
   `--teal-wash` hover from the base rule near the top of the file.

   Navy text in both cases, set with !important because the page-scoped colour
   rules above use !important too. It is doing real work on About, where the
   pill's resting text is cream: cream on lavender would be unreadable, and this
   flips it to navy for the duration of the hover. Contrast measured — navy on
   --lavender 7.37:1, navy on --seafoam higher again. */
.main-nav .nav-song:hover {
  background: var(--lavender);
  border-color: var(--lavender) !important;
  color: var(--navy) !important;
}

.page-club .main-nav .nav-song:hover {
  background: var(--seafoam);
  border-color: var(--seafoam) !important;
  color: var(--navy) !important;
}

.page-club .nav-toggle-label span,
.page-club .nav-toggle-label span::before,
.page-club .nav-toggle-label span::after { background-color: var(--navy); }
.page-club .logo-link img {
  filter: brightness(0) saturate(100%) invert(13%) sepia(18%) saturate(1180%) hue-rotate(169deg) brightness(96%) contrast(90%);
}

/* Raised 860 -> 1100 on 2026-08-10, then 1100 -> 1245 on 2026-08-23, both
   times to stay in step with the drawer itself. These are the open panel's own
   colours; left behind they would miss the band above the drawer's breakpoint,
   where .page-home's white links would sit on the light teal panel and the
   close X would vanish. This number and the drawer's must always match — see
   the long note at the drawer for how 1245 was measured. */
@media (max-width: 1245px) {
  /* .page-home was missing here, and the links were white-on-cream inside the
     open panel — the menu slid in looking empty. Its nav is white because the
     header sits on the hero band; below 860px the nav is no longer on the band
     at all, it is on the full-screen --cream panel, so it needs the same forest
     the other two pages take. Reported by Lauren 2026-08-06; not caused by the
     hero-teal change, just never visible before anyone opened it. */
  .page-club .main-nav a,
  .page-about-hero .main-nav a,
  .page-home .main-nav a,
  .page-spark .main-nav a,
  .page-oto .main-nav a {
    color: var(--forest);
  }

  .page-club .nav-toggle:checked ~ .nav-toggle-label span,
  .page-about-hero .nav-toggle:checked ~ .nav-toggle-label span,
  .page-oto .nav-toggle:checked ~ .nav-toggle-label span {
    background-color: transparent;
  }

  /* .page-home joins these now that its burger is cream: the open panel is
     --cream too, so the close X would be invisible against it. */
  .page-club .nav-toggle:checked ~ .nav-toggle-label span::before,
  .page-club .nav-toggle:checked ~ .nav-toggle-label span::after,
  .page-about-hero .nav-toggle:checked ~ .nav-toggle-label span::before,
  .page-about-hero .nav-toggle:checked ~ .nav-toggle-label span::after,
  .page-oto .nav-toggle:checked ~ .nav-toggle-label span::before,
  .page-oto .nav-toggle:checked ~ .nav-toggle-label span::after,
  .page-home .nav-toggle:checked ~ .nav-toggle-label span::before,
  .page-home .nav-toggle:checked ~ .nav-toggle-label span::after,
  .page-spark .nav-toggle:checked ~ .nav-toggle-label span::before,
  .page-spark .nav-toggle:checked ~ .nav-toggle-label span::after {
    background-color: var(--forest);
  }

  /* Hover state for the full-screen side nav, Lauren 2026-08-06: the links
     should "be lit up and stand out". A colour change alone is weak on a link
     this large, so each one lights a --seafoam pill and the label goes teal.

     Which teal: --teal (#3E8C8A) is the site's accent, but on the --cream panel
     it measures 3.7:1, and these links are 1.332rem regular — 21px, under the
     24px that would let them count as large text. --teal-deep clears it at
     5.5:1 on the cream and 5.0:1 on the lit pill, so it is the one that works
     on both halves of the state.

     The padding and radius sit on the resting link, not on :hover, so lighting
     one up doesn't shove the others around. Pill radius to match the buttons.

     :is() rather than one selector per page because the panel is --cream on
     every page, but the page-scoped colour rules above are (0,2,1) and a bare
     .main-nav a:hover would lose to them. `body` is in the list for the pages
     that carry no body class at all — contact, policies, the agreement. */
  .main-nav a {
    padding: 0.5rem 1.4rem;
    border-radius: 999px;
    transition: background-color 0.2s ease, color 0.2s ease;
  }

  :is(.page-home, .page-club, .page-about-hero, .page-spark, .page-oto, body) .main-nav a:hover,
  :is(.page-home, .page-club, .page-about-hero, .page-spark, .page-oto, body) .main-nav a:focus-visible {
    background-color: var(--seafoam);
    color: var(--teal-deep);
  }
}

/* The soft halo behind the hero illustration was a pale seafoam pool, set to lift
   the drawing off a DARK teal band. On lavender it does the opposite — it is
   lighter than its surroundings and reads as a smudge — so it goes white and
   quieter, which still separates the illustration without showing an edge. */
.club-hero-split .club-hero-figure {
  background: radial-gradient(ellipse 40% 62% at 50% 50%, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.18) 46%, transparent 74%);
}

/* ==========================================================================
   Self-Love Club — decoration
   ========================================================================== */

/* Layout helper, not decoration: .join-wrap shares the join card's exact left
   and width, so a corner piece measured from it is measured from the card and
   holds at every viewport, where a px offset from the section would not. */
.join-wrap { max-width: 720px; margin: 0 auto; position: relative; }
.join-wrap .join-card { max-width: none; width: 100%; }

/* ---------- Chalk send-off — the sprig that opens the band ----------
   TEAL on white paper since 2026-08-26, per the site rule: white leaves on the
   coloured surfaces, coloured leaves on the white. Lauren: "the leaves on the
   bottom left of the page should be teal" — this piece and the sage one beside
   "Be the First to Know" trade colourways, so read `.join-side-sage` with this.

   The swap is a DRAWING swap, not a filter: leaf-vine-sage and leaf-vine-teal
   are two different pictures (560x1004 and 560x811), so this sprig is now 23%
   shorter for the same width and everything measured below was re-measured.
   Size and opacity move to the teal values with it — 250/0.55, matching
   .feeling-foot-leaf, this page's other teal-on-white sprig — the way 230/0.5
   were the sage ones. Measured after, at 1280 and 1440: zero painted pixels on
   the FAQ card, on the intro line (nearest ink stops 139px left of it) and on
   the chalk scraps below, so the pocket problem the old note describes is
   comfortably solved rather than narrowly survived.

   Lauren, 2026-08-06: "match them to the sizes on the other pages", and match
   the opacity the other pages give leaves on white. Both are one number each:

   - `min(230px, 18%)` is exactly what About's sage segments carry —
     .twocol-top-leaf, .beyond-corner-sage and .beyond-foot-leaf are all 230 —
     so the three pages' sage now reads at one size.
   - 0.5 is the site's value for a coloured leaf on white paper: .vine-seg's
     base, .twocol-top-leaf, .beyond-corner-sage, .beyond-foot-leaf. Home's teal
     crossovers run a touch stronger at 0.55 and .thanks-leaf a touch weaker at
     0.45; 0.5 is the middle and the one the sage pieces use.

   What made this look fainter than its counterparts was never the opacity — it
   was the 135px it had to be to fit the pocket, which is why the size fix is
   the fix.

   `rotate(93deg) scaleX(-1)` — the mirror is written FIRST in source order so it
   applies first and the angle still reads in screen space. At 93deg the stem's
   foot maps to the LEFT and just above level, so the vine enters from the page
   margin the way the teal and sage always do, and its leaves fan right and dip
   toward the intro line. About's .beyond-foot-leaf makes the same entrance at
   84deg and lifts instead; this is the rhyme of it, not the copy.

   The lift to -242px is forced, not chosen. At 230 the drawing paints 398x237,
   and the pocket between the FAQ card's foot (y4337) and the giraffe scrap
   (y4491) is 154 — so it cannot sit inside the band any more. It rides UP
   instead, and that works only because this drawing's mass hangs low and to the
   right: everything that ends up above the card's foot is out at x<60, where
   the card has already ended and there is nothing but paper. Measured, it
   paints x-57..341, y4250..4487 — 8px clear of the giraffe below it, and its
   leaf tips stop 122px short of the intro line. */
.chalk-intro-leaf {
  /* 2.2%, which is very nearly the 2% this always had — and that is the honest
     record of two asks cancelling. Lauren asked for this moved RIGHT, then for
     every stem to run off the side of the page; at 328px the drawing is long
     enough that its stem tip reaches x-35 from here, so the leaves land 97px
     further right than they used to (ink x-35..420 against x-23..323) without
     the stalk ever coming onto the paper. The move right was bought with size,
     not with position. */
  left: 2.2%;
  /* -242 -> -332. The bigger drawing hangs 90px lower and the giraffe scrap does
     not move: at -242 it put 4380 painted pixels on the photograph. Swept at 30px
     steps against the scrap, the intro line and the FAQ card above — -332 is the
     first step that is clean on all three (ink y3951-4295, scrap top y4306). */
  top: -332px;
  /* 328/0.55 — the same size and opacity as .feeling-foot-leaf, and for the same
     reason: 278 x the 1.18 sage-to-teal factor. See that rule for the table. */
  width: min(328px, 26%);
  opacity: 0.55;
  transform: rotate(93deg) scaleX(-1);
}

/* ---------- The purple flight closing the chalk row ----------
   Lauren, 2026-08-06: "add a purple bfly in flight facing the right under the
   zebra and elephant photos."

   `flight-purple` is her own drawing — butterfly at the LEFT end with its dotted
   trail running away to the right, which reads as flying leftward, since a trail
   is the record of where the butterfly has been. So facing RIGHT is a scaleX
   mirror, and nothing else: the butterfly moves to the right-hand end and the
   trail follows it in from the left, passing under the zebra and arriving under
   the elephant.

   Then, Lauren: "move it higher, to the left a little and tilt it down
   slightly." All three at once, and moving LEFT is what buys the height — the
   ceiling here is not flat. Both scraps are tilted, so their lower edges are
   too: the elephant's runs from (646, 5520) down to (1135, 5540), and the
   zebra's from (142, 5522) UP to (631, 5509). Sitting under the elephant the
   piece had 78px; slid left under the zebra it has 96. That is the whole reason
   the same drawing can now be 24px higher and carry a tilt it could not before.

   6deg, applied as `rotate(6deg) scaleX(-1)`: the mirror is written second so it
   applies FIRST and the angle then reads in screen space. Clockwise drops the
   LEADING end — the butterfly, which the mirror has moved to the right — so the
   flight tips downward in the direction it is travelling. Written the other way
   round the sign would invert and it would lift instead.

   Then widened, 260 -> 320. That is not free: the piece is anchored by its
   BOTTOM, so growing it pushes its top up into the scraps, and at 320 the old
   `bottom: 26px` put 180 painted pixels on the zebra. Dropping to 12px pays for
   the extra length exactly — the top edge lands at y5525 against the 5526 it was
   at before, so the flight is 61px longer at the SAME height, and only its
   lower edge moves. That is the trade here whenever this piece is resized:
   length comes out of the footer gap, never out of the ceiling.

   Measured at this setting: painted x418-739, y5525-5601. Zero pixels on either
   scrap (tested against their real rotated corners, not their boxes, which
   overstate the elephant by 20px) and 17px clear of the footer's tear. It now
   reaches 93px past the gutter, so the trail arrives properly under the
   elephant instead of stopping at its corner.

   0.75 is the site's value for a dotted flight, and the reason it is not lower
   is worth keeping: a thin dashed line loses its colour to transparency far
   faster than a leafy sprig does. These get quiet by being SMALL, never by
   fading. (Home carried the same drawing at the same 0.75 as
   .pillars-flight-purple until 2026-08-06, when Lauren had that one removed —
   this is now the only place flight-purple appears.) */
.chalk-foot-flight {
  left: 32.8%;
  bottom: 12px;
  width: min(320px, 25%);
  opacity: 0.75;
  transform: rotate(6deg) scaleX(-1);
}

/* ---------- The sprig that changes colour at the CLUB HERO's tear ----------
   Lauren, 2026-08-06: "add a white leaf turning into sage from the left side of
   the hero section."

   White while it is on the lavender band, sage the moment it reaches the paper
   below. One drawing, two colourways, two copies at pixel-identical positions —
   and it MUST be one drawing: `leaf-vine-sage` and `leaf-vine-teal` are
   different shapes (aspect 1.792 against 1.448), so a pair built from one of
   each cannot be aligned at any offset. That was learned the hard way on the
   home page's club card.

   This is the WRAPPER construction, not the no-wrapper one the FAQ crossover
   further down uses. The difference is what the edge belongs to: a .torn-paper
   CARD paints over anything placed before it, so it hides the outer half by
   itself, but a full-bleed BAND's tear is a mask on the section above, which
   crops the upper half and does nothing at all for the lower one. So the sage
   half gets its own clip — and that clip is masked with --wave-bottom-inv, the
   exact complement of the hero's own tear curve, so the two halves meet on the
   torn edge with neither an overlap nor a gap. It used to be a plain overflow
   box starting --wave-h above the edge, which spilled sage onto the lavender;
   see the note on .club-tear-clip for why that was fine on the home page and
   wrong here.

   Both offsets derive from ONE shared value, so they cannot drift apart:
   white's element bottom sits at (hero bottom + drop); sage's is at
   clip_bottom - (clip_h - wave_h - drop), and clip_bottom is
   hero_bottom - wave_h + clip_h — the same point, by construction rather than
   by measurement. Both resolve their `left` against full-bleed boxes that share
   left and width, which is the condition that keeps a crossover together
   through a resize. */
.club-receive { position: relative; }

/* Lauren, 2026-08-06: "the one part of the leaves, the sage is in the purple
   instead of being white and you cant see."

   She is right, and it was a real construction fault rather than a placement
   one. This wrapper started life as a plain `overflow: hidden` box whose top sat
   --wave-h ABOVE the tear — the same trick .vine-crossover-clip uses on the home
   page, where the note says the two halves "overlap by up to --wave-h rather
   than risking a gap in the stem". That trade is sound THERE because the home
   crossover's lower colourway is teal and the band above it is teal, so the
   spill is invisible. Here the lower colourway is SAGE and the band above is
   LAVENDER, so every pixel of that overlap showed as green line art sitting on
   the purple, in the wave's peaks, where the white half was supposed to be.

   The proper fix is to crop the lower half along the SAME curve the band above
   is torn on, which means the exact complement of --wave-bottom. That could not
   be done before because the only inverted tile on hand was --wave-top, and it
   is a different generator seed — a different curve entirely, so masking one
   against the other leaves a mismatched band. --wave-bottom-inv is now generated
   from wave-bottom's own seed, closed downward, so the two tile exactly.

   The alignment is by construction, not by measurement. The hero's .torn-bottom
   puts its wave layer at `0 100%`, so the tear band is the hero's last --wave-h
   pixels; this clip's top is one --wave-h above .club-receive, whose top IS the
   hero's bottom, so the clip's first --wave-h pixels are the same band, and both
   tile --wave-tile from x0 of a full-bleed box. White is opaque above the curve
   and sage below it, with no overlap to show the wrong colour and no gap to
   break the stem. --wave-overlap is applied the same way .torn-top applies it,
   for the same reason: the tiles are fully opaque for their first 15/80 of
   height, so a 4px soft-edge inset lands inside that headroom at every size.

   `overflow: hidden` stays, but it is now only a bottom bound on the drawing —
   the top edge is the mask's job. */
.club-tear-clip {
  --club-clip-h: 280px;
  position: absolute;
  left: 0;
  right: 0;
  top: calc(-1 * var(--wave-h));
  height: var(--club-clip-h);
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
  -webkit-mask-image: var(--wave-bottom-inv), linear-gradient(#000, #000);
          mask-image: var(--wave-bottom-inv), linear-gradient(#000, #000);
  -webkit-mask-size: var(--wave-tile) var(--wave-h), 100% calc(100% - var(--wave-h) + var(--wave-overlap));
          mask-size: var(--wave-tile) var(--wave-h), 100% calc(100% - var(--wave-h) + var(--wave-overlap));
  -webkit-mask-position: 0 0, 0 100%;
          mask-position: 0 0, 0 100%;
  -webkit-mask-repeat: repeat-x, no-repeat;
          mask-repeat: repeat-x, no-repeat;
}

.club-tear-white,
.club-tear-sage {
  /* 180, up 30 from 210. Raising this moves BOTH halves together — it is the
     one shared value the crossover is built on — and it trades sage for white:
     less of the drawing below the tear, more of it on the lavender. */
  --club-hero-drop: 180px;
  /* RIGHT, not left — Lauren, 2026-08-06: "change sides." `right` rather than
     `left` is safe for a crossover only because both halves resolve against
     full-bleed boxes that share left AND width (the hero, and the clip which is
     left:0/right:0 in a full-bleed section), so the same value lands both in the
     same place. 4.1% puts the painted stem 20px past the right edge of the page,
     so the sprig reads as entering from the margin rather than starting in
     mid-air.

     Then 6.4% to move it left, which put the tip 9px INSIDE the page and
     exposed the stalk — then back to 4.7%, "the tiniest to the right just so the
     stem is hidden."

     20px was enough, and that is measurable rather than a guess: sampling this
     drawing's painted thickness column by column in from the tip, the bare
     stalk is only the first ~11px (4-19px thick), and at 12px in it jumps to
     150 where the leaves start. So the tip needs to sit about 13px past the page
     edge and no further — any more is leaf thrown away off-screen, which is the
     mistake .beyond-foot-leaf made on the About page for 94px. */
  right: 4.7%;
  width: min(220px, 17.2%);
  opacity: 0.5;
  /* -96deg, and the mirror is GONE rather than flipped. Changing sides is one
     sign change here, not a scaleX: the stem is at the drawing's foot, so at
     -96deg the foot maps to the RIGHT and just above level while the leaves fan
     left and dip across the tear — the exact mirror of the +96/scaleX(-1) it
     had on the left. Adding a scaleX on top would only curl the leaflets back
     the other way.

     The angle is also a size decision. Turned on its side this drawing's painted
     HEIGHT is its own element width, so every degree away from 90 costs height
     — and the budget below the tear is only 154px, from the hero's edge (y1222)
     to the top of the icon row (y1376). At 96deg and 220px it paints 415x260,
     which lands the foot of the sprig 28px clear of the icons. */
  transform: rotate(-96deg);
}

/* ---------- The small white butterfly beside the hero CTA ----------
   Lauren, 2026-08-06: "a white butterfly 2 open wings, small size of it though
   on the right side of join the waitlist button in the hero section."

   62px, against the 110 the same drawing takes on the About hero and the home
   page's corner — so "small" is measured against its own other appearances
   rather than against butterflies generally. It also has to stay small here
   because the CTA is the thing being looked at; decoration by a button guides
   the eye to it or it is in the way.

   -12deg leans it back TOWARD the button rather than away, for the same reason.
   The drawing is a symmetric open-winged one, so the angle alone gives it
   direction and no mirror is involved.

   `left: calc(50% + 154px)` rather than a percentage of the hero: this hero's
   copy is centred, so the button's right edge sits a fixed 127px from the
   midline at every width, and an offset measured from the centre keeps the
   butterfly the same distance off the button as the window changes. A % of the
   section would drift away from it.

   No knockout filter needed. The home page's `.hero .deco` rule repaints its
   decoration white because that band's art is teal line work; this is already a
   white drawing on the lavender, and .club-hero carries no such rule. */
/* Lauren 2026-08-06: "make the butterflies in the self love club hero less
   faint", and apply it on mobile too.

   Opacity alone was not the problem. These are WHITE line drawings on a pale
   lavender wash, so the ink is barely darker than nothing — going 0.85 -> 1 buys
   about 15% and the piece still dissolves. The shadow is what makes it read: it
   gives every white stroke an edge to sit against, which is the one thing a
   white-on-light drawing has none of.

   Kept deliberately small — 1.5px blur at 28% of a desaturated purple, so it
   defines the line rather than announcing itself as a drop shadow. The hero is
   watercolour and a visible cast shadow would look pasted on.

   Purple-grey rather than black: black goes muddy against lavender.

   THE MOBILE RULES INHERIT THIS. The <=700px blocks further down set only
   position and size for these two, never opacity or filter, so the phone hero
   picks the change up from here — verified at 390. Don't restate it there.

   .hero-wordmark-bfly carries a rotate(), and filter is applied to the drawn
   result before the transform positions it, so the shadow turns with the wing
   as it should. Nothing to sequence by hand.

   THESE STAY WHITE. A teal recolour was tried on 2026-08-06 and Lauren rejected
   it — "that looks muddled to me", "if it has to be dark teal id rather not".
   Worth recording why a light teal was never on the table: measured against the
   hero's lavender (~#CFC3DC), white is 1.68:1, and every pale teal the palette
   owns sits BELOW that — --panel-teal and --aqua land near 1.1-1.3:1, and even
   #4EB1AE only reaches 1.53. A light teal here is FAINTER than the white, not
   bolder, because "light" against a light ground is the whole problem. The only
   teals that beat white are dark enough to be the thing she turned down. So the
   size increase carries this on its own, and the colour stays.

   `bfly-tint-teal-*.webp` and `path-tint-teal.webp` were the tinted files; they
   are deleted. Don't regenerate them. */
.hero-cta-bfly {
  /* UNDER THE BUTTON since 2026-08-24 — "lets have it sit under keep me posted,
     tilted to the left but closer to the button". It used to sit out to the
     right of the button at calc(50% + 154px); this centres it on the same
     midline the button is centred on (painted centre lands within 1px of the
     button's). */
  left: calc(50% - 27px);
  /* ANCHORED FROM THE HERO'S BOTTOM, 2026-08-26, and that is a bug fix rather
     than a placement change. This was `top: 1022px` — measured from the hero's
     TOP — and the note that used to live here predicted its own failure: "every
     px the hero copy above it gets taller slides the button down and leaves this
     butterfly behind... anything that changes the size or leading of the eyebrow,
     H1 or script above will do this again, silently." It had already happened
     twice (1003 -> 1021 for the H1's x1.25, then 1021 -> 1029 for a x1.1), and it
     happened a third time the moment the hero's script line took a <br> and grew
     a line: the butterfly ended up 28px INSIDE the button. Lauren: "the white
     butterfly move it under the keep me posted button."

     Everything BELOW the button is fixed — the hero's padding-bottom and the tear
     — so the button's foot sits a constant 124px above the hero's bottom edge no
     matter how the copy above reflows. Measuring from the bottom makes this piece
     immune to the copy, which is the same reason the phone rule has always used
     `bottom`.

     60px puts the ink 5px under the button's foot and 3px above the tear's
     contour, in a band that is 71px tall — byte-for-byte the clearances the
     2026-08-24 placement was tuned to, now expressed against an edge that holds.
     THE VALUE IS ONE OF THREE THAT MOVE TOGETHER: change the width below and this
     has to be re-derived, because the drawing is centred in a band it barely
     fits. */
  top: auto;
  bottom: 60px;
  /* 84 -> 68 on 2026-08-24, and the size is FORCED by the new position rather
     than chosen. The band under the button is 72px — its foot at y1008, the
     hero's tear reaching up to y1079 — and at 84px this drawing paints 78px
     tall once tilted, so centred under the button it could not both clear the
     button and stay out of the tear. It overlapped one or the other at every
     `top` tried. 68px paints 63px tall, which fits the band with 5px under the
     button and 3px above the tear.

     The tear is a hard edge here, not a soft one: this butterfly is a CHILD of
     .club-hero, so the section's torn-bottom mask crops it, exactly as it crops
     .club-tear-white. Anything reaching past that contour is cut off. */
  width: 68px;
  opacity: 1;
  filter: drop-shadow(0 1px 1.5px rgba(74, 58, 94, 0.28));
  /* -12 -> -20deg, "tilted to the left" — negative is anticlockwise. This is a
     symmetric open-winged drawing, so the angle is the only thing giving it any
     direction. Past about -26 the painted height grows enough to reopen the band
     problem described above. */
  transform: rotate(-20deg);
}

/* ---------- The side-view butterfly beside "Self" ----------
   Lauren, 2026-08-06: "a small white butterfly side view next to self in self
   love club on hero."

   `bfly-white-side`, not `bfly-white-small`. Both are side views, but the small
   one is already on this page in the "Is This For You?" card, and the site rule
   is that a butterfly is never repeated — rotate the drawing, not just its size
   and angle.

   The drawing faces RIGHT, so sitting to the LEFT of the wordmark it looks
   toward the word. No mirror; that would turn it away.

   +10deg, not -10: Lauren asked for it "tilted down to the right". Positive is
   clockwise, and on a right-facing side view that drops the HEAD end — so it
   noses down toward the "S" instead of rising away from it, which is what the
   -10 it started at was doing.

   58px. Sized against the word rather than against the other butterflies: the
   H1's cap height is 74px here, and anything approaching that competes with the
   wordmark instead of accompanying it.

   `calc(50% - 288px)` measures from the midline because the hero copy is
   centred — "Self" begins a fixed 200px left of centre at every width, so a
   percentage of the section would drift off the word as the window changed.
   Same reason as .hero-cta-bfly. */
.club-tear-white { bottom: calc(-1 * var(--club-hero-drop)); }
.club-tear-sage  { bottom: calc(var(--club-clip-h) - var(--wave-h) - var(--club-hero-drop)); }

/* ---------- The painted butterfly beside "Inside the Self-Love Club" ----------
   Lauren, 2026-08-06: "a teal and purple butterfly, the side view, next to the
   text 'inside the self love club'" — "on the left side."

   Left is also the only side that was free: the hero's sage crossover now paints
   x923-1293 down to y1318, which is exactly the pocket to the heading's right.

   The drawing faces RIGHT, so sitting to the left of the heading it looks
   toward the words. -8deg lifts its leading end a little so it reads as rising
   toward them rather than sitting still. No mirror — that would turn it away.

   Full strength, no opacity. This is PAINTED art, not line work: the teal and
   purple washes are the piece, and fading them turns the drawing grey. Only the
   line-art pieces on this page are quietened. */
.receive-title-bfly {
  /* 27.4%. Went 24.6 -> 26.1 when the drawing shrank (shrinking pulls its right
     edge left with it, so the offset has to grow by the same amount or the gap
     to the heading opens up), then +10px and +6px right on Lauren's call. The
     trail moves with it — see .receive-title-path — because the two are joined
     at the wing seam and moving one alone would open a gap there.

     This is close to the end of the room: the painted wing now stops 9px short
     of "Inside the Self-Love Club". Much past this and it reads as touching the
     word rather than sitting beside it. */
  left: 27.4%;
  /* 3, up 10. This is the ceiling: the hero's tear bottoms out at y1222 and the
     painted butterfly now starts at y1227, so any higher and it begins crossing
     onto the lavender. */
  top: 3px;
  /* 95, down from 115. Still the largest butterfly on the page, which is right
     for the only painted one here — home's grammar puts painted teal/purple well
     above the sketch and line pieces. */
  width: 95px;
  transform: rotate(-8deg);
}

/* The trail it flew in on. Lauren: "a dotted loop line behind it on the left
   side ... to look like its trail."

   `path-dotted-loop` earns the placement rather than just filling space: the
   drawing rises from the lower left, runs right, and throws a single loop just
   BEFORE its right-hand end. So putting the butterfly at that end makes the loop
   read as the turn it has only just made, which is what a flight path is — the
   record of where the butterfly has been. Unrotated and unmirrored; the drawing
   already runs the right way.

   The pocket is the paper left of the butterfly, above the icon row: nothing
   sits between x60 and x342 until the first icon disc at y1371.

   0.75 is the site's dotted-trail value, and it does not go lower. A thin dashed
   line loses its colour to transparency far faster than a leafy sprig does —
   this teal reads as pale grey below about 0.6 — so restraint comes from size. */
.receive-title-path {
  /* 8.5%, so the trail's end laps the butterfly's left edge rather than stopping
     short of it — the rotation below shortens its horizontal reach. This value
     is TIED to .receive-title-bfly's left: the two are joined at the wing seam,
     so whenever one moves horizontally the other has to move with it by the same
     amount or the trail comes away from the wing. */
  left: 9%;
  /* 23. Lauren: "move the dotted line down a little more so it sits between the
     wings." That is a measurable target, not a feel: sampling the butterfly's
     painted alpha in a column 18px inside its left edge, the teal upper wing and
     the purple lower one close to a 1px seam at y1299. This lands the trail's
     front end at y1299 on the nose. */
  top: 23px;
  width: 240px;
  opacity: 0.75;
  /* Lauren: "tilt the front of the line down and the back of it up and left."
     POSITIVE is clockwise, and on a piece running left to right that raises the
     TAIL and drops the leading end — the opposite of the instinct that a
     positive angle tips things down to the right. The rotation is about the
     element's centre, so one value does both ends at once.

     22deg, and it takes that much because the DRAWING already rises: measured
     end to end it climbs about 18deg left to right on its own. So 8deg only
     flattened it, 18 levelled it, and 22 is the first value where the front
     genuinely sits BELOW the back — 10px below, here.

     The ceiling caps how much further it can go. Tilting a wide flat drawing
     costs height fast (50px painted at 22deg against 91 level, once the rise is
     cancelled), and the risen tail must stay under y1222 where the hero's tear
     bottoms out — above that line this would be teal art lying on the lavender,
     against the rule that coloured art belongs on the white paper and only white
     art goes on the colour. */
  transform: rotate(22deg);
}

/* ---------- Teal under "Is This For You?" ----------
   Lauren, 2026-08-06: "teal leaves on the left side under 'is this for you'
   stem on the left side."

   Teal on white paper, per the site rule, and entering from the page margin the
   way the coloured vines always do.

   `rotate(76deg) scaleX(-1)` — the mirror is written second so it applies FIRST
   and the angle still reads in screen space. At 76deg the stem's foot maps to
   the LEFT and below level, so the leaves fan right and lift away from it. That
   is a different tilt from both of this page's other sprigs: .chalk-intro-leaf
   sits at 93deg and dips, and About's .beyond-foot-leaf at 84. Same entrance,
   three different attitudes.

   Anchored off the section's BOTTOM (`calc(100% - ...)`) rather than its top, so
   it stays pinned under the card's tear however the list above it reflows.

   The pocket is not the 146px band between the card's foot (y2434) and the
   quote (y2580) — this drawing paints 331px tall once it is turned, so it would
   never fit there. It hangs THROUGH that band and down the left margin of the
   quote section instead, which is free: the quote is centred and its lines start
   at x407, so everything left of that is clear paper all the way to y2744. */
.feeling-foot-leaf,
.feeling-foot-white {
  /* -3%, RESOLVED AGAINST .wrap NOW, not the section — this piece moved into the
     wrap on 2026-08-26 so that the white half inside the card could take the same
     rule. -3% of 1080 is x68 at 1280 and the ink starts at x-36, which buries the
     bare stalk (roughly the first 33px of the drawing at this size) off the page
     edge. Lauren, that day: "make the stems coming from the side of the page for
     all the leaves, no matter which side they are on."

     THIS IS NOT A RETREAT FROM "move them to the right a little", which she asked
     for in the same pass. The leaves reach x491 now against x323 before, because
     the drawing GREW: growing pushes the leafy end right and the stem tip left at
     the same time, which is the only way to satisfy both asks at once on a rigid
     drawing. Same trade the phone rule makes at 200px.

     MEASURED FROM THE PAGE EDGE, NOT FROM THE CARD, which is what the calc is
     for. -3% of the wrap was right at 1280 and wrong at 1440: the card centres
     and its margins grow, so the same percentage put the stem tip at x44 — ON the
     paper, the thing the rule above forbids. `calc(50% - 50vw + 68px)` resolves to
     a fixed page x68 in any box that is centred (50% of the box plus its own left
     edge is the page's midline), so the stem overhangs by the same 35px at every
     desktop width, and the white half inside the card takes the identical value
     and stays in register. */
  left: calc(50% - 50vw + 68px);
  /* calc(100% - 321px), and 100% is now the CARD'S height rather than the
     section's — the move into .wrap re-based this number without changing where
     the piece sits. The old value was 270 off the section's bottom; the card's
     foot is a fixed 72px above that, so 270 became 342, and 321 is the 21px of
     extra lift the bigger drawing needed.

     THE VALUE IS A SWEEP, NOT A GUESS. Lifting is bounded on both sides here and
     the window is narrow: too low and the ink runs past the quote section's wave
     onto the PHOTOGRAPH below (coloured line art on a picture, which the site
     never does); too high and it runs behind the bulleted list. Measured at 20px
     steps, as painted alpha against the text's own client rects and the wave:

       lift  ink        on copy   past the wave   on the mint
       120   2107-2351    0%          1%             37%
       140   2087-2331    0%          0%             59%   <- this
       160   2067-2311    2%          0%             77%
       180   2047-2291    6%          0%             88%

     140 is the only step that is clean on both sides, and it happens to split the
     drawing near half and half across the tear, which is what a crossover wants.
     The stem's thin end is what rides highest, and it stays left of x130 where
     the copy starts at x144 — that is why 140 can sit as high as it does. */
  top: calc(100% - 321px);
  /* 328px = the sage sprig's 278 x 1.18. Lauren: "those sage leaves are bigger
     then the rest on the page ... the teal ones need to be bigger now to match."
     The 1.18 is the two-family rule measured on the assets themselves — see the
     leaf-scale table on the 1:1 page's `.oto-hero` vine — leaf-vine-sage is drawn
     about 18% heavier than leaf-vine-teal, so equal width between the families is
     NOT equal leaf size, and matching by element width is only valid within one
     drawing. */
  width: min(328px, 31%);
  opacity: 0.55;
  transform: rotate(76deg) scaleX(-1);
}

/* Phone-only — see the rule in the <=700px block for why this placement cannot
   exist at desktop widths. Off by default so it never appears in the six-across
   layout. */
.reflections-blue-bfly,
.reflections-blue-path { display: none; }

/* Phone-only sage crossover at the JOIN card's bottom tear — replaces the teal
   .join-side-* pair at <=700px. Off by default so desktop keeps the teal one
   Lauren signed off on. */
.join-foot-sage,
.join-foot-white,
.join-foot-white-faq { display: none; }

/* The wrapper that lets the join-foot sprig cross onto the FAQ card. Inert on
   desktop, where that crossover is the teal `.join-side-*` pair instead. */
.join-foot-box { display: none; }

/* Phone-only for now. Unlike the other .deco pieces gated this way, this one
   has no layout reason to be — a butterfly centred above a centred line works
   identically at 1280. It is off on desktop only because that page is signed
   off; deleting this rule turns it on everywhere. */
.chalk-intro-bfly { display: none; }

/* ---------- The sprig that changes colour at the FAQ card's top edge ----------
   Lauren, 2026-08-06: "teal leaves on the right side of ready to join section.
   have them sit just above before you begin, or maybe even slightly overlapping.
   the stem should be slightly hidden on the right. when it overlaps switch from
   teal to white."

   The site's crossover: ONE drawing, two colourways, two copies at
   pixel-identical positions, each showing only on its own side of a torn edge.
   Teal while it is on the paper below "Ready to Join", white the moment it laps
   onto the blue.

   No clip wrapper, the same construction as About's .beyond-corner-* : the card
   is .torn-paper so it is position:relative with z-index auto, and the teal half
   is a positioned sibling placed BEFORE it, so the two paint in DOM order and
   the CARD ITSELF hides the teal wherever the blue is. The white half is a
   child, so the card's mask crops it to the blue. The colour therefore changes
   along the real torn contour, not along a straight line.

   This page gets that for free in a way the About page did not: .club-faq .wrap
   and .faq-card are the SAME box — 60 / 3645 / 1160x688, measured — so the two
   halves share left, width AND top with nothing to convert between them. That
   is the condition a crossover has to meet to survive a resize; a fixed px
   offset on one half is a latent bug, never a value.

   The two must stay identical copies or the effect breaks, so right / top /
   width / transform / opacity are set ONCE on the shared selector. Opacity
   counts as alignment — letting one half inherit a different value makes the
   drawing visibly change density as it crosses the edge, which is exactly how
   the home page's club pair was found to be broken.

   Stem hidden on the right is one rotation, no mirror: the stem is at the
   drawing's foot and the leaves fan up off it, so a negative angle past -90
   swings the foot out to the right and the leaves back to the left and down —
   which is also what makes the leafy end, not the bare stalk, the part that
   dips onto the blue and changes colour. */
/* ---------- The white butterfly leading into "Before You Begin" ----------
   Lauren, 2026-08-06: "a small white butterfly facing the right ... to the left
   of it, diagonal from the B in begin. like its directing the viewer."

   A SIDE view, and that is the whole point of the choice: it is the only white
   drawing on the site with a facing, so it can point at something. The
   open-winged whites are symmetric and would just sit there. It is also the one
   white butterfly not already used on this page — the footer carries
   bfly-white-open.

   White line art on the pale blue card has almost no contrast to spend, so it
   gets none taken away: 0.9, and it is kept quiet by being SMALL instead. Same
   rule as the dotted trails.

   A child of .faq-head, which is static, so it resolves against .faq-card — the
   card is the .torn-paper element and therefore position:relative. That is what
   keeps it beside the heading rather than beside the section.

   The heading's glyphs run x504-776 and the "B" of "Begin" sits at x688-706.
   This lands the butterfly up and to the LEFT of that letter with its nose
   tilted down toward it, so the implied line from drawing to word is the
   diagonal Lauren described. 15deg clockwise on a right-facing side view drops
   the head and lifts the tail; no mirror, which would turn it away from the
   heading entirely. */
.faq-lead-bfly {
  /* 31% -> 20% on 2026-08-24, "move the white butterfly to the left slightly so
     its off the text".

     IT DRIFTED RATHER THAN MOVED. This is a percentage of .faq-card, and that
     card was condensed from the full 1160px wrap to 720px in the same pass — so
     31% went from 360px to 223px and walked the drawing straight onto "You
     Might", which had itself pulled inward with the card. Measured after: the
     butterfly painted x500-582 against heading text starting at x534, i.e.
     overlapping. Any future change to the card's width moves this piece and the
     trail below it; both are anchored to the card, not to the page. */
  left: 20%;
  top: 20px;
  width: 78px;
  opacity: 0.9;
  transform: rotate(15deg);
}

/* The trail it flew in on. Lauren: "a white dotted line behind that butterfly so
   it travels to the left and down behind it."

   `path-white` runs with its plain end at the upper LEFT and its loop at the
   lower right, so unmirrored it would leave the butterfly travelling the wrong
   way. scaleX(-1) swaps those: the plain end lands upper-right, tucked under the
   butterfly, and the trail sweeps down and away to the left, finishing in the
   loop. Written after the rotate in source order so the mirror applies FIRST and
   the angle still reads in screen space.

   Then, Lauren: "make the dotted line a little bigger. its kinda hard to see.
   also move it to the left more and down, so it is at the bottom of the
   butterfly." 250 -> 310, left 80px, down 37px.

   Down is the constrained one, and the constraint is the first FAQ row: the
   trail descends as it runs left, so lowering it walks the loop at its far end
   into that row's icon disc and question. Swept every combination — at
   top: 84px the loop puts 145 painted pixels on the first question, at 82 it is
   59, and 78 is the last clean step.

   Then, Lauren: "move it to the left more so it is not touching the butterfly."
   So they are deliberately NOT joined. The trail's near end ran 23px under the
   wing; at 2.6% it stops at x400 against the butterfly's painted edge at x416,
   a 16px gap. Worth writing down because the instinct on a butterfly-and-trail
   pair is to tuck them together, and here the brief is the opposite.

   Full opacity, and deliberately. A thin dashed line loses its colour to
   transparency far faster than a leafy sprig does, and this is white hairline
   art on a pale blue card — there is no contrast to spend. Size is the only
   lever it has, which is why "hard to see" is answered with 310px. */
.faq-lead-path {
  /* 2.6% -> 1%, and 310px -> 215px, same cause as the butterfly above: the card
     went 1160 -> 720 and this piece is measured against it.

     THE WIDTH HAD TO COME WITH THE MOVE, which is why this is not just the "move
     it to the left a little" that was asked for. At 310px on a 720 card the trail
     spans 43% of it, against the 27% it spanned on the old card — the drawing
     did not change but its proportion did. Moving it left alone ran its far end
     off the card's torn edge before it cleared the copy: at the old width the
     best available still left only 13px of clearance and hung 8px past the edge.
     215px restores roughly the original proportion and clears the copy by 35px.

     Measured after: trail paints x288-501, heading text starts x534, first
     question at x387 sits below it. */
  left: 1%;
  top: 78px;
  width: 215px;
  opacity: 1;
  transform: rotate(0deg) scaleX(-1);
}

/* ---------- The sage sprig beside "Be the First to Know" ---------- 2026-08-26
   SAGE, NOT TEAL, AND THAT MEANS A DIFFERENT DRAWING. Lauren, in the same breath
   as the move below: "actually these should be sage and the leaves on the bottom
   left of the page should be teal" — the two pieces trade colourways with
   .chalk-intro-leaf. The site has no sage version of leaf-vine-teal and no teal
   version of leaf-vine-sage; they are two drawings, 560x811 and 560x1004, so a
   colour swap swaps the artwork and every measured value below had to be taken
   again. The sage drawing is 23% longer for the same width, which is why `top`
   moved a second time even though the target — the join card's middle — did not.

   Opacity goes 0.55 -> 0.5 with it: 0.55 is the site's value for a TEAL leaf on
   white (.feeling-foot-leaf, home's crossovers) and 0.5 is its value for a SAGE
   one (.club-tear-sage, About's segments). The number belongs to the colour, not
   to the position, so it travels with the drawing. */
.join-side-sage,
.join-side-white {
  /* ---- HORIZONTAL: MEASURED FROM THE PAGE'S CENTRE, so the two halves stay in
     register across two different boxes. This was `right: -6%` while both halves
     lived in the FAQ section, where .wrap and .faq-card were the same box. They
     are not any more (the card narrowed to 720 while .wrap stayed at 1160) and
     the white half now lives in the JOIN card, which is a third box again — but
     every one of them is CENTRED, so `50%` lands on the page's midline in all of
     them and one value serves both halves at every width.

     +401px. It was +371 — the value that reproduced the old `right: -6%` to the
     pixel — and Lauren, 2026-08-26: "the sage leaves next to be the first to
     know, move them to the right alittle." 30px, which trades a little of the
     leafy end that laps the teal card for a little more reach into the margin.
     What is hidden off the right of the page is the bare stalk, which is the
     part this drawing can afford to lose. */
  left: calc(50% + 401px);
  /* ---- WIDTH IN PX, and that is forced by the same two-box problem: `24%` was
     278 in .wrap and would be 173 in the join card, so a percentage cannot hold
     a crossover together here. 280 is home's crossover size
     (.vine-believe-cross-teal) and what this piece already rendered at. */
  width: 280px;
  /* 0.5, the site's value for a SAGE leaf on white paper — see the colour note
     at the top of this rule. Stated on the shared selector so neither half can
     inherit something different. */
  opacity: 0.5;
  /* -100deg -> -85deg. Lauren, 2026-08-07: "tilt the stem end to the right just
     a little so its coming from the side of the page more."

     The stem is the drawing's TOP-RIGHT tip once rotated, and clockwise is the
     direction that swings it right and down — measured by sampling painted
     alpha, since the bounding box's rightmost point is a mid-height leaf, not
     the stem, and tuning against the box moves the wrong end. -85 lands the stem
     on the page's right edge instead of stopping short of it and pointing up
     into the margin, which is what "coming from the side" means here. Swept: -95
     leaves a 22px gap (not enough to read as a change), -80 and past put 1%+ of
     the drawing off-page and start losing the tip rather than landing it. */
  transform: rotate(-85deg);
}

/* ---- VERTICAL: the two halves sit in different sections, so they cannot share
   one `top` — but they can share one ANCHOR, and both of these numbers are the
   join card's own geometry.

   The sage half resolves against `.club-faq .wrap`, whose top edge is the FAQ
   card's top: -662px puts its ink centroid on the join card's middle (the
   measurement is in the note below). The white half resolves against the JOIN
   card, so the same line is `100% + 48px - 662px` — 100% is the join card's
   height and 48px is the gap between the two sections, which is padding on both
   sides and therefore fixed. Nothing here depends on either card's height, which
   is what makes it hold as the copy reflows.

   HISTORY, because two of these numbers still constrain the piece:
   - It was a crossover over the FAQ card's TOP tear until 2026-08-26, at -276px.
     There is a floor on lifting that version: around -355px the sprig clears the
     tear altogether and the crossover stops existing.
   - -310 -> -276 on 2026-08-07 was not a reposition; it paid for the -100deg ->
     -85deg flattening, which swings the leafy end up and collapsed the dip onto
     the card from 51px to 17px.

   Then, Lauren, 2026-08-26: "move them up higher so they hit in the middle of
   that section", and the anchor stopped being the FAQ card's tear.

   MEASURED AGAINST THE INK, not the box. This drawing's alpha-weighted centroid
   sits well below its bounding box's centre — the stem is a thin tail that drags
   the box down without carrying any weight — so centring the BOX would have left
   the leaf mass low. -662 puts the centroid on the join card's centre to the
   pixel at 1280. (-603 was the same target measured on the teal drawing, before
   the colour swap made it a different one.) */
.join-side-sage  { top: -662px; }

.join-side-white {
  top: calc(100% - 614px);
  /* 0.5 -> 0.75, AND ONLY ON THIS HALF. Lauren asked twice for the leaves to turn
     white where they hit the teal; they already did, at the shared 0.5, and the
     answer to the second ask is that 0.5 is a value tuned for line art on WHITE
     PAPER. This copy sits on the darkest surface on the site — the join card's
     deep teal — where a 50% white stroke drops most of its contrast into the
     card's own wash. The sage half keeps 0.5 because it is still on paper.

     Worth knowing before anyone "fixes" the mismatch: the two halves of every
     other crossover on this page share one opacity, and this pair deliberately
     does not. */
  opacity: 0.75;
}



/* ==========================================================================
   Self-Love Club — PHONE placements for the decoration
   ==========================================================================
   Every piece above was designed at 1280 and none of it survives the stack
   untouched. Two mechanical failures, both from [[mobile]] and both already
   measured on this page at 390:

   1. `width: min(Xpx, Y%)` COLLAPSES. The percentage resolves against the
      containing block, so on a phone `min(220px, 17.2%)` is 67px. Five pieces
      here had quietly become 67-97px specks: .club-tear-*, .feeling-foot-leaf,
      .join-side-*, .chalk-intro-leaf, .chalk-foot-flight. Each needs an
      explicit phone width, and it wants to be proportionally LARGER than
      desktop, not smaller — a sprig scaled down with the layout stops reading
      as a drawing at all.

   2. `calc(50% ± Npx)` GOES OFF THE PAGE. Four pieces on this page are anchored
      to the midline because the copy they sit beside is centred, and at 1280
      that is right. At 390 the midline is 195, so `calc(50% + 275px)` is x470
      on a 390px page — the piece is not misplaced, it is GONE. .quote-you-path,
      .quote-you-bfly, .hero-cta-bfly and .hero-wordmark-bfly were all in this
      state. A mobile rule that fixes size but not the horizontal leaves the
      piece invisible and looks like nothing is wrong; the same bug hid About's
      .hero-white-bfly for a whole session.

   What changes on a phone is WHERE THE ROOM IS, not just the sizes. At 1280 the
   copy is a column with clear margins either side, so a piece can sit beside the
   writing. At 390 the copy runs full width and the only pockets are the
   horizontal bands BETWEEN blocks. */
@media (max-width: 700px) {

  /* ---------- The white open-wing butterfly, under "Cancel anytime." ----------
     Lauren, 2026-08-06: "move the white open wing butterfly so it sits center
     under cancel anytime."

     On desktop this sits beside the Join button, at `calc(50% + 154px)` — the
     button's right edge is a fixed 127px off the midline there, so measuring
     from the centre keeps the butterfly the same distance off it at every width.
     At 390 that same offset is x349 with a 70px painted drawing, so 25px of it
     hung off the right edge of the page.

     There is no room beside the button on a phone: the button is 253px wide in a
     390px page, leaving 68px of margin against a drawing that paints 70. So the
     piece moves to the band BELOW the copy, which is the biggest clear pocket in
     the phone hero — "Cancel anytime." ends at y993 and the hero's tear troughs
     begin at y1077, giving 84px of empty full-width paper.

     Centred, and centred properly: this drawing fills its own frame (painted
     bbox 1-298 of 300 across, so its painted centre is its element centre to
     within half a pixel), which means centring the BOX centres the painting.
     `calc(50% - 31px)` is half the 62px width. Measured, it paints x160-230 —
     centre 195, exactly the midline — and it holds at every phone width because
     it is derived from the midline rather than from an edge.

     ANCHORED FROM THE HERO'S BOTTOM, not its top, and that is not a stylistic
     choice — `top: 1010px` was tried first and it put 14 painted pixels on
     "Cancel anytime." at 320. The hero grows as the copy wraps: it is 1107 tall
     at 390 and 1127 at 320, so anything measured from y0 slides up into the text
     as the phone narrows. Measured from the BOTTOM the same copy is stable,
     because the hero's bottom padding is fixed — "Cancel anytime." ends exactly
     114px above the hero's bottom edge at 320 AND at 390.

     So `bottom: 52px` holds the whole arrangement at every width. Working it
     through: the element is 45px tall, so its top sits (heroBottom - 97) and the
     painted top is 6px above that again — which lands a constant 11px under
     "Cancel anytime." and leaves the painted bottom a constant 16px clear of the
     tear. That clearance is the real constraint, not the text: .club-hero
     carries `torn-bottom`, which is a MASK on the section, so anything crossing
     into the last --wave-h is silently cut in half rather than overlapping.

     `top: auto` is required, not tidying — the desktop rule above sets
     `top: 1003px`, and with both set the top would win and the bottom would do
     nothing. Size stays at 62px; the tilt stays at -12deg, which now leans it
     back toward the button above it instead of beside it. */
  .hero-cta-bfly {
    /* -31 was half of the old 62px width — this value exists to CENTRE the
       piece, so it has to track the width. At 84px it becomes -42, or the
       butterfly sits 11px right of the midline under a centred button. */
    left: calc(50% - 42px);
    top: auto;
    /* 52 -> 38, i.e. 14px DOWN. Lauren, 2026-08-07: "the white butterfly under
       cancel anytime in the hero, move down just a bit so it isn't covering
       text." It was: 59 painted pixels sat on "Cancel anytime.", whose glyph run
       ends at y993 while the wing started at 987.

       This is the same debt the desktop rule paid twice today — the piece grew
       62 -> 84px, and a drawing that gets bigger around a FIXED bottom edge
       grows upward into whatever is above it. The `left` beside it was already
       re-derived for the new width; the vertical was not, and this is it.

       38 gives 8px of clearance. Swept: 42 clears by 4 and 46 still puts 4px on
       the text, so 38 is the first value with real air rather than a hairline.
       Room below is not the constraint — even here the wing stops 34px short of
       the hero's torn bottom edge, and going to 30 would still clear it. */
    bottom: 38px;
  }

  /* ---------- "Inside the Self-Love Club" — the painted pair comes OFF ----------
     Lauren, 2026-08-06: "hide the teal and purple butterfly and the dotted lines
     image."

     A by-name removal, the same kind she made on About for `origin-matters-bfly`
     + `origin-matters-path` — NOT a return to the old blanket hide-below-700px
     rule. Everything else on this page keeps a phone placement.

     The two go together or neither does: their `left` values are TIED, because
     they meet at the wing seam at y1299 in the drawing, so hiding the butterfly
     alone would leave a dotted trail arriving at nothing.

     Worth recording why the pocket was gone anyway. At 1280 the trail lives in
     clear paper left of the heading, x60-342, with nothing under it until the
     icon row. At 390 the heading wraps to the full width of the page and the
     icon grid is two columns instead of seven, so that lane does not exist —
     measured here the 240px trail painted x26-284 and the 95px butterfly x99-210,
     i.e. the two were overlapping the heading and each other in a band 258px
     wide on a 390px page. There was no version of this pair that fit. */
  .receive-title-bfly,
  .receive-title-path { display: none; }

  /* ---------- The colour-changing sprig at the hero's tear ----------
     Re-cut for the phone, not just resized. Three things were wrong at 390:

     - `width: min(220px, 17.2%)` resolved to 67px, so the drawing painted 127x79
       instead of 415x260 — a speck.
     - Because the painted height collapsed with it, the whole drawing ended up
       BELOW the tear (y1188-1267 against a tear at y1107). The crossover had
       stopped existing: it was sage line art floating in white paper, with the
       white half rendering invisibly on top of it.
     - `right: 4.7%` is 18px at 390 against 60px at 1280, so even the horizontal
       had quietly changed meaning.

     160px, against the desktop 220. That is BIGGER in every sense that matters
     on a phone — 41% of the page width against 17% at 1280 — and it has to be:
     this drawing's painted box is 1.887x its width by 1.182x its width once it
     is turned to -96deg, so width is the only lever on how far it reaches across
     the tear. At 160 it paints 268x174.

     THE ROOM IS ON THE OTHER SIDE HERE, and that is the real phone decision.
     At 1280 the pocket is below the tear — 154px of clear paper before the icon
     row — so the desktop split is 80px above and 180 below, i.e. mostly sage. At
     390 the icon grid is two columns and "Inside the Self-Love Club" wraps under
     the tear at y1178, leaving only 71px of paper; meanwhile the lavender above
     is wide open, because the copy is centred and ends at x248. So the split
     INVERTS: `--club-hero-drop: 120px` puts 116px of the drawing on the lavender
     and 58px on the paper. Mostly white now, where desktop is mostly sage.

     Measured at this setting: painted x136-404, y991-1165. Zero painted pixels
     on the heading below, on "Cancel anytime.", on the hero paragraph, or on
     .hero-cta-bfly — which matters, because that butterfly moved to the middle
     of this same band and the sprig's leaf mass now reaches to x136, well past
     it. The two clear only because this drawing's mass hangs LOW and LEFT while
     its upper-left corner is empty; the bounding boxes overlap by 70px and the
     paint does not.

     `right: 41px` — PX, not the desktop's percentage, and derived rather than
     picked. The drawing is a fixed px width, so a % offset drifts against it:
     at `right: 10%` the tip sits 22px past the page edge at 320 and 16px INSIDE
     it at 699, which exposes the bare stalk at the wide end. The painted right
     edge is `pageW - right - W/2 + 1.887W/2`, so for W=160 it is
     `pageW - right + 54`, and 41 puts it a constant 13px past the edge at EVERY
     width. 13 is the number because this drawing's bare stalk is only the first
     ~11px in from the tip at desktop scale; any more overhang is leaf thrown
     away off-screen. Re-derive this constant if the width changes. */
  .club-tear-white,
  .club-tear-sage {
    --club-hero-drop: 120px;
    right: 41px;
    width: 160px;
  }

  /* ---------- Blue sketch butterfly under "Weekly Reflections" ----------
     Lauren, 2026-08-06: "lets remove that one we added under weekly reflections"
     / "and instead add a blue sketch bfly." So the teal sprig that briefly lived
     here is gone, markup and CSS both, and this takes its pocket.

     A phone-only piece, and it has to be: at 1280 .receive7 runs six across and
     Weekly Reflections is the FIFTH of them, out on the right. It only becomes a
     bottom-left cell once the grid stacks to two columns, which is the only
     layout in which this description picks out a place at all. Same class of
     piece as home's .pillars-teal-bfly.

     `bfly-blue-side` — Lauren: "its the side version." It is used on the home
     page (.pillars-blue-bfly, .spark-corner-bfly) and on About
     (.twocol-tips-bfly), but nowhere on THIS page, so the no-repeat-per-page
     rule still holds. It also brings a colour the club page did not have;
     everything else here is teal, sage, lavender or white.

     The pocket is the 147px band between the last line of the Weekly Reflections
     copy (y2229) and the top of the photograph (y2376), genuinely empty across
     the full width. A butterfly asks far less of it than the sprig that briefly
     sat here: no room off the page for a stem, so it sits comfortably centred
     where the sprig had to be squeezed.

     Lauren, 2026-08-06: "move it over to the right more and make it a little
     smaller." It started centred on the Weekly Reflections column (painted
     centre x100 against the column's x99); it now sits at x152, in that column's
     right-hand portion rather than its middle. The column spans x12-185, so it
     still reads as belonging to that copy rather than floating mid-page — and
     the page centre is x195, so it has not crossed into the right column's
     territory either.

     The move and the shrink are related, not independent: this piece is
     positioned by its LEFT edge, so shrinking it alone would have pulled the
     drawing left and partly undone the move. `left` went 56 -> 112 while the
     width went 84 -> 76, which is a 52px shift of the painted centre.

     Then, Lauren: "move the blue sketch butterfly to the right a little", then
     "to the right more", then "now it feels a little too much to the right" —
     112 to 124 to 160 and back to 142, painted centre 150 to 198 to 180. It has
     left the Weekly Reflections column it was originally centred on (x12-185)
     and reads against the block as a whole rather than that one cell, but stops
     short of the page midline (195) — at 198 it read as centred on the page,
     which is a different and more formal thing than sitting off to one side.

     THE TRAIL DOES NOT MOVE WITH IT. I moved both the first two times, on the
     reasoning that the pair was one gesture — Lauren's brief for the trail had
     been that it "looks like its hanging down behind it", and moving the
     butterfly alone pulls the dots out from under its wing. She corrected that:
     "not the dotted line, just the butterfly was supposed to move." So
     .reflections-blue-path is back at its own swept position and the two are
     deliberately APART, the butterfly out near the midline with the trail still
     falling away at the left.

     So these are NOT tied values, and that is a decision rather than an
     oversight — do not "fix" the gap by dragging the trail after the butterfly.
     It is the same call she made on .faq-lead-bfly and .faq-lead-path further
     down the page, where the butterfly and its trail are deliberately not
     touching.

     Both offsets are derived from the PAINTED box rather than the element box,
     because this drawing does not sit centred in its own frame — centring the
     element would miss by several pixels.

     Vertically it is still centred in the band, and both clearances hold across
     widths: `top` is measured from .club-feeling and the photo's offset inside
     that section is fixed padding, while the copy above sits a fixed section gap
     higher.

     The drawing faces RIGHT and carries no mirror, so from the left column it
     looks inward across the page rather than off the edge of it. 0.75 is the
     site's value for this particular drawing at all three of its other
     appearances, and it is lower than the 0.85 the club page gives
     .quote-you-bfly because this one is finer line work.

     -22deg, up from -8. Lauren: "tilt the blue butterfly up and to the right."
     NEGATIVE is the direction that does that here, and the reason is the
     drawing's facing rather than any general rule: rotation is about the
     element's centre, so counter-clockwise lifts whichever end is on the RIGHT —
     and on this right-facing side view that end is the head. A positive angle
     would have dropped the nose and raised the tail instead.

     76px, which sits with this drawing's other phone appearance rather than
     against butterflies generally — home's .pillars-blue-bfly is 74px inside its
     own <=700px rule. At 76 it paints 70x80, so the band swallows it easily.

     Measured: painted x117-187, y2259-2339. Painted centre x152, 30px under the
     copy and 37px above the photograph, with zero painted pixels on any text or
     on the picture. */
  .reflections-blue-bfly {
    display: block;
    left: 142px;
    top: -50px;
    width: 76px;
    opacity: 0.75;
    transform: rotate(-12deg);
  }

  /* The trail it climbed in on. Lauren, 2026-08-06: "add a non loop dotted line
     behind the blue butterfly. have it so it looks like its hanging down behind
     it to the left."

     Read off its alpha, `path-dotted-noloop` runs from a shallow dip at the
     BOTTOM-LEFT and climbs steeply to the TOP-RIGHT. So the butterfly goes at
     its top end and the dots fall away below and to the left on their own.

     Then, Lauren: "mirror flip that line horizontally" — so the curve's shape is
     reversed, the dip now reading into the fall rather than out of it. Written
     `rotate() scaleX()`, in that order, so the mirror applies FIRST and the
     angle still reads in screen space.

     THE MIRROR FORCED THE ANGLE FROM -34 TO -74, and this is the trap worth
     remembering. Flipping horizontally reverses the drawing's OWN slope: it
     climbed left-to-right, and mirrored it falls left-to-right instead. The
     rotation that had been adding to that climb now cancels it, so
     `rotate(-34deg) scaleX(-1)` came out at -13deg — very nearly a flat line,
     with the hang gone entirely. The drawing's natural rise is worth about
     40deg, so the mirror costs roughly twice that to undo. Measured end to end,
     -74 with the mirror runs at exactly -53deg, which is the angle the
     unmirrored -34 ran at. **Re-derive this if the mirror is ever removed** —
     the two values are not independent.

     Negative is counter-clockwise, which lifts the right end and drops the left.
     Worth stating because it is the opposite of the instinct that a positive
     angle tips things down to the right.

     Then, Lauren: "move down and left just a bit" — 12px each way, from
     left 2 / top 34. That tightens nothing: the trail's top end lands 7px from
     the wing tip against 4px before, so it is still tucked under it.

     Tucked BEHIND the butterfly, which is a source-order job, not a z-index one:
     the trail is written first in the markup so the butterfly paints over the
     end of it. Measured, the trail's top end is at (114, 2319) against the
     butterfly's lower-left wing tip at (119, 2314) — 7px apart, i.e. the dots
     disappear under the wing rather than stopping short of it. That is the
     opposite of .faq-lead-bfly further down this page, where Lauren asked for a
     deliberate 17px gap; do not "tidy" either one into the other.

     Painted x15-115, y2318-2448, with zero painted pixels on any text. It does
     cross the .feeling-photo's BOX by a few pixels at the top-left, and that is
     fine and was checked by eye rather than by the box: that photo is shaped by
     a blob mask, so its rectangle overstates it badly and the corner in question
     is transparent. The box is not the picture — see the note about not trusting
     a rasterised mask.

     0.75 is the site's value for a dotted trail everywhere, and it does not go
     lower: a thin dashed line loses its colour to transparency far faster than a
     leafy sprig does. Restraint comes from size.

     NOTE: this is the SECOND use of path-dotted-noloop on this page —
     .quote-you-path further down carries the same drawing. That one is currently
     off-screen on phones and still needs its placement; if both end up visible
     and it reads as a repeat, this is the pair to change. */
  .reflections-blue-path {
    display: block;
    /* Its own value, INDEPENDENT of the butterfly — Lauren, 2026-08-06: "not the
       dotted line, just the butterfly was supposed to move." This is where the
       trail was swept to; it stayed put while the butterfly went right. */
    left: -10px;
    top: 46px;
    width: 155px;
    opacity: 0.75;
    transform: rotate(-74deg) scaleX(-1);
  }

  /* ---------- The teal sprig under the card, resized to match ----------
     Lauren, 2026-08-06, on the new sprig above: "match the size of the existing
     one."

     Matched UPWARD, and that is worth stating because it is the opposite of what
     the words say on their face. "The existing one" was not rendering at a size
     anyone chose: `width: min(250px, 20%)` resolves to 78px at 390, so it was
     painting 124x56 against the new sprig's 226x128 — less than half, and one of
     the five silent min() collapses on this page. Shrinking the new piece to
     match a bug would have made both wrong. Both are 150px now, so they read as
     the same drawing entering from the same margin twice.

     Growing it by nearly 2x is a re-placement, not a resize. At 78px it tucked
     under the card's tear and hung down the quote's left margin — at 150 it
     paints 240x110 and there is no version of that which fits beside the
     bulleted list, whose lines start at x85.

     So it moves to the band BELOW the card, which is the same shape of pocket
     the new sprig uses: 146px of clear paper between the card's foot (y3516) and
     the first line of the pull-quote (y3662). It keeps its desktop character —
     hanging from under the card, stem off the left — and loses only the part
     that depended on a wide left margin the phone does not have.

     `top: calc(100% - 141px)` stays anchored to the SECTION's bottom, as the
     desktop rule does, which is what makes the clearances hold across widths:
     the card's foot sits a fixed 72px above the section's bottom edge, and the
     quote's first line a fixed 74px below it, both of them padding.

     125 -> 141 -> 212, and 150 -> 200. Lauren asked for the same move twice, a
     day apart: "those teal leaves above 'you dont have to fit into a mold' move
     them up a little" (2026-08-06), then "move the teal leaves up a little that
     are above the you dont have to fit section. also make them bigger to match
     the other leaves on the page" (2026-08-26).

     THE TWO ASKS ARE ONE MOVE. This sprig is squeezed between two things that
     paint over it — `.feeling-card` above (it is earlier in the DOM than .wrap,
     so the card wins) and `.club-quote`'s torn top below. Growing it alone pushes
     its foot under the photo band; at 200px on the old 141 anchor only 33% of the
     painted drawing would still show. Every extra pixel of width has to be paid
     for with lift, which is why 141 -> 212 is 71px rather than "a little".

     200px, WHICH IS A MATCH RATHER THAN A SIZE. The page's other phone leaves are
     both from the SAGE drawing — `.club-tear-*` at 160 and `.join-foot-*` at 186 —
     and leaf-vine-sage is about 18% heavier in stroke than the leaf-vine-teal
     this piece uses, so equal width between the two families is not equal leaf
     size. Matching the 160 pair wants ~189 here and matching the 186 pair wants
     ~219; 200 sits between them, which is right for a piece that sits between
     them on the page. Same two-family rule as the 1:1 page's leaf-scale table.

     MEASURED BY WHAT IS VISIBLE, not by the box, because most of this drawing is
     behind something. Sampling painted alpha against the card's own mask and the
     quote's wave: 92% of the ink shows at 320, 390 AND 430, with about 60px behind
     the card and 50 under the photo at each. The old placement showed 79%.

     Its painted top sits ABOVE the card's box bottom and still puts almost nothing
     on the card — not a contradiction, and worth knowing before anyone "corrects"
     it. `.feeling-card` is .torn-paper, so its real edge undulates well above the
     box across most of its width; at this sprig's x-range the paper has already
     ended. The box is not the card.

     `left: 27px` in px rather than the desktop's 3%, so the overhang past the page
     edge is the same at every width. THAT OVERHANG GREW WITH THE DRAWING — it was
     20px at 150 and is about 35px at 200, since the stem runs off proportionally.
     Still the bare stalk, so it is the right part to lose. */
  /* RE-BASED, NOT RE-PLACED, 2026-08-26: the img moved from the section into
     .wrap so the desktop crossover could exist, and both of these numbers are the
     same position expressed against the new box. The wrap's inset is 20px and its
     bottom edge sits a fixed 72px above the section's, at 390 and at 320 alike —
     so 27 - 20 = 7 and 212 - 72 = 140. The phone placement is unchanged to the
     pixel; if the wrap's padding ever changes, these two follow it.

     The white half is desktop-only. On a phone this sprig sits BELOW the card
     with about 60px of it hidden behind the tear rather than crossing it, so
     there is nothing for a white copy to do. */
  /* THE CROSSOVER COMES TO THE PHONE, 2026-08-26. Lauren: "the leaves right
     about 'you dont have to fit into a mold' can you move them up just a bit,
     and if they overlap anything make sure that part turns to white." Both
     halves now take this one rule, exactly as they do on a desktop — the white
     copy is no longer hidden here.

     It works for the same reason it works up there: `.club-feeling .wrap` and
     `.feeling-card` have identical border boxes at every width (the wrap carries
     no horizontal padding and the card is its last child), so `left` and
     `calc(100% - ...)` land on the same pixel in both containing blocks. The
     card's mask then crops the white half to the mint and the teal below the
     tear is the same drawing continuing.

     140 -> 190. Two things had to be true at once, and they pull the same way.

     The FLOOR is the photograph, not the card: the quote band's wave starts at
     y3314 at 390 and the sprig was putting 676 painted pixels past it — coloured
     line art on a picture, which the site never does. 170 is the first value
     that clears it.

     The CEILING is that the white half needs something to do. Measured against
     the card:

       top   ink          past the wave   on the card box
       140   3186-3334        676px             3%
       170   3156-3304          0              13%
       190   3136-3284          0              39%   <- this
       210   3116-3264          0              68%

     170 satisfies "up just a bit" and nothing else: 13% of the box, and the
     card's torn edge runs well ABOVE its box bottom across this sprig's x-range,
     so almost none of that 13% is actually on the mint — the crossover existed
     and could not be seen. 190 is still a nudge (the drawing is 148px tall) and
     puts a real leaf group over the tear. Everything up to 230 stays off the
     photograph if it ever wants to go further. */
  .feeling-foot-leaf,
  .feeling-foot-white {
    left: 7px;
    top: calc(100% - 190px);
    width: 200px;
  }

  /* ---------- "Before You Begin" — the white pair comes OFF ----------
     Lauren, 2026-08-06: "hide the white butterlfy and white dotted line in
     before you begin section."

     By name again, like the .receive-title-* pair above — not a return to the
     old blanket hide-below-700px rule. (It used to cite .feeling-white-bfly as
     the other precedent; that piece was removed from the page outright on
     2026-08-24.)

     The two go together. They were deliberately NOT touching on desktop (a 17px
     gap Lauren asked for specifically), but they are still one gesture — a
     butterfly and the trail it flew in on — so keeping the trail without the
     butterfly would leave a dotted line arriving at nothing, the same reason
     .receive-title-path went with its butterfly.

     Also worth knowing: .faq-lead-path is `opacity: 1` and 310px wide, which is
     79% of a 390px page. It is white hairline art on a pale blue card and was
     sized that large on desktop precisely because it had no contrast to spend;
     at phone width that makes it the single widest mark on the section. */
  .faq-lead-bfly,
  .faq-lead-path { display: none; }

  /* ---------- The sage sprig above the chalk send-off comes OFF ----------
     Lauren, 2026-08-06: "oh yes hide that please."

     It was the last piece on this page still running its desktop rule, and it
     was actively wrong rather than merely small: `min(230px, 18%)` collapsed it
     to 70px, and its desktop `top: -242px` — which on a wide screen lifts it
     into clear paper beside the FAQ card — lands it ON the card at 390. Measured,
     it painted x-16..102, y5284-5354 with 113 painted pixels on the pale blue,
     against the site rule that coloured art belongs on the white paper and only
     white art goes on a colour.

     Hiding it is the right answer rather than a retreat, and that is measurable:
     the only pocket left is the 88px band between the FAQ card's foot (y5427)
     and the chalk intro line (y5515), and .chalk-intro-bfly now sits in the
     middle of it at x147-243. Swept 36 combinations of width, top and left
     across that band — every one either put paint on the card, crossed the intro
     line, or ran into the butterfly. This drawing paints 1.09x its own width
     tall once turned, so anything big enough to read as a vine is taller than
     the band.

     The alternative, if it should come back, is to rebuild it as a crossover at
     the FAQ card's BOTTOM tear — sage on the paper, white where it laps onto the
     blue — exactly like .join-foot-* at the join card. That would let it be full
     size. It is a build, not a value change. */
  .chalk-intro-leaf { display: none; }

  
  /* ---------- Teal crossover out, SAGE crossover in at the JOIN CARD'S FOOT --
     Lauren, 2026-08-06: "hide the teal leaves in ready to join. and instead add
     sage leaves on that side but lower down ... if they overlap sections make
     sure to switch colors." Then: "move those leaves up so they are coming from
     the bottom of the dark teal section."

     That second note moved it to a DIFFERENT EDGE, and the edge is what decides
     everything else. It first went on the FAQ card's TOP tear, sage above on the
     paper turning white as it dipped onto the blue. "The dark teal section" is
     the join card, so the piece now crosses that card's BOTTOM tear instead —
     and the colours invert with it: WHITE while it is on the teal, SAGE the
     moment it reaches the paper below. Same rule Lauren stated ("switch
     colors"), opposite order, because the colour is now above the edge rather
     than below it.

     PHONE ONLY. Desktop keeps the teal pair she signed off on, which is why
     .join-foot-* are `display: none` by default rather than the teal ones being
     deleted.

     ONE drawing, two colourways, two copies at pixel-identical positions.
     `leaf-vine-sage` and `leaf-vine-sage-white` are the same drawing; that is
     not optional, since `leaf-vine-teal` is a different shape (aspect 1.448
     against 1.792) and a pair built from one of each cannot be aligned at any
     offset.

     No clip wrapper, because this is a CARD edge and not a full-bleed band.
     `.join-card` carries its own `mask: torn-paper-club.svg`, so it crops its
     CHILDREN — that gives the white half its top-side crop for free — and it
     paints over anything before it in source order, which hides the sage half
     everywhere the teal is. The hero's `club-tear-*` needed a wrapper only
     because a full-bleed band's tear is a mask on the section ABOVE, which does
     nothing for the lower half.

     `.wrap`, `.join-wrap` and `.join-card` are all the SAME box here, so both
     halves take this identical rule and cannot drift apart — the same condition
     that made the FAQ crossover safe.

     150px, matching .feeling-foot-leaf — the size Lauren set when she asked for
     the page's leaves to agree. (The hero's sage crossover is 160; the two are
     within 6% and read as the same weight.)

     Then, Lauren: "move them lower so they overlap into the white space." At
     -60px only 8px of the drawing had cleared the tear, so it read as a white
     sprig on the teal with no crossover at all. `bottom: -140px` splits it
     almost evenly — 90px of white on the teal, 88px of sage on the paper — which
     is the point of the piece.

     -140 is also close to the floor. The clear white between the join card's
     foot (y4669) and the FAQ card's top (y4813) is 144px, and this drawing
     paints 178 tall, so pushing much further drops the leaf tips onto the FAQ
     card; at -140 it stops 56px short of it. Grow it rather than lower it if
     more sage is wanted.

     Then, Lauren: "lets move those to the left a little more" / "but keep the
     stem hidden." Those two pull directly against each other, and the trade is
     measurable rather than a matter of taste.

     THE BARE STALK IS 17px AT 150px WIDE, not the ~11 quoted elsewhere. That
     earlier figure came from the hero's crossover at 220px and does not transfer.
     Measured properly by sampling the ASSET row by row up from its foot: the
     painted width stays under 40 of 560 for the first **65 rows** and then jumps
     to 244 where the leaves start, so the bare stalk is 65 asset px — which at a
     150px render (scale 150/560) is 17.4 screen px. Do not measure this on the
     rotated element: turned -100deg, every page-column cuts across leaves at
     other heights and the profile is meaningless.

     At `right: 15px` the tip sat only 13px past the page edge, so ~4px of stalk
     was ALREADY showing. Moving left would have exposed more, and at 150px wide
     there is no left move at all that keeps the stem buried.

     So the piece GREW to make the move possible: at 186px the leaves reach 41px
     further left while the longer stem still runs off the page, 27px past the
     edge against the 21.6 that size now needs — a 5.4px margin. Growing is the
     only lever here, because the stem hides by overhanging the page and the
     overhang scales with the drawing.

     The cost is that it no longer matches .feeling-foot-leaf at 150, which was
     Lauren's earlier "same size as the other leaves on the page". Flagged.

     Note `right` resolves against the CARD (x16-374), not the page, so it is not
     the same number as .club-tear-*'s 41px even though both hide the same stalk.

     ANCHORED FROM THE BOTTOM, deliberately: the join card's height changes with
     the embedded form, and the whole piece is defined by its relationship to the
     card's FOOT. A `top` would have to know that height. */
  .join-side-sage,
  .join-side-white { display: none; }


  /* ---------- The third copy, 2026-08-26 ----------
     Lauren: "the sage leaves above you might be wondering, those need to overlap
     that section and turn white when they do."

     IT WAS ALREADY OVERLAPPING — the drawing's box reached 46px into the FAQ card
     at 390 — but nothing showed there. `.club-faq` is a later section, so it and
     its card paint over anything in `.club-join`; the sage copy simply disappeared
     under the blue. Overlapping and being VISIBLE on the other side are two
     different things, and only a copy that lives inside the far card can do the
     second.

     SO THIS IS NOW A THREE-WAY CROSSOVER: white on the join card's teal, sage on
     the paper between the two cards, white again on the FAQ card's blue. Same
     shape as `.oto-sprig` on the 1:1 page, and the same problem — three copies in
     three different containing blocks, which is exactly what drifts apart when you
     keep three sets of offsets in sync by hand.

     SO THE BOX IS REPRODUCED, NOT THE OFFSETS. `.join-foot-box` is a zero-height
     box inside the FAQ card whose bottom edge lands on the JOIN card's bottom edge
     — the edge all three copies are anchored to. All three then take the one rule
     below and cannot come apart.

     -48px IS MEASURED AND IT IS STABLE. The two cards are the same box (identical
     left and width at every width, checked), and the space between them is
     `.club-join`'s bottom padding plus `.club-faq`'s top padding — both fixed, not
     content-driven. Measured 48px at 320 AND 390. If either padding changes this
     number has to change with it; nothing else here does.

     Height: zero, so it supplies an origin and nothing else. Every offset on the
     sprig is in px for the same reason `.oto-sprig-box`'s are — a percentage would
     resolve against a height of nothing.

     ALL THREE LEGS VERIFIED BY SAMPLING, against the two cards' own masks rather
     than their boxes — the boxes overlap where nothing is painted, which is what
     hid the missing leg in the first place. Painted pixels per leg:

                        320        390        430
       white on teal    459        451        410
       sage on paper   2636       2684       2757
       white on blue    829        867        856

     The blue leg is the short one at ~29px of run, because the sprig only reaches
     that far past the join card's foot. If Lauren wants more of it on the FAQ card,
     LOWER the shared `bottom` rather than growing the drawing — growing it also
     lengthens the stem, and the stem is what hides off the page edge. */
  .join-foot-box {
    display: block;
    position: absolute;
    left: 0;
    right: 0;
    top: -48px;
    height: 0;
    pointer-events: none;
  }

  /* THE JOIN WRAP GOES BACK TO z-index 1 HERE, and it has to. The base rule
     raises it to 2 so the join CARD paints over `.join-side-sage`, which lives in
     the FAQ wrap — that is the desktop crossover, and it is display:none below
     this breakpoint. The phone crossover pulls the opposite way: `.join-foot-sage`
     lives in THIS wrap and has to pass UNDER the FAQ card so its white copy shows
     on the blue. Two crossovers, opposite directions, and the only thing that
     lets both be true is that each exists at one width and not the other.

     Lauren, 2026-08-26, on the phone view: "the sage leaves below that, when they
     overlap the blue section, make that white." They already had a white copy in
     the FAQ card; raising the wrap earlier the same day had buried it. */
  .club-join .wrap { z-index: 1; }

  .join-foot-sage,
  .join-foot-white,
  .join-foot-white-faq {
    display: block;
    right: 10px;
    bottom: -140px;
    top: auto;
    width: 186px;
    opacity: 0.55;
    transform: rotate(-100deg);
  }

  /* ---------- Painted butterfly above "A few reminders…" ----------
     Lauren, 2026-08-06: "add a teal and purple butterfly above a few reminders
     to carry with you. open wing version. have it sit in the center."

     Then, Lauren: "swap out with the side view verison, and make it so it is
     overlapping the blue section slightly above."

     `bfly-teal-purple`, the side view. It is the same drawing .receive-title-bfly
     carries, but that one is hidden on phones and this one is hidden on desktop,
     so the two never appear together and the no-repeat rule holds.

     THE SWAP FORCED A RESIZE. The side view is a much taller drawing than the
     open-wing one — 400x520 against 320x304 — so at the 100px the open version
     used it painted 126 tall instead of 90 and ran straight into "A few
     reminders to carry with you". 88px brings it back to 110 tall, which is the
     size that fits the pocket once the piece also has to lap upward.

     "Overlapping the blue slightly" is measured against the card's REAL torn
     edge, not its box. `.faq-card` is masked with torn-paper-a.svg, and
     rasterising that at the card's rendered size and sampling alpha per column
     puts the actual paper at y5418-5426 across this butterfly's x-range — an
     average of 5423, only 4px above the box bottom, because this card's bottom
     tear is shallow. So the box would have been a fair approximation here, which
     is not true of the blob-masked photographs elsewhere on the site; it was
     worth checking rather than assuming either way.

     Then, Lauren: "have it overlap the blue and turn slightly down to the
     right." So the lap went 34px -> **49px**, close to half the drawing, and the
     piece gained a +15deg turn.

     POSITIVE is what turns a RIGHT-FACING side view down to the right. Rotation
     is about the element's centre, so clockwise drops whichever end leads — and
     on this drawing that is the head. A negative angle would have lifted the
     nose and dropped the tail instead. Same reasoning as .faq-lead-bfly's +15
     and .hero-wordmark-bfly's +10; the opposite sign from .reflections-blue-bfly,
     which had to tilt UP to the right and so went negative.

     THE TURN MOVED THE CENTRE. This drawing is not symmetric about its frame, so
     rotating it walked the painted centre 7px left of the midline even though
     `left` had not changed. `calc(50% - 37px)` is the 44 that centres the
     element, less that 7 — derived from the painted box, not the element box,
     which is the only way to keep a rotated asymmetric piece centred.

     `z-index: 2` IS REQUIRED, and the reasoning that said otherwise was wrong.
     "The chalk band comes after .club-faq in the document, so it paints on top"
     is true only when document order is what decides, and here it is not:
     **`.club-faq .wrap` carries `z-index: 1`** and is therefore a stacking
     context sitting at level 1 of the root. `.chalk-band` is
     `position: relative; z-index: auto`, which does NOT create a stacking
     context, so this butterfly does not stack inside the band at all — it
     participates directly in the ROOT stacking context, at the `z-index: 0` that
     `.deco` gives every piece. 1 beats 0, so the FAQ card's wrapper painted over
     the butterfly and Lauren saw it disappear behind the blue.

     Raising the butterfly works precisely BECAUSE its ancestors create no
     stacking context; if `.chalk-band` had a z-index of its own, no value here
     could lift the piece past `.wrap` and the band would have to be raised
     instead. Verified by hit-testing the overlap after temporarily setting
     `pointer-events: auto` — `.deco` is `pointer-events: none`, so an ordinary
     elementFromPoint probe silently reports whatever is underneath and tells you
     nothing about paint order.

     Full strength, no opacity. This is PAINTED art: the teal and purple washes
     are the piece, and fading them turns the drawing grey. Only the line-art
     pieces on this page are quietened — the same call .receive-title-bfly makes.

     100px, against the 95 .receive-title-bfly takes on desktop — the painted
     butterflies are the largest on the page and this is the only one left
     visible on a phone.

     Centred from the MIDLINE (`calc(50% - 50px)`, half the width), not from a
     section edge, because the line it sits above is centred text and tracks the
     midline at every width. Measured, it paints x147-243 — centre exactly 195 on
     a 390px page.

     The pocket is the 90px of clear white between the FAQ card's foot (y5427)
     and "A few reminders to carry with you" (y5517). At this setting the drawing
     lands 12px under the card and 20px above the line.

     A NOTE ON MEASURING HERE, because it cost real time: the FAQ answers are in
     CLOSED `<details>`, and Chrome keeps layout boxes for hidden `<details>`
     content — `getClientRects()` returns geometry for text that paints nothing.
     A collision sweep that trusts those rects reports this whole band as
     occupied and rejects every placement in it. Any sweep over .faq-card must
     skip text inside `details:not([open])` (excepting the `<summary>`). */
  .chalk-intro-bfly {
    display: block;
    left: calc(50% - 37px);
    top: -126px;
    width: 88px;
    z-index: 2;
    transform: rotate(15deg);
  }

  /* ---------- The purple flight under the elephant, enlarged ----------
     Lauren, 2026-08-06: "make the purple bfly in flight larger under the
     elephant."

     It was not really a size choice before — `min(320px, 25%)` resolved to 97px
     at 390, so the piece had silently collapsed to under a third of its desktop
     length, the same failure as the four other min() pieces on this page.

     260px, which is 2.7x what it was rendering and still short of the desktop
     320. The ceiling is the elephant, not the page: this drawing paints only
     0.2x its width tall, so length is cheap and height is not — at 260 it paints
     260x60 and sits 23px below the elephant's base with 17px left above the
     chalk band's foot. The band's foot is the real floor, because .site-footer
     carries .torn-top and paints over anything the flight pushes into it.

     The elephant's base is honest here, unusually: that scrap is a full-bleed
     scan with no transparent margin, so its painted bottom (y7129) and its box
     bottom (y7130) agree to a pixel. Most of the photographs on this site are
     blob-masked and their boxes lie.

     `left: 66px` in px, and centred on the PAGE rather than kept at the desktop
     rule's 32.8%: at 1280 the flight starts under the zebra and arrives under
     the elephant, but the grid is a single column on a phone and there is only
     the elephant to sit under, so the piece centres on it instead. Painted
     x65-325, centre 195. */
  .chalk-foot-flight {
    left: 66px;
    width: 260px;
  }

  /* ---------- The quote pair, moved under the text ----------
     Lauren, 2026-08-06: "move the teal butterfly and the dotted line in the 'you
     dont have to fit into a mold' section so they both sit under the text in the
     white space in that section."

     Both were entirely OFF THE PAGE before this, which is the `calc(50% + Npx)`
     failure in its purest form. The quote is centred text, so at 1280 anchoring
     to the midline is exactly right — the butterfly sits beside "be you." and
     tracks it at every desktop width. At 390 the midline is 195, so
     `calc(50% + 275px)` resolves to x470 on a 390px page: the trail was not
     misplaced, it was gone, and so was most of the butterfly.

     THE POCKET IS BIGGER THAN THE SECTION. `.club-quote` ends at y3801, only
     74px below the last line of the quote — not enough for either piece. But it
     is `overflow: visible` and `.club-join` opens with 72px of padding before
     `.join-card` begins at y3873, so the real band of clear white is
     y3727-3873: **146px**, full width, the same size pocket as the one under
     "Weekly Reflections". Both pieces are children of .club-quote and simply
     hang past its edge into that padding.

     The pair keeps its desktop reading rather than being re-invented: the
     butterfly sits at the trail's LOW end and the dots climb away to the upper
     right, so the flight reads as having come down from that corner to settle
     under the words. `path-dotted-noloop` needs no rotation or mirror for that —
     the drawing already runs from a shallow dip at the bottom-left up to the
     top-right.

     BOTH ARE ANCHORED FROM THE SECTION'S BOTTOM, and that is the whole reason
     this holds. A `top` measured from .club-quote's top was tried first and put
     20 painted pixels on "You just have to be you." at 320 — because the quote
     wraps to THREE lines there instead of two, so the copy grows downward while
     a fixed `top` stays put. Measured from the bottom the same copy is stable:
     the last line sits 74px above the section's bottom edge at 390 and 75px at
     320, and .club-join's padding is a fixed 72px, so the 146px band is the same
     band at every width. Same fix as .hero-cta-bfly in the hero.

     Then, Lauren: "move them both to the right, and the dotted line tilt down
     and right. its ok for the full dotted line image to not be shown."

     +38deg, POSITIVE, and it has to clear the drawing's own slope before it does
     anything: `path-dotted-noloop` rises 21deg left-to-right on its own, so
     anything under +21 still reads as climbing. At +38 the trail runs at a
     measured +17deg — descending to the right, which is what was asked. Positive
     is clockwise, which drops the leading end and lifts the tail.

     The trail runs 20px PAST the right edge by permission, not by accident.
     `body` is `overflow-x: hidden`, so this costs no horizontal scrollbar —
     worth checking before ever letting a piece overhang, since decoration that
     widens the document is a real bug on a phone.

     Measured: butterfly paints x85-171, y3751-3825; trail x202-410, y3753-3819,
     starting 31px off the butterfly's right wing. 24px under the quote, 48px
     above the join card, zero painted pixels on any text or on the card.

     The trail is 205px, down from the desktop 240, and the butterfly stays at
     92px. The butterfly is the piece that must not shrink: it is the only
     teal-and-purple painted drawing left visible on this page now that
     .receive-title-bfly is hidden on phones.

     NOTE: `path-dotted-noloop` now appears TWICE on the phone — this and
     .reflections-blue-path up in "Is This For You?". They are far apart and in
     different colourways, but it is the same drawing; if it reads as a repeat,
     these two are the pair to separate. */
  }


/* ==========================================================================
   Home page Self-Love Club banner — dark to match the club hero
   ========================================================================== */
/* The band itself is light now — the teal lives in the card, not the stripe. */
.club-banner {
  background:
    radial-gradient(ellipse 26% 32% at 100% 8%, rgba(var(--c-lav), 0.34), transparent 70%),
    radial-gradient(ellipse 22% 28% at 0% 96%, rgba(var(--c-blue), 0.30), transparent 70%),
    var(--soft-white);
}

/* Scoped to .club-copy, not to the whole band: "A Note From Me" now shares this
   section, and a light-on-teal rule applied band-wide turned its heading cream
   on a white background. Only the teal card gets the reversed colours. */
/* These reversed colours belong to the dark teal club card, which now only
   exists on self-love-club.html. On the home page the club is a pale lavender
   panel, so scope them off .page-home or the copy renders white on lilac. */
body:not(.page-home) .club-copy h2,
body:not(.page-home) .club-copy p,
body:not(.page-home) .club-copy .club-features div { color: var(--cream); }

body:not(.page-home) .club-copy .eyebrow { color: var(--seafoam); }

body:not(.page-home) .club-copy h2 .heart { color: var(--lavender); }

body:not(.page-home) .club-copy .club-features .mark { color: var(--lavender); }

body:not(.page-home) .club-copy .btn-primary {
  background: var(--lavender);
  color: var(--forest);
  border-color: var(--lavender);
}
/* #c9b8d6 was --lavender with two channels nudged by one — no visible hover at
   all. Same hue (273) and saturation, lightness 78 -> 70. 5.6:1 on the forest
   label. */
.club-copy .btn-primary:hover {
  background: #B59BCA;
  border-color: #B59BCA;
}

/* ==========================================================================
   Sunday Spark — sunday-spark.html, added 2026-08-13
   Lauren asked for the sign-up to have its own page. The home page's
   #sunday-spark block is UNCHANGED and still live: her Instagram link
   lumilibra.com/#sunday-spark keeps working, and the inline sign-up on the
   home page keeps working. Only the nav item moved to point here.

   Nothing on this page crosses a torn edge, deliberately. A crossover needs a
   matched pair of halves whose offsets are re-derived together at every width
   (see the vine notes above) and this page has no pair — the two decorations
   here are single pieces that live entirely inside one section.
   ========================================================================== */

/* The band. Same recipe as .hero — brand-teal ramp, baked paper in soft-light,
   torn bottom — but NOT that class: .hero carries the home page's two-column
   grid, its 7.29rem wordmark and the brightness(0) invert(1) knockout on its
   decoration, none of which belong here. Copied rather than shared because the
   two will drift apart; if they ever need to move together, factor the
   background out into its own class and let both wear it. */
.spark-hero {
  position: relative;
  padding: 9rem 0 6.5rem;
  background:
    url("../images/art/paper-wash.png"),
    radial-gradient(ellipse 46% 52% at 12% 8%,  rgba(255, 255, 255, 0.34), transparent 66%),
    radial-gradient(ellipse 40% 44% at 88% 78%, rgba(255, 255, 255, 0.26), transparent 68%),
    radial-gradient(ellipse 36% 40% at 72% 6%,  rgba(26, 62, 61, 0.30), transparent 70%),
    radial-gradient(ellipse 34% 38% at 4% 88%,  rgba(26, 62, 61, 0.22), transparent 72%),
    linear-gradient(158deg,
      var(--hero-teal-deep) 0%,
      var(--hero-teal-mid) 46%,
      var(--hero-teal-light) 100%);
  background-size: cover, auto, auto, auto, auto, auto;
  background-position: center, 0 0, 0 0, 0 0, 0 0, 0 0;
  background-blend-mode: soft-light, normal, normal, normal, normal, normal;
  overflow: hidden;
}

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

/* One centred column, unlike the home hero's copy/photo split — there is no
   photo here and a lone column of copy pinned left reads as unfinished. The
   measure is capped so the script line breaks somewhere sensible instead of
   running the full 1160px wrap. */
.spark-hero-copy {
  max-width: 42rem;
  margin-inline: auto;
  text-align: center;
}

/* Inverted for the dark band, exactly as the home hero does it. The site's
   "display headings go NAVY" rule still holds everywhere on paper; navy on this
   ramp measures 3.0:1 and reads muddy. The h1 keeps the SITE scale rather than
   the hero's 7.29rem — that size belongs to the wordmark, and "Sunday Spark" is
   a page title. */
.spark-hero h1 { color: #FFF; margin-bottom: 0.8rem; }
/* The .heading-heart span was removed from this h1 on 2026-08-13 at Lauren's
   ask ("remove the heart in the hero"), and its colour override went with it.
   The heart is still live on the home page's own Sunday Spark heading — that
   one is untouched. */
.spark-hero .eyebrow { color: rgba(255, 255, 255, 0.92); letter-spacing: 0.22em; font-size: 0.999rem; }
.spark-hero .script { display: block; color: #FFF; margin-bottom: 2rem; }

/* The email field is already --panel-teal with the paper wash over it, which is
   the site's form treatment and sits correctly on this band. Only the row needs
   centring — .signup-form is left-aligned where it lives on the home page. */
.spark-hero .signup-form {
  justify-content: center;
  max-width: 30rem;
  margin-inline: auto;
}

/* White pill, navy label — the same inversion .hero .btn-primary makes, and for
   the same reason: --teal IS the ramp's light stop, so a --teal button would be
   painted in its own background. 9.7:1 on the navy label. */
.spark-hero .btn-primary {
  background-color: var(--white);
  color: var(--navy);
  border-color: transparent;
  border-radius: 999px;
  white-space: nowrap;
}
.spark-hero .btn-primary:hover { background-color: #E4EEEC; border-color: transparent; }

.spark-hero .ml-form-success-message { color: #FFF; }
.spark-hero .ml-form-success-message strong { color: #FFF; }

/* 0.78 rather than a lighter ink: white at full strength here competes with the
   script line directly above it, and this is the quietest thing in the band. */
.spark-small-print {
  margin-top: 1.1rem;
  font-size: var(--t-xs);
  color: rgba(255, 255, 255, 0.78);
}

/* The trail from the "I'd Love That" button up to the butterfly.

   ANCHORED TO THE BUTTERFLY, not to the button, and that is the deliberate
   choice: the button is CENTRED while the butterfly sits at `right: 5%`, so the
   distance between the two grows with the window — 50px of clear gap at 1000,
   far more at 1440. Only one end can be pinned. Pinning the butterfly end keeps
   the head tucked under her wing at every width, which is the join that would
   look broken if it drifted; the tail simply reaches further back toward the
   button on a wide screen, which reads as a longer flight rather than a fault.

   `rotate() scaleY()`, IN THAT ORDER. Transforms apply right to left, so this
   mirrors first and the rotation then reads in screen space. Written the other
   way round — scaleY(-1) rotate(-34deg), which is what went in first — the flip
   lands AFTER the rotation and turns a 34-degree climb into a 34-degree
   descent: the trail ran downhill away from the butterfly, its low end below
   her and its high end above the button, exactly backwards. The drawing
   DESCENDS left to right on its own (ink centre y12 -> y248 across the frame),
   so the mirror is what makes it climb.

   Desktop only. The butterfly is hidden below 700px, and a trail to a piece
   that is not there is just a line. */
.spark-hero-path {
  /* Steepened and shortened from 250px/-34deg: at the shallower angle the trail
     ran 14 painted pixels across the hero tagline, which has no background to
     hide behind. The BUTTON's overlap is fine and left in — it is an opaque
     white pill inside `.spark-hero .wrap` (z-index 1) and the deco sits at 0,
     so the tail disappears cleanly behind it, which is the "leads from the
     button" join. Text with no backing is the thing to clear.

     CENTRE-ANCHORED, like the button and (since 2026-08-13) the butterfly. It
     was `right: 9%` first and that broke the whole point of the piece: the
     button is centred while a right-anchored piece walks outward with the
     window, so the gap between button and trail went from 17px at 1000 to
     197px at 1440 and the trail stopped reading as leaving the button at all.
     All three now hang off the same 50%, so the flight path holds its shape at
     every width. */
  /* RESOLVED 2026-08-19, Lauren: "make the dotted line image larger in the hero
     and also moved to the left so it is sitting under the butterfly, looking
     like the butterfly's flight trail", then "flip it horizontally".

     BOTH ENDS ARE PINNED, which is what fixes the size and the angle: Lauren
     wants "a nice line going from the button to the butterfly", so the two ends
     have to land on two named things rather than merely point in the right
     direction.

     The top end is aimed at the butterfly's ABDOMEN TIP, her "under the butt of
     the butterfly", and that point is measured rather than eyeballed: sample the
     drawing's alpha, take the lowest painted row within 12px of the ink's
     horizontal centre (the body column, since the wings fall away either side),
     then push it through the element's own transform. At 1280 the tip is
     (1020,217) and the trail's head (1034,245) — 14px across, 28px below.

     The bottom end has to finish INSIDE the button, not run past it: the tail
     lands at (877,451), against a pill of 675-880 x 398-455, so the last dots
     slip behind its corner and nothing pokes out underneath. Before this pass
     the tail ran 45px below the pill and read as a line going somewhere else.
     `belowBtn == 0` is the condition worth re-checking if these numbers move.

     Only 12 combinations in the whole sweep satisfy both ends at once, which is
     why the width came DOWN to 250 from the 320 the previous pass used — the
     button-to-butterfly distance is what it is.

     THE MIRROR IS scaleX(-1) ALONE, and the scaleY(-1) this rule carried since
     it was written is GONE. That is the whole of "flip it horizontally", and it
     is worth writing down why the obvious reading was wrong: adding scaleX to
     the existing scaleY gives scaleX(-1) scaleY(-1), which is a 180-degree
     turn, not a mirror. Lauren looked at it and said "I think you flipped it
     vertically instead" — she was right.

     What the mirror actually decides is WHICH END CARRIES THE LOOP. This
     drawing is a long dotted S with a small curl near one end. Under scaleY it
     put the curl up against the butterfly; under scaleX the curl lands at the
     BUTTON end and the smooth run rises to her, which is both the way the trail
     reads as flight and the grammar every other trail on this site follows —
     see .faq-lead-path on About, which "sweeps down and away to the left,
     finishing in the loop".

     The angle had to be re-solved with the mirror in place rather than nudged:
     -42 -> -30.

     ALL FOUR VALUES WERE SWEPT TOGETHER against the painted alpha, not the
     boxes — 6397 combinations that clear every glyph, ranked by how close the
     smooth end lands to the butterfly and how far the run reaches back toward
     the button. The binding constraint is the tagline's first
     line, which ends at x967 and has no backing behind it: any trail running
     from the butterfly down to the button has to pass that line's last word, and
     only the steep ones pass to the RIGHT of it. This one clears all text by 6px
     at its tightest and still tucks its tail behind the button. Re-sweep rather
     than nudge if any of it moves. */
  width: 240px;
  /* +195px -> +210px on 2026-08-24, "move to the right a little". 15px, and the
     ceiling is the butterfly rather than the copy: moving right walks the trail
     AWAY from her tail, and the gap opens fast — 2.3px at +195, 15.3 at +210,
     29.4 at +225, 44.2 at +240. Past about +225 it stops reading as her trail
     and starts reading as a line that happens to be nearby. Copy clearance is
     not the binding constraint; it only improves as this moves right. */
  left: calc(50% + 210px);
  /* Top-anchored, to hold the BUTTERFLY end. Bottom-anchoring was tried first,
     because the pill sits a constant 148px above the hero's bottom edge and
     that tracks it for free — but the butterfly is `top: 8.5rem` and does not
     move, so as the hero shrinks a bottom-anchored trail rides up into her and
     across the tagline (47 painted samples on type at 900, head 45px ABOVE the
     abdomen). The two ends are anchored to opposite edges of a box whose height
     changes, so no single fixed-length trail spans both across the whole range.
     See the 1100px breakpoint below, which shortens it for the narrower half. */
  top: 18.5rem;
  /* scaleX(-1) -> scaleY(-1) on 2026-08-24: "flip it so the direction of the
     line matches better", after the butterfly's tilt went from -12deg to -20.

     BOTH MIRRORS KEEP THE TRAIL VERTICAL; they differ in which way it bows. The
     old scaleX version curled left immediately off her tail, against the
     direction she is now heading. scaleY leaves the tail heading down-RIGHT and
     only then sweeps away left, so the tight part of the curve is up beside her
     and the line falls away below — which is how a trail behind something flying
     actually reads.

     Do NOT reach for the unmirrored or doubly-mirrored versions to fix this. Both
     lay the drawing nearly FLAT (300x74 against this one's 140x274) and strand it
     43px and 72px from her tail respectively — measured on painted alpha. Only
     the two single mirrors put it on end. */
  transform: rotate(-30deg) scaleY(-1);
  /* 0.9, not 0.75. White dots on a teal band composite toward the band as they
     fade, and thin dashed ink loses its colour to transparency far faster than
     a leafy sprig does — the site rule is to keep a dotted line quiet by SIZE
     and spend nothing on opacity. At 200px it is already small. */
  opacity: 0.9;
}

/* White line art, so no knockout filter — see the note in the markup. Sits in
   the band's top-right, clear of the centred column. */
.spark-hero-bfly {
  width: min(150px, 16%);
  top: 8.5rem;
  /* Was `right: 5%`. Moved onto the centre line on 2026-08-13 so that the
     button, the trail and the butterfly all resolve against the same origin —
     see the note on .spark-hero-path. A right-anchored butterfly drifts away
     from a centred button as the window widens, and no fixed-length trail can
     span both. She sits nearer the copy on a wide screen than she used to and
     further from the margin; that is the trade Lauren chose. */
  left: calc(50% + 300px);
  opacity: 0.85;
  /* -12deg -> -20deg on 2026-08-24, "tilt the white butterfly in the hero to the
     left a little". Negative is anticlockwise, which is left — the drawing is a
     symmetric open-winged butterfly, so the tilt is the only thing giving it any
     direction at all.

     WATCH THE TRAIL, not the copy, when changing this. Rotating anticlockwise
     swings the lower wing DOWN toward .spark-hero-path, and the gap between the
     two closes fast: sampled on painted alpha it is 14.1px at -12, 4.9px at -18,
     and 0.2px at -22 — touching. Past -22 the trail runs into the wing rather
     than off the tail. -20 sits just inside that, ~2px clear, which reads as the
     trail leaving her rather than as a detached line.

     The copy is not the binding constraint here and there is no point tuning
     against it: clearance to the tagline and the form only falls from 68px to
     51px across that whole range. */
  transform: rotate(-20deg);
}

/* ---------- What lands in your inbox ---------- */

.spark-what {
  position: relative;
  padding: var(--section) 0 var(--section);
}

.spark-what .wrap { position: relative; z-index: 1; }

.spark-what-head {
  max-width: 40rem;
  margin: 0 auto var(--space-lg);
  text-align: center;
}

/* `text-wrap: balance` because the heading is 35 characters against a 40rem
   measure and breaks one word short: "Start Your Week With a Little / Spark"
   leaves the section's own subject orphaned on line two. Balanced, it splits
   near the middle instead. Browsers without it fall back to the ragged break,
   which is what was there anyway — nothing depends on this. */
.spark-what-head h2 { margin-bottom: 0.9rem; text-wrap: balance; }
.spark-lead { font-size: var(--t-md); line-height: 1.7; }

/* Two, not three — the third card ("An Invitation, Never a To-Do") was cut on
   2026-08-13: Lauren, "theres no invitation". It promised something the email
   does not contain. Both survivors restate what the home page's own Sunday
   Spark block already promises, so nothing here is invented.

   The ROW fills the full 1160px wrap, so this band lines up with every other
   section on the site. It was capped at 46rem first and Lauren read the result
   as too narrow on a wide screen — with only two cards that cap left 352px of
   bare paper either side at 1440, and the row sat visibly narrower than its
   neighbours.

   The cap moved onto the ITEM instead. Two cells across 1160px would otherwise
   put each caption on a ~560px measure, which reads as a banner rather than a
   card; 22rem holds each at ~352px, the width the three-up row had, centred in
   its own half. So the row is wide and the reading measure is not. */
.spark-items {
  position: relative;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: clamp(1.5rem, 3vw, 2.6rem);
  align-items: start;
}

.spark-items .item { max-width: 22rem; margin-inline: auto; }

/* Same construction as the club's .receive7 row — a painted patch, its caption
   under it, and a per-item tilt so the pair doesn't line up like a spec sheet.

   SIZES CUT 2026-08-26 — Lauren: "can we make the icons smaller on the sunday
   spark page, both dekstop and especially mobile." 150 -> 116 here, and 150 -> 96
   once the row stacks. The old note argued the patch could be BIGGER than the
   club's 132 because there are two across rather than six; what that reasoning
   missed is that the patch is not competing with its neighbours, it is competing
   with its own caption. At 150 it was 43% of a 352px card, and on a phone it was
   38% of the whole screen with nothing beside it to give it scale — which is why
   the phone needed the deeper cut of the two. */
.spark-items .item { text-align: center; margin-top: var(--lift, 0); }
.spark-items .item:nth-child(1) { --lift: 0rem;   --tilt: -4deg; }
.spark-items .item:nth-child(2) { --lift: 1.6rem; --tilt:  3deg; }

/* Only the patch tilts. Rotating the whole item would tip the caption with it,
   and slanted paragraphs stop being playful immediately. */
.spark-items .si-img {
  display: block;
  width: min(116px, 100%);
  aspect-ratio: 340 / 325;
  object-fit: contain;
  margin: 0 auto 1rem;
  transform: rotate(var(--tilt, 0deg));
  transform-origin: 50% 88%;
  transition: transform 0.35s ease;
}

/* Each title takes its own patch's colour, which is what tells you which title
   belongs to which drawing — the same rule the home pillars follow. These are
   the derived values, not the patch colours: at full strength the gold measures
   1.5:1. Sizes match .pillar h3 (1.393rem/600), which is large text, so the
   4.0:1 the --blob-* set clears is AA here. */
.spark-items h3 { margin-bottom: 0.7rem; font-weight: 600; font-size: 1.393rem; }
.spark-items .item:nth-child(1) h3 { color: var(--blob-gold); }
.spark-items .item:nth-child(2) h3 { color: var(--club-playlist); }

.spark-items p { font-size: var(--t-base); line-height: 1.7; }

/* Enters from the page's left margin, the way the teal sprigs do elsewhere, and
   sized to that family: every sprig cut from leaf-vine-teal.webp (560x811, so
   the declared width IS the apparent leaf size) runs 270-320px on this site.
   Rotated about its own centre, so the on-screen box is not the layout box —
   height collapses toward W and width opens to (811/560)W. Both offsets below
   are derived from that, not nudged; re-derive them together if the width
   changes. */
.spark-what-leaf {
  /* 260 -> 300, Lauren: "i think the leaves need to be bigger?" Every sprig cut
     from leaf-vine-teal.webp (560x811, so declared width IS apparent leaf size)
     sits in 270-320, and at 260 this was the runt of the set.

     IT WENT TO 320 FIRST AND THAT WAS TOO BIG — clean at 1280 and 1440, but 66
     painted pixels on the copy at 1024 and 17 at 880, at EVERY `left` worth
     having. The wrap is `min(1160px, 92%)`, so below ~1261 the copy's left edge
     is a percentage of the window and marches leftward as the window narrows;
     the sprig is fixed px and cannot retreat with it. 300 clears the whole
     range with one value.

     `left` and `top` are re-derived with the width, never left alone: the
     drawing is rotated about its centre, so growing it alone walks it. */
  width: 300px;
  /* Lauren, 2026-08-13: "move it up and to the right so it sits closer to the
     teal hero." 30px right, 20px up from -140/44. The ceiling on "up" is the
     torn edge: the hero's teal follows that curve down to roughly its box
     bottom, and a TEAL sprig on the teal band disappears — so the drawing is
     tucked to within a few px of the tear rather than lapped over it. If she
     wants it further up still, the piece has to change colourway to the white
     one, the way the crossovers do. */
  left: -170px;
  top: 32px;
  /* Was -140deg. Lauren, 2026-08-13: "rotate them left" — anticlockwise, so the
     angle goes further negative. One 25deg step. The rotation is about the
     element's CENTRE, so the drawing swings as well as turns: at -165 it sits
     13px further right in its box, 13px lower, and shows 164px of leaf on the
     page against 211 before. The angle lives here and here only; the narrow
     rules below move size and offsets, never the angle, so the sprig reads as
     the same drawing at every width. */
  transform: rotate(-165deg);
  opacity: 0.85;
}

/* ---------- The gap pieces: dotted trail + two-tone butterfly ----------

   Lauren, 2026-08-13: a dotted line and a "teal and purple side flying
   butterfly", the butterfly BETWEEN the icons and the trail behind it, "not
   touching text".

   Anchored to `left: 50%` rather than a measured px offset. The two cards are
   equal cells in a centred wrap, so the gap between them is centred on the row
   at EVERY width — a percentage here is not a guess, it is the geometry. The
   px offsets that would have to be re-derived at each breakpoint are exactly
   what walks a piece onto the copy when the layout moves.

   `translateX(-50%)` has to lead the transform list and the rotation follow it:
   transforms apply right to left, so this centres first and the angle then
   reads in screen space. Written the other way the rotation swings the piece
   off its own centring. */
.spark-gap-path,
.spark-gap-bfly { left: 50%; }

/* The trail TRAILS the butterfly — it is the flight path she has just flown,
   not a line drawn behind her. So it does not straddle her: it runs in from the
   left and its leading end tucks under her body.

   `translateX(calc(-100% - 41px))` is what does that. -100% puts the trail's
   RIGHT edge on the 50% line, i.e. entirely left of centre, and the -41px backs
   it off further so the dots stop just short of her. The butterfly faces right
   — her antennae are the thin ink at the far right of the drawing — so
   left-to-right is the direction of travel and no mirroring is needed.

   THE 41px IS DERIVED FROM PAINT, NOT FROM BOXES, and it has to be. Both
   drawings carry transparent margin and both are rotated, so their boxes say
   nothing about where the ink stops: her BOX starts at x585 and her PAINT at
   x608, and the trail's box ends at 672 with ink to 669. Lauren asked for
   "a little space between the line and the butterfly. like a breath is all" —
   that is a gap between the two INKS, so it was measured by mapping every
   painted pixel of each through its own transform and taking the extremes.
   The lap was +30px (ink 61px UNDER her); -41px leaves ~10px of clear paper. */
.spark-gap-path {
  /* THE DRAWING CHANGED on 2026-08-13, path-dotted-flat -> path-dotted-noloop.
     The flat one was picked for its 4.55:1 aspect, so the trail would run
     across the gap rather than stand 300px through it — but it pays for that
     shape with FAT dots, and Lauren read them as chunky at every length we
     tried ("its the chunkiness"). Measured source median dot run: flat 32px,
     noloop 13px, long/loop 9px; at a 170px display width that is 6.0px of dot
     against 2.5px and 1.7px.

     The finest is path-dotted-long — but it is BYTE-IDENTICAL to
     path-dotted-loop and really does carry a loop (71 of its 900 columns hold
     two separated strands, against 7 for noloop), and Lauren had a looped
     dotted line removed from the home page for exactly that reason. So noloop,
     which also climbs left to right and ends at its TOP-right corner, where the
     butterfly is, so it needs no mirroring.

     Length history: 250 -> 160 -> 230 -> 200 -> 170. The 160 was an
     over-correction when the trail became a tail rather than straddling her
     ("i think you cut it too much"). */
  width: 170px;
  /* 44 -> 60 with the new drawing: noloop is 2.25:1 against flat's 4.55:1, so
     at the same width it is 76px tall rather than 37, and its ink ends HIGH at
     the right. Re-derived so that end still meets the butterfly's body. */
  /* 68 -> 78 on 2026-08-24, with the 10px left below: "move the dotted line down
     a little and to the left, and the butterfly to the right a little". */
  top: 78px;
  /* The -41px became +9px when the pair moved right 50px on 2026-08-13
     ("move the butterfly to the right more on the desktop view", and the trail
     "to the right slightly also"). The two move TOGETHER by the same 50 so the
     10px breath between their inks is preserved — it was measured for, and
     moving one alone would open it back up. */
  /* +13px -> +3px. The trail and the butterfly now move APART rather than
     together, which is the opposite of the 2026-08-13 pass that shifted both by
     the same 50px to preserve the breath between their inks.

     That breath necessarily opens: measured on painted alpha it goes 15.1px ->
     33.3px across this move. Deliberate, and it still reads as one gesture,
     because the two are spanning the gap between the icons rather than sitting
     beside each other — Lauren: "i like that bc its showing they go together."

     The trail is what limits how far this can go, not the butterfly. Moving left
     walks its dots toward the left card's copy: 37.9px clear now, 26px here,
     20.5px at -2 and 10.4px at -12. The butterfly has over 100px of room on its
     own side throughout. */
  transform: translateX(calc(-100% + 3px)) rotate(-6deg);
  /* Restrained by SIZE, not opacity. This art is teal ink (#317583) and a thin
     dashed line loses its colour to transparency far faster than a leafy sprig
     does — at 0.45 it composites to a grey that reads as white. Small and
     opaque, never large and faded. Raised 0.75 -> 0.9 when the dots got finer:
     less ink to spend, so it cannot also spend contrast. */
  opacity: 0.9;
}

/* Painted two-colour art, so NO opacity and no filter — both would pull the
   very teal and purple she picked it for. Sits over the trail's centre. */
.spark-gap-bfly {
  /* 86 -> 72 on 2026-08-26, following the patches down: they went 150 -> 116 in
     the same pass and this piece is read against them, not against the band. It
     is centred by `translateX(calc(-50% + ...))`, so shrinking it holds its
     centre and only its edges move — the trail opposite keeps its own end where
     it was. */
  width: 72px;
  top: 6px;
  /* +50px -> +60px off the gap's centre line on 2026-08-24, "the butterfly to
     the right a little", as the trail went left and down. Desktop only — the
     stacked rule below sets its own transform and is unaffected.

     There is room to go further on this side: her ink still clears the right
     card's copy by 108px. What bounds the pair is the trail's end, opposite. */
  transform: translateX(calc(-50% + 60px)) rotate(-14deg);
  z-index: 1;
}

/* The phone crossover's two extra elements are OFF by default and switched on
   in the <=700px block. Desktop keeps the single teal .spark-what-leaf: there is
   a real page margin at those widths for a sprig to enter from, so it does not
   need to borrow the band. */
.spark-tear-white,
.spark-tear-clip { display: none; }

/* The clip's top is one --wave-h above .spark-what, whose top IS the hero's
   bottom, so its first --wave-h pixels are the same tear band the hero's
   .torn-bottom crops on — and both tile --wave-tile from x0 of a full-bleed
   box, so they line up by construction rather than by measurement.
   --wave-bottom-inv is generated from wave-bottom's own seed closed downward,
   so it is the EXACT complement; --wave-top is a different seed and would leave
   a mismatched band. --wave-overlap is applied the way .torn-top applies it,
   for the same reason: the tiles are fully opaque for their first 15/80 of
   height, so a 4px soft-edge inset lands inside that headroom at any size.
   `overflow: hidden` is only a bottom bound here — the top edge is the mask. */
.spark-tear-clip {
  --spark-clip-h: 260px;
  position: absolute;
  left: 0;
  right: 0;
  top: calc(-1 * var(--wave-h));
  height: var(--spark-clip-h);
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
  -webkit-mask-image: var(--wave-bottom-inv), linear-gradient(#000, #000);
          mask-image: var(--wave-bottom-inv), linear-gradient(#000, #000);
  -webkit-mask-size: var(--wave-tile) var(--wave-h), 100% calc(100% - var(--wave-h) + var(--wave-overlap));
          mask-size: var(--wave-tile) var(--wave-h), 100% calc(100% - var(--wave-h) + var(--wave-overlap));
  -webkit-mask-position: 0 0, 0 100%;
          mask-position: 0 0, 0 100%;
  -webkit-mask-repeat: repeat-x, no-repeat;
          mask-repeat: repeat-x, no-repeat;
}

/* ---------- Closing ---------- */

/* ---------- The closing band, on a photograph since 2026-08-25 ----------
   This page was the only one on the site without an original photograph, and
   this block was its emptiest moment — a script line and a button in a large
   field of white. It is now the same object as `.club-quote`: full bleed, torn
   both edges, the sign-off reversed out, and the picture pinned so the band
   scrolls over it.

   THE PHOTOGRAPH is IMG_7910.heic, sun breaking low through pines onto moss —
   Lauren picked it over IMG_8063 after seeing both in place. Cut twice, each
   centred on the burst, which sits around x900-1400, y2400-2900 of the original:

     desktop  crop (0, 1535, 3024, 3665)   3024x2130, aspect 1.42, a window's
              resize 2400x1690             shape so `fixed` never has to zoom
     phone    crop (200, 0, 2100, 4032)    1900x4032, aspect 0.47, a phone's
              resize 1200x2546
     both     GaussianBlur(1.5), WEBP q72  198KB and 195KB

   THE BLUR IS A FILE-SIZE MEASURE, AND IT WENT TOO FAR AT FIRST. Unblurred these
   are 524KB and 494KB — three to four times every other band — because a forest
   of thin trunks is nearly incompressible. But 3.0 turned the sunburst, which is
   the whole reason for this photograph, into a haze. 1.5 keeps the star shape,
   still halves the file, and the trunks stay soft enough not to read through the
   script. Same trick as `.about-thankyou`, one notch lighter.

   THE WASH IS WARM, NOT THE CLUB'S PLUM. It started as a copy of `.club-quote`'s
   rgba(46, 30, 58), which is right over a pink zinnia and actively cancels a
   golden forest — the band came back reading grey-purple with none of the
   picture's warmth. rgba(38, 26, 16) is a dark brown: it darkens without
   neutralising the orange, and it MEASURES BETTER as well, 3.60:1 against the
   plum's 3.41 at the same depth. Site teal was tried too and cools it further,
   2.18. This is the only band on the site whose scrim is not in the teal/plum
   family, and the photograph is the reason.

   THE WASH IS x1.2 OF THE CLUB'S CURVE, and the reason it needs any is worth
   recording: all three photographs Lauren offered have a BLOWN-OUT WHITE SUN, so
   wherever the copy crosses it the contrast is set by the wash alone and not by
   the picture — all three measured identically, to two decimals. At the club's
   depth the sign-off came back 2.82:1 against the 3.0 it needs; x1.2 gives 3.71
   for 51% of the photograph.

   If the picture is ever wanted brighter, the lever is moving the copy OFF the
   sun's column rather than deepening this further — the club quote does exactly
   that. The copy here is centred and the sun is centre-ish, so they collide by
   default. */
.spark-closing {
  position: relative;
  padding:
    calc(var(--section) + var(--wave-h) + 1rem) 0
    calc(var(--section) + var(--wave-h) + 1rem);
  text-align: center;
  overflow: hidden;
  overflow: clip;
  background:
    linear-gradient(180deg,
      rgba(38, 26, 16, 0.31) 0%,
      rgba(38, 26, 16, 0.50) 22%,
      rgba(38, 26, 16, 0.60) 45%,
      rgba(38, 26, 16, 0.60) 62%,
      rgba(38, 26, 16, 0.46) 82%,
      rgba(38, 26, 16, 0.31) 100%),
    url("../images/spark-closing-phone.webp") center 50% / cover no-repeat;
}

/* Reversed out, where it was --script-blue on white paper. */
.spark-closing .spark-closing-script { color: var(--cream); }
.spark-closing .wrap { position: relative; z-index: 2; }

/* The wide crop and the pinned picture, pointer-gated — see the long note at
   `.home-joy::before`. Touch devices keep a plain scrolling background at the
   phone crop set above, whatever their width. */
@media (min-width: 761px) and (hover: hover) and (pointer: fine) {
  /* A FIXED LAYER, NOT A FIXED BACKGROUND — 2026-08-26, the same swap as
     `.home-joy::before`; the reasoning lives there in full. Short version:
     `background-attachment: fixed` repaints on the main thread every frame and
     lags the copy moving over it, which is the shakiness Lauren reported; a
     `position: fixed` box has identical geometry and the compositor simply does
     not move it. `clip-path` is what holds it inside the band — `overflow: clip`
     cannot clip a fixed descendant — and it must not be a transform or a filter,
     which would make the section a containing block and un-fix the layer.

     THE SCRIM HAD TO COME OFF THE SECTION with it. It was the first layer of the
     same `background` shorthand, which is what guaranteed it painted above the
     picture; a pseudo-element always paints above its element's own background,
     so once the picture is a pseudo the scrim cannot stay where it was. It moves
     to ::after at the band's size — the shape is byte-for-byte the gradient that
     was measured for this band, only its host changed. */
  .spark-closing {
    clip-path: inset(0);
    background-image: none;
  }

  .spark-closing::before {
    content: "";
    position: fixed;
    inset: 0;
    z-index: 0;
    background: url("../images/spark-closing-wide.webp") center 50% / cover no-repeat;
  }

  .spark-closing::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    background:
      linear-gradient(180deg,
        rgba(38, 26, 16, 0.31) 0%,
        rgba(38, 26, 16, 0.50) 22%,
        rgba(38, 26, 16, 0.60) 45%,
        rgba(38, 26, 16, 0.60) 62%,
        rgba(38, 26, 16, 0.46) 82%,
        rgba(38, 26, 16, 0.31) 100%);
  }
}

/* And the phone pinning, the scroll-driven one. Placed here rather than beside
   the shared `.pin-photo` rules because `.spark-closing` is declared just above
   at the same specificity and source order would otherwise win — the same trap
   that cost a round on `.oto-do` and `.about-thankyou`. */
@supports (animation-timeline: view()) {
  @media (max-width: 760px) and (prefers-reduced-motion: no-preference) {
    .spark-closing {
      --pin-img: url("../images/spark-closing-phone.webp");
      background-image: none;
      /* THE SUNLIGHT, CENTRED — 2026-08-26. Lauren: "i want the sunlight
         centered."

         Why it needed a new lever rather than a background-position: on a phone
         this photograph is not a background at all, it is the pinned layer, and
         `.pin-photo > i` is 100lvh tall. The file is 1200x2546 (aspect 0.471) in
         a 390x900 box (0.433), so `cover` scales it BY HEIGHT — the whole image
         height is already on screen and `background-position-y` has nothing left
         to move. Only the travel can move it.

         The arithmetic, which is worth keeping because it is not guessable:
         the travel is -100lvh -> +100% over an entry-to-exit range, so 1px of
         scroll is 1px of translate, and when the band is centred in the window
         the layer sits at -(100lvh - band)/2. That puts the image's MIDPOINT at
         the band's centre. Measured on the file, the glow's centre of mass is at
         0.620 of its height and the brightest row at 0.670 — so the light lands
         at band y 321-366 of 427, in the bottom quarter.

         -130px is between those two: it centres the glow and keeps the brightest
         row just below middle, which is where it reads as light coming through
         the trees rather than a lamp behind the type. Re-measure if the crop or
         --section ever changes. */
      --pin-shift: -130px;
    }
    .spark-closing::after {
      content: "";
      position: absolute;
      inset: 0;
      z-index: 1;
      pointer-events: none;
      background: linear-gradient(180deg,
        rgba(38, 26, 16, 0.31) 0%,
        rgba(38, 26, 16, 0.50) 22%,
        rgba(38, 26, 16, 0.60) 45%,
        rgba(38, 26, 16, 0.60) 62%,
        rgba(38, 26, 16, 0.46) 82%,
        rgba(38, 26, 16, 0.31) 100%);
    }
  }
}

/* Lauren, 2026-08-13: "a sage leaf on the right side under the discover self
   love club button. have the stem coming from the right and the leaves curving
   to the left and under the button."

   The source drawing runs stem-at-the-BOTTOM, tip-at-the-top — measured, not
   assumed: its bottom eighth spans 424px of ink reaching to x555, its top
   eighth only 54px at x76-130. `rotate(-90deg)` swings that bottom round to
   point RIGHT, so the stem enters from the margin and the leaves sweep left
   underneath the button, which is what she asked for.

   THE ROTATION ARITHMETIC, which any resize of this needs. At 90 degrees the
   on-screen box is not the layout box: height collapses to W and width opens to
   k*W, with k = 1004/560 = 1.793 for the SAGE drawing (the teal one is 811 tall
   and has its own k — they are different sprigs). Both visible edges move by
   (k/2 - 1/2) * W = 0.396 * W, right OUTWARD and bottom UP. So growing W moves
   the drawing unless `right` and `bottom` are re-derived with it. */
/* Sage sprig in the closing band: stem entering from the right margin, leaves
   curving left. On DESKTOP it stays out at the right and does not reach the
   button — Lauren, 2026-08-13: "for desktop you can just keep it off to right
   side, not under the button." On a PHONE it goes under the button; see the
   <=700px block.

   That split is not a preference, it is forced. The sprig is anchored to the
   page's right edge while the button is CENTRED, so the distance between them
   grows with the window: a size that reaches under the button at 1440 puts 58
   painted pixels on the copy at 1024, and one that clears at 1024 falls 100px
   short of the button at 1440. On a phone the problem vanishes, because the
   button nearly spans the page.

   THE ROTATION ARITHMETIC, which any resize needs. At 90 degrees the on-screen
   box is not the layout box: height collapses to W and width opens to k*W, with
   k = 1004/560 = 1.793 for the SAGE drawing. (The teal sprig is 811 tall and has
   its own k — they are different drawings, which is also why the two must never
   be paired as a colour-changing crossover.) Both visible edges move by
   (k/2 - 1/2) * W = 0.396 * W, right OUTWARD and bottom UP. The first attempt
   ignored that term and put 43px of the drawing off the page. */
/* GONE AT EVERY WIDTH, 2026-08-25, Lauren's call — desktop first, then phones
   once she saw the same problem there. It was a sage sprig on white paper here
   until this section became a photograph band; the white colourway went in with
   the band, because sage line art drawn for paper disappears over a dark
   picture. Over the forest it reads as a sticker stuck on top rather than as
   part of the scene, and the photograph already has real leaves in it.

   THE POSITIONING RULES BELOW ARE LEFT INTACT on purpose, both the base one and
   the narrow-width one. They cost nothing while this is hidden and they are the
   whole placement if the sprig is ever wanted back — delete this rule and it
   returns exactly where it was. */
.spark-closing-leaf { display: none; }

.spark-closing-leaf {
  width: 240px;
  /* 116 -> 76 on 2026-08-13 ("move those sage leaves to the right a little").
     That puts the painted stem 16px PAST the page edge instead of 24px inside
     it, so the sprig reads as entering from the margin rather than starting in
     mid-air — the same read every other sprig on the site has. Safe to run off:
     body is overflow-x: hidden, so it clips rather than scrolling. */
  right: 76px;
  bottom: -92px;
  transform: rotate(-90deg);
  opacity: 0.85;
}

.spark-closing-script {
  font-family: var(--font-script);
  font-variation-settings: var(--display-vars);
  font-style: italic;
  /* THE FLOOR WENT 1.417 -> 1.55rem ON 2026-08-25, a contrast decision as much as
     a reading one. On a phone this clamp bottoms out, and at 22.7px the line sat
     just under WCAG's 24px large-text threshold — so reversed out over the new
     photograph it needed the full 4.5, which took a x1.6 wash and left 34% of
     the picture. At 24.8px it needs 3.0, x1.2 does it, and 51% survives. Bigger
     type and a brighter photograph out of one change. The `.accent` rule below
     carries the same clamp and had to move with it, or it would simply win.
     Same fix as `.about-thankyou .thanks-lead`. */
  font-size: clamp(1.55rem, 2.592vw, 1.863rem);
  line-height: 1.4;
  color: var(--script-blue);
  max-width: 34rem;
  margin-inline: auto;
}

/* ---------- Sunday Spark, narrow ---------- */

/* The trail is re-solved TWICE more on the way down, because the hero is not a
   fixed box: its h1 is a clamp() and its tagline goes from two lines to one at
   ~965px, so the button climbs 76px between 1280 and 900 while the butterfly,
   at `top: 8.5rem`, does not move at all. A line pinned to both ends therefore
   has to get shorter as the window narrows. Each band is solved AT ITS NARROW
   EDGE, where the pill is highest, and then checked across.

   Measured: the pill's top sits at y398 at 1280 and above, 383 at 1101, 372 at
   1024, 365 at 970 — and then jumps to 329 at 960 when the tagline unwraps.
   That jump is the reason for the 965 boundary; it is a wrap, not a curve, and
   no single value spans it. */
@media (max-width: 1100px) {
  .spark-hero-path {
    width: 260px;
    left: calc(50% + 170px);
    top: 17.75rem;
    transform: rotate(-25deg) scaleX(-1);
  }
}

@media (max-width: 965px) {
  .spark-hero-path {
    width: 220px;
    left: calc(50% + 195px);
    /* 16.75 -> 16.6rem. At 16.75 the tail cleared the pill's bottom edge by a
       hair at 870 (2 painted samples below it) while still landing inside at
       965; 16.6 lands inside at both ends of the band. */
    top: 16.6rem;
    transform: rotate(-20deg) scaleX(-1);
  }
}

@media (max-width: 860px) {
  /* 2.6rem -> 7rem. The gap IS the pocket once the cards stack, and at 2.6rem it
     was 42px against a 93px butterfly — the piece landed 324 painted pixels on
     the copy above it. This is the "THE GAP IS THE BUDGET" rule: when a drawing
     has to live between two things, the space between them is what decides
     whether it can, and shrinking the art to fit a too-small gap just makes it
     unreadable. 112px leaves ~9px of clear paper either side of the butterfly. */
  .spark-items { grid-template-columns: 1fr; gap: 7rem; max-width: 26rem; margin-inline: auto; }
  /* Stacked, the row itself is already the reading measure, so the per-item cap
     would only narrow it a second time. */
  .spark-items .item { max-width: none; }

  /* 96px, a deeper cut than the desktop's 116 and the one Lauren asked for by
     name. Stacked, each patch has the full column to itself and no neighbour to
     be scaled against, so it reads larger than the same number does across two
     cards — at the old 150 it filled 38% of a 390px screen. This only ever makes
     the gap the butterfly sits in TALLER, so the clearance measured below is a
     floor, not a ceiling. */
  .spark-items .si-img { width: 96px; }

  /* Stacked, "between the icons" is a VERTICAL gap, and a tight one — 42px of
     clear paper between the first card's last line and the second card's patch.
     `top: 50%` lands in it by construction rather than by measurement: the two
     cards are the row's only in-flow children, so the row's midpoint IS the gap
     between them, at any width and however the copy wraps.

     translate() leads and rotate() follows: transforms apply right to left, so
     the piece rotates about its own centre first and the centring then reads in
     screen space. The percentages in translate resolve against the unrotated
     border box, which is what keeps this stable as the angle changes.

     Both come down in size — the pocket cannot take the desktop butterfly, which
     is 129px tall against a 42px gap. It is allowed to lap the PATCH below it;
     that is painted art, not copy, and a butterfly passing an icon reads as
     intended. The rule Lauren set was "not touching text". */
  .spark-gap-path {
    width: 130px;
    top: 50%;
    /* Same breath as desktop, re-derived at this size rather than copied: the
       pieces are ~72% of their desktop widths here, so the gap is 7px, not 10.
       Measured ink-to-ink, not box-to-box. */
    /* +42px vertical drops the trail below the row's midpoint ("the dotted line
       needs to be moved down on mobile", then "a little more"). Sweeps stay
       clean of text all the way to +66, but that is the ceiling worth using:
       the trail climbs to the right, so its HEAD is its top edge, and past ~66
       the head falls to her lower rim and the two stop reading as joined. At
       +42 the head still runs 34px up into her body.

       The horizontal term carries the pair's +22px shift off centre: -29 + 22
       = -7. Lauren, 2026-08-13: "move the butterfly to the right a little so
       everything isnt perfectly centered." BOTH pieces take the same 22, so the
       7px breath between their inks survives the move — shifting one alone
       would open it straight back up, the same trap as on desktop. */
    /* FLIPPED 2026-08-22, Lauren: "flip it so the butterfly is facing to the
       left and down, and the line trailing up and behind it."

       The SIDES SWAP, the drawings mostly do not. The butterfly moves to the
       left of centre and the trail to the right, so the pair now reads
       right-to-left. The path art already rises left-to-right, which is exactly
       what "trailing up behind her" needs once she is the left-hand element —
       so it is NOT mirrored. Mirroring it would make it fall away to the right
       instead, which is the opposite of the ask.

       Its left edge now sits at centre + 22, and the butterfly's right edge 7px
       short of that, so the 7px ink breath and the +22px off-centre shift both
       survive the swap. */
    transform: translate(calc(30px), calc(-50% - 16px)) rotate(-4deg);
  }
  .spark-gap-bfly {
    /* 62 -> 52, with the stacked patches' 150 -> 96. Safe against the trail by
       construction: the translate below leads with -100%, so her RIGHT edge is
       the anchored one and the 7px breath to the trail survives any width. */
    width: 52px;
    top: 50%;
    /* scaleX(-1) turns her to face LEFT; it is the rightmost transform so it
       applies FIRST, which leaves the rotate() that follows working in ordinary
       screen terms rather than in the mirrored frame. rotate(-18deg) then tips
       the head down — with the head pointing left, a negative angle drops it,
       where on the unmirrored art the same sign lifted it.

       Her right edge lands 7px short of the trail's left edge; see the note on
       .spark-gap-path above for why both carry the same +22. */
    transform: translate(calc(-100% - 7px + 22px), calc(-50% + 4px)) rotate(-18deg) scaleX(-1);
  }
  /* The stagger only reads as a stagger across a row. Stacked, --lift is just an
     uneven gap. */
  .spark-items .item { --lift: 0rem; }
  /* Smaller and pulled further off the page edge. The angle is held at the
     desktop -140deg so it is recognisably the same sprig; only the size and the
     offsets move. Measured, not judged: at 170px/-58px it put 13 painted pixels
     on the first card's copy once the row stacked. A px `top` rather than a
     percentage, because the section's height nearly doubles when the three
     items stack and a percentage walks the sprig down with it. */
  .spark-what-leaf { width: 170px; left: -92px; top: 20px; }
  .spark-hero-bfly { width: 96px; top: 7rem; left: auto; right: 4%; }
  /* The trail has to follow her here. Above 860 both pieces hang off the centre
     line; at this breakpoint she jumps to `right: 4%` and a centre-anchored
     trail is left behind in the middle of the band pointing at nothing. That was
     true before 2026-08-19 too, but a 340px trail makes it obvious rather than
     merely wrong, and at 800 it also ran 6px off the right edge (clipped, not a
     scrollbar, but still off the page).

     Right-anchored to match her, and swept rather than scaled down by eye.
     SOLVED AT 720, the bottom of this band, not in the middle of it: the tagline
     is one line throughout the band and it grows as the viewport does, so 720 is
     where it reaches furthest under the butterfly (x666 of 720, against x706 of
     800). Values that clear it at 800 put 78 painted samples across it at 720 —
     which is exactly what the first pass here did. 150px at right 7% / top 11rem
     clears every glyph at 720, 800 and 860, and lands the head 4-8px under her
     abdomen tip across the band.

     IT DOES NOT REACH THE BUTTON HERE, and cannot. Above 860 the trail runs
     button-to-butterfly, which is the whole point of it; in this band she jumps
     to the top-right corner while the button stays centred, and the tagline —
     one full-width line at y254-282 — lies straight across every route between
     the two. The sweep returns ZERO combinations that touch the button, tuck
     under her, and clear the type. So it is a short flourish trailing from her
     instead. Don't "fix" it by dragging it down to the pill; check the sweep. */
  .spark-hero-path {
    width: 150px;
    left: auto;
    right: 7%;
    top: 11rem;
    transform: rotate(-5deg) scaleX(-1);
  }
}

@media (max-width: 700px) {
  .spark-hero { padding: 7.5rem 0 5rem; }
  .spark-hero .signup-form { flex-direction: column; align-items: stretch; }
  /* .signup-form's field is `flex: 1 1 200px`, and once the row becomes a
     COLUMN that 200px basis is a HEIGHT — the email box grew into a 200px slab.
     Basis back to auto so the field is sized by its own padding and text. */
  .spark-hero .signup-form input[type="email"] { flex: 0 0 auto; }
  .spark-hero .signup-form .btn { width: 100%; }
  /* Below the wordmark it has nowhere to be that is not over the copy — the
     centred column takes the full width here. The trail goes with it: a trail
     to a butterfly that is not there is just a line. */
  .spark-hero-bfly,
  .spark-hero-path { display: none; }

  /* The sage sprig goes UNDER the button here, which is what Lauren asked for
     on the mobile view. The band below the button had to grow for it,
     var(--section) -> 9rem: a phone button nearly spans the page and is a SOLID
     teal pill, so "under the button" cannot mean lapped over it (the drawing
     would sit on the fill) or behind it (the fill would hide the drawing) — it
     has to mean BELOW it, and 72px of band could not hold anything bigger than
     a speck. Same call as the stacked card gap further up: open the space
     rather than shrink the art until it stops reading. */
  .spark-closing { padding-bottom: 9rem; }

  /* Stem in from the right margin, leaves sweeping left and passing BEHIND the
     button — the deco comes before .wrap in the markup and nothing here opens a
     stacking context, so the teal pill paints over the drawing and the leaves
     read as running underneath it. 180px with `right` and `bottom` derived from
     it by the 0.396 * W rotation term, same as desktop. */
  /* right 88 -> 52 ("now just move those sage leaves to the right a little").
     That takes the painted stem from 18px INSIDE the page edge to 18px past it,
     so it enters from the margin rather than starting in mid-air — the same
     treatment the desktop one got, which runs 16px off. */
  .spark-closing-leaf { width: 180px; right: 52px; bottom: -70px; }

  /* THE PHONE CROSSOVER, 2026-08-13. Lauren: "i think on here we overlap onto
     the teal and make it go from white to teal leaves."

     One drawing, two colourways, at ONE position, each clipped to its own side
     of the hero's torn edge — the technique the home page and the club page
     already use. leaf-vine-white and leaf-vine-teal are the SAME 560x811
     source, which is the condition for a colour-changing pair: two different
     sprigs cannot be aligned at any offset.

     The single-piece .spark-what-leaf stands down here and the pair takes over,
     rather than trying to make one element do both jobs. That is the
     .hero-seam-bfly lesson from the home page: a crossover cannot be run from
     inside a masked section, because the half that should land on the paper is
     erased by the same mask that crops the half on the band.

     BOTH OFFSETS DERIVE FROM ONE VALUE, --spark-hero-drop, so they cannot drift:
       white's element bottom  = hero_bottom + drop
       teal's  element bottom  = clip_bottom - (clip_h - wave_h - drop)
                               = hero_bottom + drop, by construction
     and both resolve `left` against full-bleed boxes that share left and width
     (the hero, and a clip that is left:0/right:0 in a full-bleed section).
     That shared-box condition is what keeps a crossover together on resize —
     a fixed px offset on one half alone is a latent bug, never a value. */
  .spark-what-leaf { display: none; }

  .spark-tear-white,
  .spark-tear-clip { display: block; }

  /* Raising the drop moves BOTH halves together and trades teal for white:
     less of the drawing below the tear, more of it up on the band. */
  .spark-tear-white,
  .spark-tear-teal {
    /* 140 -> 180 with the desktop sprig, Lauren: "i think the leaves need to be
       bigger?" The drop grows with it, 96 -> 120, so the white/teal split stays
       about half and half rather than the drawing sliding up onto the band.
       BOTH halves take these values from the one rule — change them here or the
       stem breaks at the seam. */
    --spark-hero-drop: 120px;
    width: 180px;
    left: -108px;
    transform: rotate(-165deg);
    opacity: 0.85;
    top: auto;
  }
  .spark-tear-white { bottom: calc(-1 * var(--spark-hero-drop)); }
  .spark-tear-teal  { bottom: calc(var(--spark-clip-h) - var(--wave-h) - var(--spark-hero-drop)); }

  /* Superseded by the crossover above; kept only so the note below still reads.
     Phones get a designed placement rather than a hide, per the standing rule.
     Flat px, never min(Xpx, Y%) — that collapses on a narrow page and the sprig
     disappears entirely.

     Lauren, 2026-08-13: "on the mobile move it to the right so the leaves are
     on the page more." -108 -> -92 puts 72px of leaf on a 390px page against
     56. THAT IS THE CEILING, measured: a 2-D sweep of seven `left` values
     against seven `top` values returned exactly two clean placements, both at
     -92. Everything further right paints on the heading, because at 92% wrap
     there is no page margin here — the copy runs the full width and the sprig
     only has the sliver the centred lines leave. */
  .spark-what-leaf { width: 140px; left: -92px; top: 16px; }
}

/* The smallest phones cannot take the step above: at 320 the same -92 puts 18
   painted pixels on the copy, because the wrap narrows with the page but the
   sprig does not. Back to the value that clears there, 56px on page. Same
   two-step shape as .vine-pillars-left on the home page. */
@media (max-width: 360px) {
  /* The single sprig is not shown at these widths any more — the crossover is —
     so this now steps the PAIR. -108 puts 9 painted pixels on the copy at 320
     because the wrap narrows with the page while the drawing does not. Both
     halves, together, always. */
  .spark-tear-white,
  .spark-tear-teal { left: -118px; }
}

/* ============================================================
   Icon-card labels, 2026-08-19
   ============================================================
   Movement / Creativity / Nature / Play / Self-Expression, the club's "Inside
   the Club" cards, and Sunday Spark's two items. These ran on Atma for a few
   hours; Lauren then took it off — "lets also keep the icons text in the sans
   font we have so we dont have too many font styles going on" — so they now use
   the body sans rather than the display face, which is what the h1/h2/h3 rule
   would otherwise give them.

   700 rather than the sans's own 500: at 22px in title case, sitting under a
   watercolour patch and above a paragraph of the SAME family, only the weight
   separates the label from the copy. The uppercase sans labels elsewhere on the
   site (.believe h2, .who-for h2) take 700 for the same reason.

   ATMA IS NOW UNUSED and has been removed from the font links in all eight
   pages. Do not reintroduce it without her asking. */
.pillar h3,
.inside-card h3,
.spark-items h3 {
  font-family: var(--font-body);
  font-weight: 700;
}


/* ==========================================================================
   1:1 With Lauren — one-on-one.html, added 2026-08-23

   Nothing here invents a treatment. Every band, scrap, patch row and pull-quote
   on this page is one the site already owns, and this block is mostly geometry:
   which existing recipe each section wears, and where its decoration sits.

   NOTHING ON THIS PAGE CROSSES A TORN EDGE, deliberately — the same decision
   the Sunday Spark page records. A crossover needs a matched pair of halves
   whose offsets are re-derived together at every width (see the vine notes
   further up this file) and this page has no pair: every decoration here lives
   entirely inside one section.
   ========================================================================== */

/* ---------- Shared, page-wide ---------- */

/* The pull-quote that turns a passage. `.script` is an inline span everywhere
   else it is used, so it has to become a block to sit on its own line and take
   a measure; `margin-inline: auto` centres that measure, because `text-align`
   alone would not once max-width binds. Same job as `.pillars-close .script` on
   the home page — and as `.story-turn` on About, until that page's last
   pull-quote was cut on 2026-08-25 — and no new type style.

   NOTHING USES IT RIGHT NOW. This page's one pull-quote was cut in the same
   2026-08-25 rewrite that took About's, so the class matches no element on the
   site. It is kept because the shape keeps coming back and the rule is three
   lines; if it is still unused the next time this block is opened, delete it. */
.oto-turn {
  display: block;
  max-width: 30rem;
  margin: 1.9rem auto;
}

/* ---------- 1 · Hero ----------
   A FULL-BLEED PHOTOGRAPH, built the way About's is. Lauren, 2026-08-23: "use
   this as the hero section. lets try what it looks like how i did the about."
   So this is `.about-hero`'s construction, value for value where it transfers:
   a cover photograph with a dark gradient over it, a teal frosted layer on
   ::before, a torn bottom edge, and the page title reversed out in cream with a
   shadow under it.

   WHAT IT REPLACED: a --panel-blue watercolour band. The photograph is a
   swallowtail on white blossom against a blue sky, so the band is still blue —
   it is just a real sky now, and the butterfly is the site's own motif arriving
   as a photograph rather than as line art.

   THE SCRIM IS NOT DECORATION. About's note records why: the nav sits over the
   hero on every page, and cream links over a bright sky measured 1.4:1 there.
   Same sky here, same problem, same answer — the gradient plus the frosted
   layer is what buys the header its contrast, and the top stop is heavier than
   About's because this photograph's top third is brighter than that one's.

   TWO ASSETS, NOT ONE, and the phone one is not an optimisation. The band is
   wider than it is tall on a desktop and TALLER than it is wide on a phone, and
   `cover` resolves those two boxes completely differently: at 390 the landscape
   crop scales up ~3x and shows a thin vertical core of the frame, which on this
   photograph is empty sky, because the butterfly sits well left of centre. The
   -tall asset is cropped for that box. See the <=760 rule below. */
.oto-hero {
  position: relative;
  display: flex;
  align-items: flex-end;
  min-height: clamp(520px, 74vh, 720px);
  padding: 7rem 0 calc(1.4rem + var(--wave-h));
  overflow: hidden;
  background:
    linear-gradient(180deg,
      rgba(17, 78, 88, 0.42) 0%,
      rgba(17, 78, 88, 0.14) 22%,
      rgba(17, 78, 88, 0.10) 62%,
      rgba(17, 78, 88, 0.46) 100%),
    url("../images/oto-hero-butterfly.webp") center 62% / cover no-repeat;
}
/* Teal frosted-glass layer over the photograph, exactly as About does it. */
.oto-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  background: rgba(20, 86, 94, 0.30);
  -webkit-backdrop-filter: blur(1px);
          backdrop-filter: blur(1px);
  pointer-events: none;
}

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

/* RIGHT, where About's is left, and the photograph is the whole reason. The
   butterfly occupies the frame's lower left and the branch runs up through the
   middle; the one unbroken run of sky is the right-hand third, which is the
   only place three lines of type can sit without landing on a wing. Measured
   rather than assumed — the title was set left first and the "1" of "1:1" fell
   across the yellow of the lower wing. */
.oto-hero-copy {
  max-width: 34rem;
  margin-left: auto;
  text-align: right;
}

/* Reversed out for the photograph. The site's "display headings go NAVY" rule
   holds on paper and on the pale panels; over a sky it measures nothing, which
   is the same call About's title makes.

   The shadow is doing real work rather than adding style: the sky behind these
   lines is not one value, it runs from near-white cloud to mid blue, so a flat
   cream would drop to ~2:1 wherever a cloud sits behind a letter. */
.oto-hero h1 {
  color: var(--cream);
  font-size: clamp(2.43rem, 5.1vw, 4.05rem);
  letter-spacing: 0.01em;
  margin-bottom: 0.6rem;
  text-shadow: 0 2px 18px rgba(10, 38, 44, 0.6);
}

/* The "Coming to Lumi Libra" line, which sits BELOW the heading on this page —
   Lauren's order, 2026-08-23. That inverts the usual eyebrow: every other page
   on the site sets its small caps above the title. `.eyebrow` carries a bottom
   margin written for sitting above something, so `.oto-hero-status` cancels it
   and gives a top margin instead. */
.oto-hero .eyebrow {
  color: rgba(250, 250, 248, 0.94);
  letter-spacing: 0.22em;
  font-size: 0.999rem;
  text-shadow: 0 1px 12px rgba(10, 38, 44, 0.55);
}

.oto-hero-status { margin: 0.5rem 0 0.9rem; }

/* The tagline, back for a third time — the band carried "A space to come back
   to you.", then "Personalized time to explore what makes you feel more like
   you.", then nothing at all for one revision. This one is the longest of the
   three, so the measure is wider than the 26rem the first took. */
.oto-hero .script {
  display: block;
  color: var(--cream);
  max-width: 30rem;
  margin-left: auto;
  text-wrap: balance;
  text-shadow: 0 2px 14px rgba(10, 38, 44, 0.55);
}

/* The portrait crop takes over where the band stops being wide. `background`
   is restated in full rather than only `background-image`: the shorthand above
   carries the gradient, and overriding one layer of a shorthand is how you end
   up with the gradient silently dropped. */
@media (max-width: 760px) {
  .oto-hero {
    background:
      linear-gradient(180deg,
        rgba(17, 78, 88, 0.44) 0%,
        rgba(17, 78, 88, 0.16) 24%,
        rgba(17, 78, 88, 0.12) 60%,
        rgba(17, 78, 88, 0.48) 100%),
      url("../images/oto-hero-butterfly-tall.webp") 32% center / cover no-repeat;
  }

  /* Centred again once the copy has the full width — a right-set block on a
     390px page reads as an accident rather than as placement. */
  .oto-hero-copy { margin-inline: auto; text-align: center; }
}

/* ---------- 2 · The opening ---------- */

/* Bare paper: `main` carries the continuous ground and this section adds
   nothing of its own. */
.oto-open { position: relative; padding: var(--section) 0 calc(var(--section) - 0.5rem); }
.oto-open .wrap { position: relative; z-index: 1; }

/* A single centred column at a reading measure. Her opening is five short
   paragraphs; run across the full 1160px wrap they would be five one-line
   banners. */
.oto-open-copy {
  max-width: 40rem;
  margin-inline: auto;
  text-align: center;
  font-size: var(--t-md);
  line-height: 1.8;
}

.oto-open-copy p + p { margin-top: 1.15rem; }

/* THE CLOSE, on its own class rather than on position. This was
   `.oto-open-copy .oto-turn + p` — the paragraph after the pull-quote — which is
   a selector that describes where the line sits instead of what it is. Her
   2026-08-25 rewrite cut the pull-quote, `.oto-turn` stopped matching anything in
   this section, and the emphasis on "That's what these sessions are about."
   would have disappeared without a single rule being touched. A class survives
   the copy moving; an adjacency does not. */
.oto-open-copy .oto-close { font-weight: 700; color: var(--navy); }

/* ---------- The sprig that changes colour at the 1:1 HERO's tear ----------
   Lauren, 2026-08-24: "lets do a white to teal leave coming down from the
   bottom left corner of the hero page into the white section. once it hits
   white, turn to teal."

   White while it is on the photograph, teal the moment it reaches the paper
   below. ONE drawing, two colourways, two copies at pixel-identical positions —
   `leaf-vine-white` and `leaf-vine-teal` are both 560x811 from the same source,
   which is the condition that makes this work at all. Never pair it with
   `leaf-vine-sage`: that is a different drawing (aspect 1.792 against 1.448)
   and cannot be aligned at any offset.

   THIS IS THE .club-tear-clip CONSTRUCTION, NOT THE HOME PAGE'S. The home
   crossover clips its lower half with a plain overflow box starting --wave-h
   above the tear, accepting that the lower colourway spills into the wave's
   peaks — fine there, because that spill is teal on a teal band. Here the band
   above is Lauren's BUTTERFLY PHOTOGRAPH, so the same spill would be teal line
   art painted over the sky. That is the exact fault she caught on the club page
   ("the sage is in the purple instead of being white"). So the clip is masked
   with --wave-bottom-inv, generated from wave-bottom's own seed closed
   downward, and the two halves tile exactly.

   Alignment is BY CONSTRUCTION, not measurement. .oto-hero's .torn-bottom puts
   its wave at `0 100%`, so the tear band is the hero's last --wave-h pixels;
   this clip's top is one --wave-h above .oto-open, whose top IS the hero's
   bottom, so the clip's first --wave-h pixels are that same band. Both tile
   --wave-tile from x0 of a full-bleed box.

   .oto-open already carries `position: relative` and puts its .wrap at
   z-index 1, so the teal half sits behind the copy without either being
   touched. */
.oto-tear-clip {
  /* THIS HAS TO GROW WITH --oto-hero-drop, and that is the trap in this piece.
     The teal half's bottom always lands at (hero bottom + drop) — the clip's
     height cancels out of that sum by construction — so raising the drop moves
     the drawing down while the clip's lower edge stays put, and past a point the
     clip simply chops the vine's foot off. Measured: at drop 225 the foot had
     53px of clearance under it, so the 280 below would have cut it. 375 restores
     ~72px. Check the clearance after ANY change to the drop, and measure it on
     painted alpha rather than the element box — the box runs well past the ink.

     It still has to stay inside .oto-open (345px tall), or the teal half starts
     showing over the section beneath. */
  --oto-clip-h: 375px;
  position: absolute;
  left: 0;
  right: 0;
  top: calc(-1 * var(--wave-h));
  height: var(--oto-clip-h);
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
  -webkit-mask-image: var(--wave-bottom-inv), linear-gradient(#000, #000);
          mask-image: var(--wave-bottom-inv), linear-gradient(#000, #000);
  -webkit-mask-size: var(--wave-tile) var(--wave-h), 100% calc(100% - var(--wave-h) + var(--wave-overlap));
          mask-size: var(--wave-tile) var(--wave-h), 100% calc(100% - var(--wave-h) + var(--wave-overlap));
  -webkit-mask-position: 0 0, 0 100%;
          mask-position: 0 0, 0 100%;
  -webkit-mask-repeat: repeat-x, no-repeat;
          mask-repeat: repeat-x, no-repeat;
}

/* EVERY DECLARATION HERE IS ON THE SHARED SELECTOR, and that is the rule the
   piece lives or dies by: the two halves are pixel-identical copies of one
   drawing, and the colour change only reads while they stay that way. Split any
   of left / width / opacity / transform across the two and it stops being a
   sprig that changes colour and becomes two sprigs that nearly line up. */
.oto-tear-white,
.oto-tear-teal {
  /* How far the sprig's foot sits below the hero's bottom edge. Both halves
     derive from this one value, so they cannot drift apart. Raising it trades
     white for teal: less drawing on the photograph, more on the paper. */
  /* SCALES WITH THE DRAWING, and it has to. This was a flat 280px, which is
     right at 1440 and wrong everywhere below it: `width` bottoms out at 21vw,
     so between about 760 and 1360 the sprig shrinks while the drop does not,
     and it walks off the bottom of the tear. Measured at 761px the topmost ink
     sat 54px BELOW the hero's edge — no white half at all, the same failure the
     narrow rule was written to fix.

     clamp(75px, 19.5vw, 280px) is 280 at 1440 and above, so the placement
     Lauren approved is unchanged, and it tracks the drawing down from there. */
  --oto-hero-drop: clamp(75px, 19.5vw, 280px);
  /* 2.5% -> 0.8% with the drop, 2026-08-24: "move it lower and to the left a
     little". At 1440 that walks the painted stem about 21px PAST the left edge,
     which is deliberate and is the same idiom .club-tear-white uses on the other
     side ("20px past the right edge, so the sprig reads as entering from the
     margin rather than starting in mid-air"). Left overflow costs nothing: it
     is clipped without producing a scrollbar, unlike the right edge. */
  left: -0.7%;
  /* vw rather than %, so it and the drop above are in the same units and cannot
     drift apart as the viewport changes. 21vw hits the 300px cap at 1429, so
     desktop is unaffected. */
  width: min(300px, 21vw);
  opacity: 0.62;
  /* Lauren, 2026-08-24: "flip it so the leaves are facing down, and the stem is
     coming from the left side" — very nearly word for word what she asked of
     the home page's crossover, and the answer is the same shape.

     READ THE DRAWING FIRST: leaf-vine-teal has its BARE STEM entering at the
     bottom-right and its leafy tip at the top-left, so the stem-to-tip vector
     points up and to the LEFT. Everything below follows from that one fact, and
     anyone changing this number should look at the asset before guessing.

     170deg turns that vector to roughly (558, 633) — down and to the right at
     about 49 degrees below horizontal — which puts the bare stem in at the
     upper left and runs the leaves down across the tear. Rotation only, no
     scaleX: the mirror is what swaps stem and leaves end for end, and here the
     rotation alone already lands them the right way round.

     It was rotate(8deg) for one revision, which is near enough the drawing's
     natural orientation and therefore had the stem entering from the BOTTOM
     right with the leaves climbing up out of the paper — the exact opposite of
     what this piece is for.

     ON THE SHARED SELECTOR, like every other declaration here. A transform that
     differs between the halves breaks the crossover outright. */
  transform: rotate(170deg);
}

/* ---------- Narrow widths, 2026-08-24 ----------
   THE DESKTOP VALUES DO NOT DEGRADE — they fail outright, and only measurement
   showed it. --oto-hero-drop is 280px flat while the drawing scales with the
   viewport, so on a phone the whole sprig slides below the tear it is supposed
   to straddle: measured at 375px the topmost ink sat 168px BELOW the hero's
   bottom edge, meaning there was no white half at all and the crossover was
   just a teal vine in the cream. It also ran straight through "You just know
   you want to feel more like you." at every width from 375 to 760.

   Solved by sweeping left / width / drop against painted alpha and keeping only
   combinations with zero collisions and real ink on BOTH sides of the tear.
   Measured at 375 / 430 / 600 / 760: white 118/146/234/318, teal 62/60/54/48,
   no collisions anywhere, ~6.6% of the drawing running off the left edge.

   THE DROP STAYS IN PIXELS, and the teal tail therefore shortens toward 760.
   That is a considered trade, not an oversight. A vw-based drop holds the split
   at a constant 34% teal — which is what you want — but at 600 and 760 it walks
   the sprig into the copy, 36 and 64 ink pixels of overlap. Searched the wide
   end for a way out (three left offsets x two widths x three drops, wanting
   teal >= 75px) and there is none: at 760 the copy's left edge is at x=68, so
   there is no corridor to put a longer tail in. A short teal run beats a sprig
   crossing the words.

   ONE RULE ON THE SHARED SELECTOR, as everywhere else here. Splitting these
   across the two halves is what breaks a crossover. */
@media (max-width: 1100px) {
  .oto-tear-white,
  .oto-tear-teal {
    /* 760 -> 1000 -> 1100, and each move was measured rather than assumed.
       Widening the block does not "fix" anything by itself — it MOVES THE SEAM,
       and the seam is where the trouble is: at 761 and again at 1001 the
       desktop geometry put the sprig straight back through the copy the moment
       this rule stopped applying. 1100 is where the desktop values measure
       clean on their own, so the two rules finally meet without a gap.

       THE VALUES BELOW ARE A SOLUTION ACROSS THE WHOLE BAND, not a fix for one
       width. Solved by sweeping left x width x drop and keeping only
       combinations with zero text collisions AND real ink on both sides of the
       tear at 375, 430, 600, 760, 900, 1000 and 1100 simultaneously — 15 of 36
       survived. 430 is why that mattered: it failed on its own while 375 and
       600 both passed, because the hero tagline wraps differently there. Any
       future change here has to clear the whole band, not the width in front
       of you.

       Worst case across those widths: 62px of white above the tear, 48px of
       teal below. Nothing else lives in this block, so widening it only moves
       the two halves and their clip. */
    --oto-hero-drop: 75px;
    left: -12%;
    width: 27%;
  }

  /* The clip comes down with the drawing. At 375px the desktop 375px clip runs
     PAST the bottom of .oto-open, which puts a live clipping box over the start
     of the next section for no reason — measured -26px at 600 and -52px at 760.
     The foot only needs ~140px of room here. */
  .oto-tear-clip { --oto-clip-h: 200px; }
}

/* ---------- Phones: the hero vine, sized to the sprig — 2026-08-26 ----------
   Lauren, across four goes on the phone view: "those leaves need to be bigger",
   "move it to the right more", "i want it to match the size of the leaves over what
   to expect section", "they still look smaller though", "and i would like it more
   right."

   THE REFERENCE IS THE SPRIG, NOT THE CORNER LEAF, and that is what a first pass got
   wrong. `.oto-corner-leaf` sits at the BOTTOM of What to Expect; the leaves OVER it
   are `.oto-sprig`, coming down into the card's top edge. Matching the corner leaf
   was easy — same file, so 140px matched exactly — and Lauren still read the hero
   vine as smaller, because she was not comparing against it.

   AND THE TWO DRAWINGS ARE NOT DRAWN AT ONE SCALE. leaf-vine-teal / -white (560x811,
   this piece) is a finer drawing than leaf-vine-sage (560x1004, the sprig): measured
   on the assets themselves, horizontal ink runs come out at a median of 5px against
   7, and 17 against 20 at the 97th percentile — the sage is drawn roughly 18% heavier
   with fewer, fuller leaves. So EQUAL WIDTH IS NOT EQUAL LEAF SIZE between these two,
   and matching by element width is only valid within one drawing.

   180px = the sprig's 150 x that 1.18. Checked by rendering sage@150 beside teal@180
   and comparing the leaves rather than the numbers.

   ---- The tagline's measure is part of this rule ----

   `.oto-hero .script` is capped here, and it is not a separate change. This piece is
   anchored from its BOTTOM, so size grows it UPWARD; at rotate(170deg) the end that
   fans RIGHT is the leafy one. Bigger and further right are therefore ONE constraint
   pushing the same leaves at the same obstacle — the hero's tagline — which is why
   three passes each bought one at the cost of the other.

   At 30rem that tagline falls to TWO nearly full-width lines at 430 (x18-412 on the
   last one), leaving a corridor 151px tall and nothing clear either side of it. A
   180px vine paints 220px tall, so at that measure it simply does not fit: at 430 the
   only clean cell in a 4x4 sweep of width x left was the old 140 at -90.

   At 24rem the same tagline sets as THREE balanced lines — which is what it already
   does at 390 — and the longest of them stops at x348, opening a clear column from
   x0 to x94 running the full height of the block. That column is the room the vine
   needed. 24rem is 384px, so nothing at or below ~390 rewraps: this changes 430 and
   leaves the widths it already suited alone. It is better type either way; a script
   face reads worse in two long lines than in three short ones, and 390 and 430 now
   wrap the same.

   ---- Verification ----

   Solved against painted alpha at 320 / 360 / 390 / 430 / 440 with the cap in place,
   keeping only combinations with zero text collisions AND real ink on both sides of
   the tear at every width. 180 / -90 / 92 is the only cell clean at all five; -80
   fails 390 by 17px and -70 by 58.

   AND `left` GOING BACK TO -90 IS NOT THE VINE GOING BACK LEFT. The drawing is 40px
   wider, so at the same offset its painted right edge moves from x60 to x103 — 43px
   further onto the page than the 140px version sat. Left is where the drawing starts,
   not where it reads.

   PX, NOT PERCENTAGES, for both offsets. A percentage renders a different drawing at
   every width, so it can never match a piece sized in px — and a percentage `left`
   against a fixed-size drawing is the drift failure the mobile-anchoring notes
   record.

   440px, NOT 560. At 480 the corridor is different again; 440 clears every phone in
   use, 430 being the widest common one. Above it the ≤1100 rule takes over unchanged,
   tagline included. */
@media (max-width: 440px) {
  /* NOT COSMETIC — see above. The three-line wrap this forces is what makes room for
     the vine, so this and the width below are one setting. Widen it and the vine
     paints into the copy at 430. */
  .oto-hero .script { max-width: 24rem; }

  .oto-tear-white,
  .oto-tear-teal {
    /* Centres the drawing in that corridor rather than hanging it from the top. At
       86 it still paints 9px into the tagline at 390; at 98 the foot reaches
       .oto-open's first line. Two values wide — re-measure it with the width, not
       after. */
    --oto-hero-drop: 88px;
    left: -110px;
    /* 180 = .oto-sprig's 150 x the 1.18 the two drawings differ by. If the sprig is
       ever resized, this follows it — they are matched by eye, not by file. */
    width: 180px;
  }
}

/* THE SIZE HOLDS AT 320, THE POSITION GIVES. A 180px drawing paints 212px wide at
   the tagline's height, and on a 320px page a centred tagline cannot clear that
   however narrow its measure — the sums do not work, not the wrap. So rather than
   shrink the vine on the one width where it would visibly stop matching the sprig,
   it slides another 20px off the left edge. Measured at 320x568: clean at -130,
   53 painted pixels on the tagline at -110.

   340px, so it catches 320 and nothing anyone carries — 360 is the narrowest phone
   in real use and it is clean on the rule above. */
@media (max-width: 340px) {
  .oto-tear-white,
  .oto-tear-teal { left: -130px; }
}

/* Both halves anchor from their BOTTOM to the same page line. White's element
   bottom sits --oto-hero-drop below the hero's bottom edge; teal's is the same
   point, reached by cancelling the clip's height and its negative top. Anchoring
   from the bottom is what keeps them locked: a `top` on the teal half would have
   to know the image's rendered height, which is derived from its width and so
   cannot be written here. */
.oto-tear-white { bottom: calc(-1 * var(--oto-hero-drop)); }

.oto-tear-teal {
  bottom: calc(var(--oto-clip-h) - var(--wave-h) - var(--oto-hero-drop));
}

/* ---------- 3 + 4 · The panel pair ----------
   Two torn scraps side by side, offset, lapping — the home page's own
   construction rather than a new one. `.believe-for` lays What I Believe and
   Who Lumi Libra Is For out exactly this way and `.about-twocol` repeats it on
   About; every value below is theirs, so the three pages read as one system.

   Lauren, 2026-08-23: "bring back the torn pages with lavender and light teal.
   have sections free form, but so they are next to each other instead of these
   straight horizontal sections we have."

   WHAT IT REPLACED. "Joy is a compass." was a full-bleed warm sage-and-gold
   band torn top and bottom, and "This Isn't Just Talking About It" was a blue
   scrap inset in a 1000px wrap — two more horizontal stripes on a page that had
   become almost nothing but stripes. The blue left with them: the hero is this
   page's blue now, and these two carry the lavender and light teal.

   FULL-BLEED, NO `.wrap`. The panels run to both page edges, which is what
   makes them read as torn pages laid on the sheet rather than as cards; their
   own padding holds the measure. Same as both existing pairs.

   `align-items: start`, NOT stretch. They are two scraps at two heights, not a
   row ruled into two cells — and the two panels here differ in length by a long
   way, which is the point rather than a problem. */
.oto-pair {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1.04fr;
  align-items: start;
  padding: 2rem 0 3.5rem;
}

/* The same baked paper the hero and every panel on the site take: the PNG
   carries lightness only, so the colour stays in background-color underneath
   and one file serves all of them. It lands softer on a pale panel than on a
   dark band without any tuning — soft-light's effect falls off as the base
   approaches white.

   The top padding runs over the nominal --space-xl for the reason both existing
   pairs record: the torn top edge bites up to ~42px into the panel, and at the
   plain value the headings cleared it by single digits. */
.oto-panel {
  position: relative;
  background-image: url("../images/art/paper-wash.png");
  background-size: cover;
  background-position: center;
  background-blend-mode: soft-light;
  padding: calc(var(--space-xl) + 1rem) clamp(1.6rem, 2.6vw, 2.8rem) calc(var(--space-xl) + 2rem);
}

/* Tears `a` and `b`. Home's pair takes b and c and About's takes a and c, so
   this pair matches neither — no two panels anywhere on the site carry the same
   edge as their neighbour, and the tile repeats at a fixed width so each panel
   cuts a different part of it anyway.

   z-index descends left to right so the overlap stacks one way. Without it the
   later panel always paints on top and the lapping reads in a single direction
   regardless of which one is meant to be in front. */
/* BOTH PANELS CENTRE, and every section on this page with them. Lauren,
   2026-08-23: "i think this page since it has a lot of lists, the sections
   should be centered." Four of the eight sections are built around a list, and
   a page of left-set blocks with centred headings above them reads as two
   different pages — see `.oto-list` for how the lists themselves stay legible
   inside a centred column. */
.oto-panel { text-align: center; }

.oto-panel-teal {
  background-color: var(--panel-teal);
  --panel-tear: url("../images/art/torn-paper-a.svg");
  margin-top: 0;
  z-index: 2;
}

/* BLUE, not lavender, since 2026-08-24 — Lauren: "change the joy is a compass
   to the blue background we have on the other pages". --panel-blue is the same
   token .who-for and About's .beyond-card already carry, so this is the site's
   existing blue rather than a new one.

   THE CLASS WAS RENAMED WITH IT (.oto-panel-lav -> .oto-panel-blue). A class
   named for a colour it no longer is costs the next person more than the rename
   costs now, and lavender moved to .oto-expect-card in the same edit — leaving
   the old name would have put `-lav` on the blue panel and no `-lav` on the
   lavender one. */
.oto-panel-blue {
  background-color: var(--panel-blue);
  --panel-tear: url("../images/art/torn-paper-b.svg");
  margin-top: 4.5rem;
  margin-left: -3%;
  z-index: 1;
}

/* On colour the headings go navy and the copy to the panel ink, the same
   treatment both existing pairs take. Measured: navy 9.7:1 on the teal and
   8.2:1 on the lavender, ink 6.5 and 5.4. */
.oto-panel .oto-title { color: var(--navy); }
.oto-panel p { color: var(--ink); }
.oto-panel p + p { margin-top: 1.15rem; }

/* The Joy heading keeps the script voice the line has everywhere else on the
   site, at a display size. It sits in the LAVENDER panel since the 2026-08-23
   restructure — `.oto-panel-teal` no longer holds it, so the selector is on the
   class rather than on a panel. */
.oto-joy-title {
  font-family: var(--font-script);
  font-variation-settings: var(--display-vars);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(1.863rem, 3.4vw, 2.7rem);
  line-height: 1.25;
  color: var(--script-blue);
  margin-bottom: 1.6rem;
}

/* --teal-ink, NOT --script-blue, and the panel colour is the reason rather than
   taste. Re-measured on --panel-blue after the 2026-08-24 swap: --script-blue
   falls to 2.98:1 there, which misses even the 3.0 that LARGE text is allowed,
   where --teal-ink holds 3.69:1. The Joy heading renders at 26.5px at its
   smallest — above the 24px large-text threshold at every width — so 3.69
   clears it, but note how little room that leaves: this line cannot take a
   lighter colour, and it cannot be allowed to shrink under 24px. It was 4.06:1
   on the lavender this panel used to be. */
.oto-panel-blue .script { color: var(--teal-ink); }

/* AND THE JOY HEADING ITSELF, which the rule above does NOT reach — `.oto-joy-title`
   is not a `.script`, it just sets --script-blue on itself. That was easy to miss
   and the measurement caught it: on the blue the heading was still --script-blue
   at 2.98:1, under even the 3.0 its size entitles it to, while the rule meant to
   fix exactly this sat one line above matching nothing on the page.

   --navy, 2026-08-24: "change the title to black". It is the site's near-black
   dark ink rather than true #000 — the same colour every other heading on this
   page already takes, and the one Lauren has previously distinguished from black
   by name. 7.45:1 on --panel-blue, against 3.69 for the --teal-ink this replaced
   and 2.98 for the --script-blue before that.

   IT GIVES UP THE SCRIPT'S COLOUR VOICE, deliberately and on her instruction.
   The line keeps the handwriting face; only the colour joins the headings. */
.oto-panel-blue .oto-joy-title { color: var(--navy); }

/* The lapping only works while the two sit side by side. Stacked, a negative
   inline margin just drags the panel off the left edge of the page.

   They still need a real gap. Butted at margin-top: 0 the first panel's torn
   base meets the next one's torn top with no paper showing between, the two
   tears interlock, and the boundary reads as a hard colour change — the torn
   edges look like they have been taken away. Paper between them is what makes a
   tear visible at all. Same value and same reasoning as both existing pairs.

   Wider inline padding for the same reason they take it: the side tear is ~14px
   on a full-width panel and the clamp bottoms out at 1.6rem, which leaves too
   little clearance to the text. */
@media (max-width: 900px) {
  .oto-pair { grid-template-columns: 1fr; padding-bottom: 2rem; }
  .oto-panel-blue { margin-left: 0; margin-top: 3rem; }
  .oto-panel { padding-inline: 2.2rem; }
}

/* ---------- The heart lists ----------
   FOUR OF THEM after the 2026-08-23 restructure, where the page had none: "This
   Could Be for You If…", the Joy prompts, "What Might We Actually Do?" and "You
   Don't Need To…". Lauren: "where you see bullets make those hearts. make them
   coloured hearts."

   ONE MARK, ONE COLOUR VARIABLE. The heart is the site's own list mark — it is
   what `.feeling-list` on the Club and both panel lists on the home page use —
   and every one of those sets it in a single `--bullet-blue`. These take a
   per-section `--heart` instead, so each list can carry its own colour without
   a second rule. Set it on the section, not the list.

   The values below are a FIRST PASS chosen to be visible on each list's own
   ground and distinct from its neighbours, not a decision — she asked to see
   where they fall before picking. Change the `--heart` on each section. */
/* CENTRED ROWS WITH THE HEART TRAVELLING WITH ITS LINE. Lauren, 2026-08-23:
   "center all the text on this page because of how the layout is i think it
   looks better."

   THE MARK HAD TO STOP BEING ABSOLUTE FOR THAT TO WORK, and this is the whole
   trick. Everywhere else on the site a heart list hangs its mark at `left: 0`
   of the item with the text indented past it — that gives a clean hanging
   indent and it is why the home page's panel lists are set left. Centre the
   text under that construction and the marks stay pinned to the left edge
   while the sentences drift to the middle: six hearts in a column with nothing
   next to them, which reads as a rendering fault. It WAS one, briefly, on the
   teal panel.

   Inline `::before` with a right margin instead, so the heart is simply the
   first thing on the line and centres with it. The cost is the hanging indent:
   a wrapped item's second line starts under the heart rather than under the
   first word. On centred text that is invisible, because neither line starts at
   a shared left edge anyway. */
.oto-list {
  list-style: none;
  max-width: 32rem;
  margin: 1.4rem auto 0;
  text-align: center;
}

.oto-list li {
  margin-bottom: 0.85rem;
  font-size: var(--t-base);
  line-height: 1.65;
  color: var(--ink);
}

.oto-list li::before {
  content: "\2665";
  margin-right: 0.5em;
  color: var(--heart, var(--bullet-blue));
  font-size: 0.92em;
}

/* ---------- The four hearts, one colour each ----------
   Set on the SECTION, so each is one value to change:

     This Could Be for You If…   on --panel-teal   -> plum
     What Might We Actually Do?  on the photograph -> blue
     You Don't Need To…          on bare paper     -> teal

   THREE, NOT FOUR, since the Joy prompts became prose on 2026-08-23 — that
   panel carries no list and no heart at all now.

   THAT LIST WENT TEAL AND THEN BLUE, 2026-08-23. It was gold, then both paper
   lists went teal ("make teal on the white for the hearts"), then only this one
   ("sorry the ones under what might we actually do"), then blue ("you can make
   the teal ones you just did, blue"). Ending on blue also means no two lists on
   this page share a colour, and none of them repeats the teal of the panel
   above.

   --club-playlist for the blue, which is the Club's playlist-patch colour and
   the only real blue in this palette that is dark enough to read as a mark on
   white — the others (--panel-blue, --butterfly-blue, --periwinkle) are all
   pale panel fills and would disappear on the page ground. It was derived to
   clear 4.5:1 on paper, so it is safe at this size. */
.oto-panel-teal { --heart: var(--blob-purple); }
.oto-panel-blue { --heart: var(--blob-teal); }
.oto-do         { --heart: var(--club-playlist); }
/* TEAL, 2026-08-25 — Lauren: "change the hearts in you dont need to to teal".
   It has now been gold, teal, blue, pink and teal again.

   --blob-teal, NOT --teal or --teal-ink. The other two hearts on this page are
   both watercolour-patch colours (--blob-plum and --club-playlist), so the patch
   teal is the one that belongs to the same set; --teal is the button/accent
   colour and would put an interface colour in a decorative mark.

   Measured on the ground it actually paints on rather than on the token: 3.9:1,
   which clears the 3.0 a non-text graphical mark is held to. It is also distinct
   from BOTH teals it sits between — the pale --panel-teal panel above and the
   dark band below — so the section reads as a step between them rather than as
   an echo of either. */
.oto-neednt     { --heart: var(--blob-teal); }

/* TWO COLUMNS for the two short-item lists. "Move." / "Write." / "Play." are one
   word each: stacked they make a tall thin ribbon down the middle of the page,
   and the whole point of those lists is that they read as a spread of
   possibilities at a glance.

   `columns` rather than a grid, so the items flow to balance themselves as the
   count changes — six items and eight items both split evenly without a rule
   per list. `break-inside: avoid` stops a wrapped item splitting across the
   gap, which is the one thing CSS columns do badly here. */
.oto-list-2col {
  columns: 2;
  column-gap: clamp(1.4rem, 4vw, 3rem);
  max-width: 34rem;
  margin-inline: auto;
}

.oto-list-2col li { break-inside: avoid; }

/* ---------- 5 + 6 · "What Might We Actually Do?" / "You Don't Need To…" ------
   Bare paper, and the same shape twice on purpose: one names what you might do,
   the other what you do not have to be, and they are written as a matched pair.
   Treating them identically is what makes them read as one. */
/* ---------- "What Might We Actually Do?" — a photograph band, 2026-08-24 ----
   Lauren: "the middle section, what might we actually do, i want to put this
   photo as the background, like we did for the hero."

   HER PHOTO, NOT MIRRORED. She asked for a horizontal flip and then corrected
   it — "oh wait i want the butterfly to be on the right" — and the butterfly is
   already on the right in the original, so the flip is exactly what would move
   it to the left. No transform here and none baked into the asset.

   The crop was chosen off contact sheets rather than guessed, and it was tried
   both ways. y=1000 of the 3024x4032 source is the one in use: the big yellow
   flower whole at the left, foliage across the middle, and the butterfly at the
   right with its wing running off the frame edge. A second pass cut y=450
   instead, which holds the WHOLE butterfly, wing through tails — Lauren asked
   for it ("maybe crop the pic so more of the butterfly is in it"), looked at
   it, and preferred the original. Both are one line apart if it comes up again:
   y=1000/`center 54%` against y=450/`center 50%`.

   Only about 5% is cropped vertically at this aspect, so there is very little
   play in that background-position — re-crop the ASSET to reframe this, do not
   expect the percentage to do it.

   CONSTRUCTION IS .oto-hero's, values re-derived: cover photograph, a vertical
   gradient scrim over it, and a teal frosted layer on ::before. The scrim is
   HEAVIER than the hero's (0.52/0.34 against 0.42/0.10) and that is not taste —
   the hero's type sits on an unbroken run of sky, and this one sits on yellow
   flowers and sunlit green, which is the brightest ground on the site. See the
   contrast note on the copy below.

   TORN TOP AND BOTTOM, which .oto-hero does not need. This is a mid-page band
   between two paper sections, so it takes .oto-deeper's grammar rather than the
   hero's: the same `--section + --wave-h` padding, so the copy clears both
   tears instead of sitting under them. */
.oto-do {
  position: relative;
  /* Lauren, 2026-08-24: "can we also extend the edges of the photos on both top
     and bottom". The extra 3.5rem each side is photograph, not white space —
     the card is a fixed height, so all this padding does is show more picture
     above and below it. It is on top of the `--section + --wave-h` that
     .oto-deeper's grammar already requires, which is what keeps the copy clear
     of both torn edges. */
  padding:
    calc(var(--section) + var(--wave-h) + 3.5rem) 0
    calc(var(--section) + var(--wave-h) + 3.5rem - 1rem);
  /* `clip`, NOT `hidden`, and it is load-bearing for the phone pinning at the
     end of this section. `overflow: hidden` makes an element a SCROLL CONTAINER
     — a scrollport that cannot actually be scrolled — and
     `animation-timeline: view()` resolves against the subject's nearest ancestor
     scroll container. With `hidden` the timeline sits frozen and the picture
     tracks the BAND instead of the window, which looks exactly like the effect
     not being applied at all. Same note as on `.home-joy` and `.club-quote`. */
  overflow: hidden;
  overflow: clip;
  background:
    linear-gradient(180deg,
      rgba(17, 78, 88, 0.30) 0%,
      rgba(17, 78, 88, 0.12) 30%,
      rgba(17, 78, 88, 0.12) 68%,
      rgba(17, 78, 88, 0.34) 100%),
    url("../images/oto-do-flowers.webp") center 54% / cover no-repeat;
}

/* ---------- The pinned photograph, 2026-08-25 ---------- The 1:1 page's turn at
   the effect the two home/about bands have. IT IS HERE RATHER THAN ON THE HERO,
   and that was tried first: `fixed` sizes the background to the WINDOW, the hero
   photograph is 3024x1470 with no taller original to re-cut from, and a window
   is much squarer than the band — so it took the picture from 93% of its width
   to 69% and cut the wingtip off. Lauren: "i dont like the hero its too zoomed
   in now. what if we did it to middle section on that page instead". That block
   is gone; the hero is exactly as it was.

   THIS BAND HAS THE ROOM THE HERO DIDN'T. Its source is a full 3024x4032
   portrait, so the crop could simply be opened out:

     images-original/oto-do-flowers-src.HEIC
                    ->  crop (0, 691, 3024, 2821)    3024x2130, aspect 1.42
                    ->  resize 2400x1690
                    ->  WEBP quality 76              160KB

   No brightness and no blur, matching the shipped file — fitted against it, the
   2400x1200 asset is crop y1000-2512 of the same source at brightness 0.9995,
   and this is that crop with 309 rows added above and below. At 1280x900 `cover`
   fits it by WIDTH, so 100% of the picture survives with about one pixel of
   vertical overflow.

   NO SCRIM CHANGE, and for once that needs no measurement to justify: every word
   in this section sits on `.oto-do-card`, an opaque torn-paper panel. The long
   note in the markup records why — cream type straight on this picture failed on
   8 of 10 lines and the scrim that fixed it threw away 64% of the photograph, so
   the copy moved onto paper instead. Nothing here reverses out, so nothing here
   depends on what the picture is doing behind it.

   POINTER-GATED, as everywhere else — see the long note at `.home-joy::before`. */
@media (min-width: 761px) and (hover: hover) and (pointer: fine) {
  /* A FIXED LAYER, NOT A FIXED BACKGROUND — 2026-08-26, the same swap as
     `.home-joy::before`; the reasoning lives there in full. Short version:
     `background-attachment: fixed` repaints on the main thread every frame and
     lags the copy moving over it, which is the shakiness Lauren reported; a
     `position: fixed` box has identical geometry and the compositor simply does
     not move it. `clip-path` is what holds it inside the band — `overflow: clip`
     cannot clip a fixed descendant — and it must not be a transform or a filter,
     which would make the section a containing block and un-fix the layer.

     THE SCRIM HAD TO COME OFF THE SECTION with it. It was the first layer of the
     same `background` shorthand, which is what guaranteed it painted above the
     picture; a pseudo-element always paints above its element's own background,
     so once the picture is a pseudo the scrim cannot stay where it was. It moves
     to ::after at the band's size — the shape is byte-for-byte the gradient that
     was measured for this band, only its host changed. */
  /* THIS BAND TAKES THE OTHER PSEUDO, and that is forced rather than chosen.
     `.oto-do::before` is already spoken for — it is the flat teal veil at
     z-index 0 — so the picture goes on ::after, which paints LATER. `z-index: -1`
     is what puts it back underneath, and `isolation: isolate` is what keeps a
     negative index inside this section instead of letting it fall behind the
     page. The veil and the band's gradient then share ::before as two layers,
     veil first, exactly the way `.home-joy::after` holds its pair. */
  .oto-do {
    clip-path: inset(0);
    isolation: isolate;
    background-image: none;
  }

  .oto-do::before {
    background:
      linear-gradient(rgba(20, 86, 94, 0.10), rgba(20, 86, 94, 0.10)),
      linear-gradient(180deg,
        rgba(17, 78, 88, 0.30) 0%,
        rgba(17, 78, 88, 0.12) 30%,
        rgba(17, 78, 88, 0.12) 68%,
        rgba(17, 78, 88, 0.34) 100%);
  }

  .oto-do::after {
    content: "";
    position: fixed;
    inset: 0;
    z-index: -1;
    background: url("../images/oto-do-flowers-wide.webp") center 50% / cover no-repeat;
  }
}

/* Teal frosted-glass layer, the same one .oto-hero and About use. It is doing
   more work here than on the hero: the blur softens the flower detail directly
   under the copy, which is what stops busy edges reading through the type. */
/* MUCH LIGHTER THAN THE HERO'S NOW, and barely a scrim at all. It was doing
   legibility work while the copy sat on the photograph; the card took that job,
   so all this has left to do is tie the picture to the site's teal and keep the
   torn edges from reading as a hole cut in the page. The blur is gone with it —
   it existed to soften flower detail under the type, and there is no type on the
   photograph any more. */
.oto-do::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  background: rgba(20, 86, 94, 0.10);
  pointer-events: none;
}

.oto-do .wrap { position: relative; z-index: 1; }

/* THE CARD. Same object as About's panels and the club card — a paper colour
   with paper-wash.png blended over it in soft-light, masked by .torn-paper — so
   the section reads as the site rather than as a photo with a box on it.

    FROSTED WHITE AND TRANSLUCENT, 2026-08-24. It was opaque --cream-accent for a
   revision: "i dont love the cream background", then "could we make them
   slightly transparent maybe also". Dark teal was tried on the way and ruled
   out by her outright.

   72% white with an 8px backdrop blur. The photograph reads through as soft
   colour — yellow warming the left edge, green through the right — without any
   detail sharp enough to fight the type.

   THE BLUR IS NOT LOAD-BEARING FOR LEGIBILITY, which is why there is no
   @supports branch. Measured both ways against the actual photo behind the
   card: 5.23:1 worst-case body contrast with the blur, 5.17:1 without it. A
   browser that ignores backdrop-filter gets a flat 72% white card that still
   clears AA with room, so the fallback needs no separate value.

   Pale --panel-teal at 80% was the other candidate and measured 4.45:1 — just
   under AA, set by the bright yellow flower edge under the card's left side.
   It would have needed 88% to be safe, at which point it is barely translucent.
   Note what that says generally: with a translucent card the contrast floor is
   wherever the BRIGHTEST thing behind it happens to be, so it has to be
   measured across the whole panel and not sampled once.

   NO COLOUR OVERRIDES ON THE TYPE, which is the point of the whole change. The
   copy is on paper, so `.oto-title` and the paragraphs keep the navy they have
   everywhere else on the page, and `.oto-neednt` — which shares the
   `.oto-do-copy` class and stays on paper — needs no scoping to protect it. */
.oto-do-card {
  --panel-tear: url("../images/art/torn-paper-c.svg");
  /* 46rem -> 37rem, 2026-08-24: "can we make the box smaller". It is a measure
     change as much as a size one — at 46rem the copy ran to the card's own
     comfortable line length and the card was doing nothing but framing it,
     where at 37rem the paper reads as an object sitting ON the photograph and
     the picture keeps its left and right thirds. The padding came in with it,
     or a narrower card just means more white space and the same measure. */
  width: min(37rem, 100%);
  margin-inline: auto;
  background-color: rgba(255, 255, 255, 0.72);
  -webkit-backdrop-filter: blur(8px);
          backdrop-filter: blur(8px);
  padding: clamp(1.9rem, 4vw, 2.8rem) clamp(1.6rem, 3.2vw, 2.4rem);
}

/* The narrow crop, the same job oto-hero-butterfly-tall.webp does: a phone gets
   a composed squarer frame instead of a zoomed slice out of the wide one, which
   at this aspect would have been mostly stem. */
@media (max-width: 760px) {
  .oto-do {
    background:
      linear-gradient(180deg,
        rgba(17, 78, 88, 0.30) 0%,
        rgba(17, 78, 88, 0.14) 30%,
        rgba(17, 78, 88, 0.14) 68%,
        rgba(17, 78, 88, 0.34) 100%),
      url("../images/oto-do-flowers-phone.webp") center 50% / cover no-repeat;
  }

  /* THE CARD IS CONDENSED HERE, 2026-08-25. Lauren, on a phone: "both of those
     have the text boxes very large and covering the whole photo... is there a
     way where we can make the text box smaller and moved so we can see more of
     the pics". This card was 750px tall in a 1050px band — 71% of it — and this
     section's copy is six paragraphs, so it is the worst offender on the site.

     NO TYPE GETS SMALLER; see [[lumilibra-type-legibility]]. Everything below is
     spacing. Line-height is the big one again: the card holds around twenty
     lines at this width, so 1.75 -> 1.45 is worth roughly 110px on its own.

     A NEW CROP CAME WITH IT. The butterfly sits at the FAR RIGHT of this
     photograph and the big yellow flower at the far left, and no phone-shaped
     slice can hold both — `cover` was showing a 32% core of green with neither
     in it. images/oto-do-flowers-phone.webp is x1100-3024 of the original at
     full height, 1924x4032, which is almost exactly a phone band's shape: 97% of
     it survives, and the butterfly is in the top third where the card is not. */
  /* THE BAND GETS TALLER, NOT SHORTER, and that was worth getting wrong once to
     learn. Trimming the padding to "tighten" the section shrank the picture with
     it — the card is a fixed height, so the padding IS the photograph, and at
     -1rem the card went from 68% of the band to 79%. Under the pinned layer the
     band's height does not affect the crop at all (the picture is sized to the
     window), so every pixel added here is pure photograph. */
  .oto-do {
    padding:
      calc(var(--section) + var(--wave-h) + 2.5rem) 0
      calc(var(--section) + var(--wave-h) + 2.5rem);
  }

  .oto-do-card {
    padding: 1.5rem clamp(1rem, 4.2vw, 1.5rem) 1.6rem;
  }
  .oto-do-copy p,
  .oto-do-copy .oto-title { line-height: 1.45; }
  .oto-do-copy p { margin-bottom: 0.5rem; }
  .oto-do-copy .oto-title { margin-bottom: 0.6rem; }

  /* ---------- The phone pinning, for this band ---------- The shared
     `.pin-photo` rules are much earlier in the file; only the band-specific part
     is here, and it has to be HERE rather than beside them because `.oto-do` is
     declared just above at the same specificity and source order would otherwise
     win. That cost a round: the rules were written up there, computed styles
     came back untouched, and it read as the effect not working.

     PHOTOGRAPH AND SCRIM ARE BOTH ON THE SECTION here, with a flat teal veil on
     ::before over them. The pinned layer is a real child, so it would paint
     above both — the picture would land on top of its own wash. So the section
     paints nothing, and the veil and the gradient move into ::before together,
     in that order: the veil sat on top of the gradient before and still does.

     NO WASH CHANGE, and for once none was needed: every word in this section is
     on a 72% white card, which measures much the same whatever is behind it.
     Pinned, the copy comes back 6.67:1 against the 4.5 it needs — and the
     picture GAINS, 32% of its width showing against 40%, because a window is
     squarer than this unusually tall band. */
  @supports (animation-timeline: view()) {
    @media (prefers-reduced-motion: no-preference) {
      .oto-do {
        --pin-img: url("../images/oto-do-flowers-phone.webp");
        background-image: none;
      }

      .oto-do::before {
        z-index: 1;
        background:
          linear-gradient(rgba(20, 86, 94, 0.10), rgba(20, 86, 94, 0.10)),
          linear-gradient(180deg,
            rgba(17, 78, 88, 0.30) 0%,
            rgba(17, 78, 88, 0.12) 30%,
            rgba(17, 78, 88, 0.12) 68%,
            rgba(17, 78, 88, 0.34) 100%);
      }

      .oto-do .wrap { z-index: 2; }
    }
  }
}
.oto-neednt { position: relative; padding: calc(var(--section) - 1rem) 0 var(--section); }

.oto-do-copy {
  max-width: 38rem;
  margin-inline: auto;
  text-align: center;
}

.oto-do-copy .oto-title { margin-bottom: 1.4rem; }
.oto-do-copy > p + p { margin-top: 1.1rem; }
.oto-do-copy .oto-list + p { margin-top: 1.8rem; }

/* ---------- 7 · "There's Something Deeper Underneath All the Fun" ----------
   The page's one dark moment and its spine. Removed and restored twice across
   2026-08-23 — once folded into "Come As You Are", once retitled "There's More
   to It Than Just Having Fun" — and back now under its original heading.
   Without it the whole lower half of the page is pale panels and bare paper,
   which is the argument for keeping it if it is questioned again.

   Built like About's `.bg-teal`: baked paper blended soft-light over uneven
   radial pools, torn top AND bottom so it floats, copy reversed out. */
.oto-deeper {
  position: relative;
  padding: calc(var(--section) + var(--wave-h)) 0;
  background:
    url("../images/art/paper-wash.png"),
    radial-gradient(ellipse 46% 52% at 10% 10%, rgba(255, 255, 255, 0.18), transparent 66%),
    radial-gradient(ellipse 40% 46% at 88% 84%, rgba(255, 255, 255, 0.14), transparent 68%),
    radial-gradient(ellipse 38% 42% at 74% 4%,  rgba(18, 74, 80, 0.34), transparent 70%),
    linear-gradient(158deg, #2E7E7C 0%, #1C6469 100%);
  background-size: cover, auto, auto, auto, auto;
  background-blend-mode: soft-light, normal, normal, normal, normal;
}

.oto-deeper .wrap { position: relative; z-index: 1; }

.oto-deeper-copy {
  max-width: 40rem;
  margin-inline: auto;
  text-align: center;
}

.oto-deeper-copy .oto-title { color: var(--cream); margin-bottom: 1.5rem; }
.oto-deeper-copy p { color: rgba(250, 250, 248, 0.94); }
.oto-deeper-copy p + p { margin-top: 1.15rem; }

/* ---------- Sage leaves in the page's bottom-right paper ---------- 2026-08-25
   Lauren: "these will be sage, and the stem will be on the right, leaves down to
   the left."

   -110deg IS EXACTLY THAT, and it is the drawing's own geometry rather than a
   number to taste. leaf-vine-sage has its bare stem at the foot, bottom-right, with
   the leaves fanning up off it; at -110 the foot swings up to the RIGHT and the
   leafy end falls away to the left and below. Rotation only — a mirror would swap
   the ends and put the bare stalk out in the margin.

   IT IS THE SAME DRAWING AND ANGLE AS `.oto-sprig` UP IN THE TEAL BAND, which is
   the one thing here that needed a second look. That piece has since been tilted to
   -101 and sits at 230px, so the two differ in both angle and size, and they are
   ~1700px apart. That is a recurring motif rather than a repeat — but if either is
   ever changed toward the other, this is the pair to check.

   200px, UNDER THE SITE'S 230 FOR A SAGE SEGMENT. The pocket is the binding
   constraint: the note is only 179px tall and the footer's torn top cuts the
   drawing off at y5180, so at 230 the visible portion would be a smaller fraction of
   a bigger drawing rather than more leaf on the page. */
.oto-note-leaf {
  /* 82.8% of the full-bleed section. Derived: the rotated box is 405 x 311 and wants
     its centre at x1160 — far enough right that its leafy end clears the note's copy
     at x990, far enough left that the stem does not vanish off the page. */
  left: 82.8%;
  /* NEGATIVE, so the drawing starts above this section. The note is 179px tall and
     the drawing is 311; it has to begin in the paper above and end behind the footer
     below, which is the whole gesture.

     -65 -> -95, 2026-08-25: "you can move it up a little." Painted y4932-5214, so it
     now starts level with the CTA card's lower third and still runs 34px behind the
     footer's torn edge.

     THE CARD IS NOT THE CEILING, which is worth knowing before the next nudge. The
     navy card ends at x1000 and this drawing's leftmost ink is at x1014, so the two
     never meet however far up it goes — the real limit is that the further it rises,
     the less of its foot the footer takes, and at about -160 it stops passing behind
     the band at all and just sits in the gutter. */
  top: -95px;
  width: min(200px, 15.7vw);
  /* 0.5, the site's value for a coloured leaf on white paper — the same as
     `.vine-seg`, `.twocol-top-leaf` and About's `.beyond-corner-sage`. */
  opacity: 0.5;
  transform: rotate(-110deg);
  pointer-events: none;
}

/* 15.7vw IS 61px ON A PHONE, which is the min() collapse rather than a decision —
   the drawing had quietly become a third of its size and read as a smudge. And the
   desktop placement does not survive the stack either: it is derived from the navy
   CTA card ending at x1000 with the leaf's ink starting at x1014, and on a phone that
   card is the full width of the page, so there is no gutter beside it to come down.

   SO IT MOVES TO THE CARD'S TORN BOTTOM-RIGHT CORNER, which is the one place here
   that still has the shape the piece wants: the mask cuts the navy away diagonally,
   so a drawing entering from the right page edge crosses card, torn edge and paper in
   that order. The heading sits at x123-267 and the copy starts at y6894, so the
   pocket is everything right of x269 and above 6888.

   105px, AND THE POCKET IS WHAT SETS IT rather than the phone grammar's 110-150. At
   105 the painted leaf runs x269-390 by y6725-6888 — 6px clear of the copy below and
   clear of "A Quick Note" to its left. Bigger and it reaches one or the other.

   THE FOOTER GESTURE IS GONE, deliberately. On desktop this drawing ends behind the
   footer's torn top, which is most of why it is here; on a phone the note's copy
   fills the whole band between the card and the footer and there is no column left
   to run down. Sitting on the card's corner is the honest substitute — same entry
   from the page edge, same crossing of a torn edge, against the edge that exists. */
/* ---------- The note's sprig, moved under the copy — 2026-08-26 ----------
   Lauren: "the sage leaves in a quick note, lets move them under the text and push
   to the left so more are showing."

   THE DESKTOP GESTURE DOES NOT SURVIVE THE STACK. At 1280 this comes down the right
   margin beside the note's copy and ends behind the footer's torn top — it works
   because the navy CTA card above ends at x1000 and the drawing's ink starts at
   x1014, so there is a gutter to come down. On a phone that card is the full width
   of the page and there is no gutter, so the piece has to find a different pocket.

   THE POCKET IS THE BAND UNDER THE COPY, and it is small: the last line's ink ends
   at y7040 and the footer's own mask starts painting dark at about y7130 in this
   drawing's x range, so there are roughly 90px of clear paper. The drawing is 211px
   tall. Most of it goes behind the footer, which is the desktop gesture intact —
   just more of it than at 1280.

   AND IT LIES DOWN. Lauren: "move them horizontal so they are resting under the
   text." Upright in a 90px band, a 211px-tall drawing can only ever show a slice of
   itself; laid along the band it shows almost all of it. Measured the same way each
   time — painted ink that is on the page AND above the footer's mask AND clear of
   the copy — the three versions go 261 -> 931 -> 2263. Turning it did more for this
   piece than moving or resizing it did.

   -74deg, READ OFF THE DRAWING. Sampling leaf-vine-sage's ink centroid in eight
   bands down its height gives a spine running from (100,72) at the leafy tip to
   (342,921) at the bare stem — tip-to-stem at 74.09deg, so stem-to-tip is -105.91.
   Rotating by -74 lands that at 180deg: stem to the RIGHT, leaves running LEFT,
   which is the direction that matters because the piece enters from the right page
   edge. RE-DERIVE IT if the asset changes; do not nudge it by eye, and mind that the
   drawing is an L — its lower fifth bends away from the spine, which is the part
   that tucks under the footer.

   The tail still runs behind the footer's torn top, so the desktop gesture survives
   the move — but only just. Lauren, 2026-08-26: "move them up just a little", and
   -101 -> -91 takes the ink hidden under the footer from 884 painted pixels to 343
   while the visible count goes 2263 -> 2804.

   -94, AND THE LAST 3px OF THAT ARE 430's. Centred, the drawing's upper edge sits
   under the middle of the paragraph rather than off to one side, so it meets the
   copy where the lines are longest: at -91 it painted 4 pixels into the last line at
   430 while measuring clean at 320 and 390. Small enough to miss by eye, which is
   why this is swept at three widths rather than tuned at one.

   THERE IS STILL MORE ROOM ABOVE THAN THE BOXES SUGGEST — the drawing's top threads
   between the right-hand ends of the last two copy lines, which stop at x273 and
   x362. Check painted alpha, not line boxes, before assuming otherwise. */
@media (max-width: 760px) {
  .oto-note-leaf {
    /* BOTH AXES ANCHORED TO EDGES THAT DO NOT MOVE, because neither of the obvious
       ones is stable. A `top` percentage or px from the section's own top drifts
       with the copy — that paragraph wraps to five lines at 390 and six at 320 — and
       a `left` percentage against a fixed-width drawing lands it somewhere different
       at every width, which is the drift failure the mobile-anchoring notes record.

       The footer's edge is the section's bottom and does not move relative to it, so
       the vertical anchors there; the page's right edge is what the drawing enters
       from, so the horizontal anchors there. -152 / 53 reproduce the placement solved
       at 390 — painted x153-382 by y7019-7230 — at every phone width. */
    top: auto;
    bottom: -94px;
    /* CENTRED ON THE PAGE, so the vine cups the paragraph rather than entering from
       one side. Lauren: "lets center it so its almost holding that text. creating
       this nice little scoop at the bottom."

       `right` IN PX CANNOT DO THIS. It held the drawing a fixed distance from the
       right edge, which is correct for a piece entering from the margin and wrong
       for one that has to stay centred — at 80px it sat 43px right of centre at 390
       and further at every wider phone.

       `translateX(-50%)` after the rotate, in that order: the rotation happens first
       and the translate then shifts the finished drawing half its border-box width
       (75px) left, in screen axes. Same idiom and same order trap as
       `.oto-neednt-bfly`. The painted area lands within 3px of the box centre, so
       centring the box centres the drawing. */
    left: 50%;
    right: auto;
    /* THE ROTATION MOVES THE ANCHORS. Turning the drawing changes its bounding box,
       so the offsets had to be re-derived with it — at the upright values the
       horizontal sprig sat 51px too low and 27px too far right, and nearly all of it
       went behind the footer. Change the angle and re-measure. */
    transform: translateX(-50%) rotate(-74deg);
    /* 150 = the sage family's phone width, matching `.oto-sprig`. It was 105, which
       was the ceiling of the old pocket up beside the CTA card; moving down here
       opened the room. See the leaf-scale table on `.oto-corner-leaf` — the two sage
       pieces move together, and so do the two teal ones. */
    width: 150px;
  }
}

/* ---------- The teal/white leaf at "What to Expect"'s bottom-left corner ------
   2026-08-25. Lauren: "lets add a teal/white leaf coming from the bottom left
   corner of what to expect section, into the white."

   ONE DRAWING, TWO COLOURWAYS, TWO COPIES at pixel-identical positions — white
   while it is on the lavender, teal the moment it crosses onto the paper. The pair
   is leaf-vine-teal / leaf-vine-white, both 560x811 from the same source, which is
   the condition that makes a crossover possible at all. NEVER pair either with
   leaf-vine-sage: that is a different drawing (aspect 0.5578 against 0.6905) and
   cannot be aligned at any offset — which matters here, because the sage sprig is
   only a few hundred pixels up the same section.

   IT STRADDLES THE CORNER, which is the point of the piece. Centred at roughly
   (140, 4210) at 1280 against a card corner at (100, 4261), so the drawing has
   lavender above-right of it and bare paper below-left, and the colour change
   happens ON the torn corner rather than near it.

   -92deg, DERIVED FROM THE DRAWING. leaf-vine-teal has its bare stem at the
   BOTTOM-RIGHT and its leafy tip at the TOP-LEFT — read off the asset with a
   percentage grid, stem at (97%, 98%) and tip at (10%, 3%) — so its stem-to-tip
   vector points up and to the left, at about 227deg. Turning that to point down and
   to the left instead, 135deg, is a difference of -92.

   AND THEN MIRRORED, 2026-08-25 — Lauren: "flip the leaves so the stem is on the
   left side." Rotation alone put the stem up-RIGHT, back toward the middle of the
   card, with the leaves trailing off to the page margin. Mirrored, the stem enters
   from the margin and the leaves fan in across the corner, which is how every other
   vine on the site arrives.

   `scaleX(-1) rotate(-92deg)` — AND THE ORDER IS THE WHOLE TRICK. CSS applies
   transform functions right to left, so the rotation happens first and the mirror
   then flips the FINISHED drawing across the vertical axis. That is what swaps left
   for right on screen while leaving the -92 reading in screen space. Written the
   other way round, `rotate(-92deg) scaleX(-1)`, the mirror would apply to the
   upright drawing and the angle would then take the mirrored copy somewhere else
   entirely. Both orders appear in this file deliberately — see the notes on
   `.beyond-corner-white` and `.chalk-intro-leaf`.

   THE BOX DOES NOT MOVE. A scaleX about the element's own centre mirrors the
   content inside an unchanged bounding box, so `left` and `top` needed no
   re-deriving — only the ink clearances did, and those re-measure clean.

   240px, UNDER THE 280-430 THE GRAMMAR GIVES A VINE SEGMENT. The paper it lives in
   is an L — a 100px margin left of the card and a 72px band below it — and at 300
   the rotated box was wide enough to reach the copy inside the card.

   IT NOW CROSSES OUT OF ITS OWN SECTION, DELIBERATELY. Lauren, 2026-08-25: "move
   them down lower." .oto-expect ends at y4333 and the drawing's foot is at y4384,
   so the last ~50px sit inside .oto-interest. That is safe rather than sloppy, and
   it is worth knowing why: .oto-interest has no background of its own, so the paper
   under the leaf is the same paper as above it and the section boundary is not a
   visible line. The next thing that could hide it is that section's deep-teal card
   at y4413, which the drawing stops 29px short of.

   So the ceiling on moving this further down is y4413, not the section edge. */
.oto-corner-leaf {
  /* MATCHED TO THE SPRIG ABOVE, 2026-08-25 — Lauren: "now match the stem of the
     leaves under what to expect to be like that, in terms of how much is showing."
     "That" is `.oto-sprig` in the teal band, which after its own tilt runs 24px past
     the RIGHT page edge.

     So this is not a taste value any more, it is a copy of a measured one: the
     painted stem here runs 24px past the LEFT page edge, so the two pieces lose the
     same amount of stalk to their respective margins and read as one hand. It went
     -7.4% -> -5.1% -> -7.04% across the session to get there; the last move is the
     one with a reason attached.

     RE-DERIVE THIS IF THE SPRIG'S ANGLE CHANGES. The 24px is a consequence of
     `.oto-sprig`'s -101deg — rotating that drawing changes its bounding box and so
     changes how far its stem reaches — so the pair only stays matched while that
     number holds.

     The right edge is the constraint on this piece, not the left: the leaf paints to
     x306 and the card's lowest line, "Sessions happen over video…", starts at x368.
     `main` is overflow-x: clip, so what hangs off the page costs nothing and cannot
     produce a scrollbar. */
  /* -7.04% -> -10.74% -> -14.44%, 2026-08-30. Lauren: "the sage and white leaves
     in the lavendar section, need to be moved to the left some", then "move to
     left a little more" after seeing the first step. 40px each time, 80px total
     at 1280. The first step read as subtle because the drawing is 352px wide and
     the preview downscales it; the second doubles the displacement.

     THIS OVERRIDES THE DERIVATION ABOVE, deliberately. -7.04% was not a taste
     value: it was solved so the painted stem ran 24px past the LEFT page edge,
     matching `.oto-sprig`'s 24px past the right so the two would lose the same
     stalk to their margins. That match is now broken on purpose &#8212; the stem runs
     105px past the left against the sprig's 25px past the right. If the pair
     should read as one hand again, the sprig moves to match this, not the other
     way round; she asked for this one.

     THE CROSSOVER SURVIVES, which was the thing at risk. Measured as INK rather
     than boxes, because the box lies here in both directions (see the note
     below): the white copy's ink ran x-25..x309 originally, x-65..x269 after the
     first step and x-105..x229 now, against a card whose left edge is x100. So
     the painted overlap into the lavender goes 209px -> 169px -> 129px. Still
     comfortably the "even if just the slightest" overlap Lauren asked for on
     2026-08-25, but the budget is now half spent: about 129px of further
     leftward movement remains before the white copy has nothing to show and this
     stops being a crossover at all. RE-MEASURE THE INK before the next step, and
     recolour the two copies to check if it is ever in doubt - the box overlaps
     the card either way and says nothing.

     IT ALSO GAINS CLEARANCE. The constraint on the right was the card's lowest
     line, "Sessions happen over video...", which starts at x368 against ink that
     reached x309; that gap widens rather than narrows, to 139px. */
  left: -14.44%;
  /* 60.4% -> 70% -> 62.1%. The 70% came from "move them down lower"; this partly
     walks it back, for a reason worth recording — at 70% the crossover had stopped
     being one.

     MEASURED: ZERO painted pixels landed inside the card's box. Lauren spotted it
     ("id like the teal ones under what to expect to come out a little so they
     overlap even if just the slightest over the lavender") and the canvas agreed —
     the white copy was rendering nothing at all, so what looked like a two-colourway
     crossover was really just a teal leaf sitting below and left of the card.

     THE BOX LIED IN BOTH DIRECTIONS HERE, which is why this went unnoticed. The
     drawing's bounding box overlapped the card by 131px vertically, so every
     box-based check said the two met. But the stem is top-LEFT and the leaves fall
     down-RIGHT, so the box's upper-right quadrant — the only part inside the card —
     is empty. Sampling the ink per column tells the real story: the topmost ink
     right of the card's left edge sat at y4302 against a card bottom of y4291, 11px
     short.

     62.1% raises it 45px, which puts the ink from x100 to about x200 onto the
     lavender. Slight, which is what she asked for. Anyone tuning this again should
     re-run the per-column check rather than trusting the boxes. */
  top: 62.1%;
  width: min(240px, 22%);
  /* 0.55, the value the site's teal crossovers carry — a step up from the 0.5 a
     plain coloured leaf on paper takes, because half of this one is white on
     lavender and needs the weight. ON THE SHARED SELECTOR: a half at a different
     density visibly changes the drawing's weight as it crosses the edge. */
  opacity: 0.55;
  transform: scaleX(-1) rotate(-92deg);
  pointer-events: none;
}

/* `top: 62.1%` IS A DESKTOP NUMBER AND IT DOES NOT TRAVEL. The percentage resolves
   against the card, and the card is 430px tall at 1280 and 1111px tall at 390 — so
   62.1% is 267px down a short card and 690px down a tall one. The piece stopped
   being a corner ornament entirely: measured at 390 it sat halfway up the card
   across "A 30-minute call after our last session…", and the crossover it exists
   for was nowhere near an edge.

   SO IT ANCHORS TO THE BOTTOM INSTEAD. `top: auto; bottom: <px>` holds the drawing
   on the card's bottom-left corner however tall the copy makes the card — which is
   the same reasoning as the seam anchor on the About page, one axis at a time.

   -75px, AND IT WAS MEASURED THE HARD WAY. The card's box bottom is at y6003 at 390,
   but the box is not the edge: `torn-paper` masks the card with torn-paper-c.svg, and
   in the leaf's own x range the visible lavender stops at y5966 — 37px above the box.
   Placed against the box the drawing sat entirely on the paper and the white copy
   rendered NOTHING, which is the exact failure this piece already had once on desktop.

   TINTING IS WHAT PROVED IT. Sampling the mask SVG to a canvas gave 6002 and was
   wrong — the file carries preserveAspectRatio="none" for CSS but drawImage does not
   stretch it the same way. Recolouring the two copies in the page (white -> red, teal
   -> blue) and reading the screenshot is the check that cannot lie: no red anywhere
   meant no crossover. Do that before trusting any number here.

   At -75 the visible leaf runs y5949-5993 against that 5966 edge: about 17px of it on
   the lavender and 27px on the paper below, which is the "even if just the slightest"
   overlap Lauren asked for on desktop. The copy above ends at y5902 and the navy CTA
   card below starts at y6155, so both clearances are large. */
@media (max-width: 760px) {
  .oto-corner-leaf {
    top: auto;
    bottom: -115px;
    /* -13%, not the desktop -7.04%. That number was derived to run the stem 24px
       past the LEFT page edge to match `.oto-sprig`'s 24px past the right — but the
       card sits only 16px inside the page at 390 against 100px at 1280, so the same
       percentage of a narrower box leaves the stem sitting in open paper instead of
       entering from the margin. -13% of 359 is -47px, which puts the element at x-31
       and the painted stem back off the page. */
    /* -5%, moved right 2026-08-26 — Lauren: "lets make the teal leaves under the
       lavender section moved to the right more." At -13 the drawing spent 43% of
       itself off the left page edge, which is waste rather than margin; at -5 that
       is 20%, the painted stem still runs 38px past the edge so it keeps entering
       from the margin, and the leafy end reaches x214 against x137 before. */
    left: -5%;
    /* 180, up from 140, and it is a MATCH rather than a size — see the note above
       about the two drawings' weights. `.oto-tear-white/-teal` at the hero is the
       same leaf-vine-teal / -white pair and is already at 180; at 140 this one read
       a size smaller than a piece drawn from the identical file.

       THE PAGE'S PHONE LEAF SCALE, so all four stay in step:
         leaf-vine-teal / -white  -> 180px   (.oto-tear-*, .oto-corner-leaf)
         leaf-vine-sage / -white  -> 150px   (.oto-sprig, .oto-note-leaf)
       The two families differ because the sage drawing is about 18% heavier; equal
       width between families is NOT equal leaf size. Move one and move its pair.

       -115px goes with it. Bottom-anchored, a bigger drawing grows upward and its
       leafy end swings right, so both changes push more of it onto the lavender —
       measured, the overlap went from 6.3% of its ink to 19% at the old offset. -115
       brings it back to 6.5%, which is the "even if just the slightest" Lauren asked
       for on desktop. RE-MEASURE THIS RATIO, don't eyeball it: the box overlaps the
       card either way and says nothing about whether the crossover is happening. */
    width: 180px;
  }
}

/* ============================================================
   THE SAGE SPRIG THAT CROSSES THREE GROUNDS — 2026-08-25
   ============================================================
   Lauren asked for sage leaves off the bottom right of "It's All Self-Love",
   overlapping the teal band, the paper below it and the lavender card — stem on
   the right, leaves coming down — and gave the colour rule herself: "when the
   leaves are on teal and lavender they are white, when they are on the white
   they are sage."

   THIS IS THE SITE'S FIRST THREE-WAY CROSSOVER. Every other one is a pair: one
   torn edge, one colour change, two copies. This one passes teal -> paper ->
   lavender, so it is two changes, three copies, and the white RETURNS on the far
   side of the sage. The three must stay pixel-identical or the drawing visibly
   jumps as it crosses, so every visual declaration lives on the shared
   `.oto-sprig` selector below and only the clipping differs between them.

   THE HARD PART IS THAT THE THREE COPIES LIVE IN THREE DIFFERENT SECTIONS, which
   is not true of any existing crossover — About's pair resolves both halves
   against boxes the layout already forces to be identical. Here the containing
   blocks are the teal band (full-bleed), a clip inside .oto-expect (full-bleed)
   and the lavender card (min(1080px, 92%), centred). Three different origins
   would need three sets of offsets kept in sync by hand, which is exactly the
   kind of thing that survives one edit and not two.

   SO THE BOX IS REPRODUCED INSTEAD OF THE OFFSETS. `.oto-sprig-box` is the card's
   own box — same width rule, same centring — dropped into the other two
   contexts at the card's own top. All three copies then position against boxes
   with identical left, width and top, and one `right`/`top`/`width` serves all
   three. Nothing here needs re-deriving when the sprig moves; only `.oto-sprig`
   does. */
.oto-sprig-box {
  position: absolute;
  /* left+right+width+auto margins is what centres an absolutely positioned box.
     NOT `left: 50%; transform: translateX(-50%)`: a transform on this wrapper
     would make it the containing block AND a stacking context, and the sprig
     inside already carries its own transform. */
  left: 0;
  right: 0;
  width: min(1080px, 92%);
  margin-inline: auto;
  /* Zero, because this box exists only to supply an origin — it must never
     capture pointer events or affect layout. Every offset on .oto-sprig is
     therefore in px rather than %, since percentages would resolve against a
     height of nothing. */
  height: 0;
  pointer-events: none;
}

/* In the teal band, the card's top is the band's own bottom plus the section's
   top padding — .oto-expect is `padding: var(--section) 0` and its .wrap is the
   card exactly. Measured at 1280: 3086 + 536 + 72 = 3694 against the card's real
   3693, so the construction is right to a rounding pixel and does not need a
   tuned constant. */
.oto-deeper > .oto-sprig-box { top: calc(100% + var(--section)); }

/* Inside the clip the same point is one --wave-h further down, because the clip
   starts that far above .oto-expect's top. */
.oto-sprig-clip > .oto-sprig-box { top: calc(var(--wave-h) + var(--section)); }

/* The paper copy's top edge. Identical in construction to .oto-tear-clip at the
   hero — masked with --wave-bottom-inv, the complement of the same curve
   .torn-bottom draws, tiling --wave-tile from x0 of a full-bleed box — so the
   sage begins exactly where the teal ends, with neither overlap nor gap.

   420px tall: the sprig paints down to about 250px below the card's top and the
   card only covers x100-1180, so the slice running past the card's right edge
   needs the clip to still be there. It stays well inside .oto-expect's 712. */
.oto-sprig-clip {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(-1 * var(--wave-h));
  height: 420px;
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
  -webkit-mask-image: var(--wave-bottom-inv), linear-gradient(#000, #000);
          mask-image: var(--wave-bottom-inv), linear-gradient(#000, #000);
  -webkit-mask-size: var(--wave-tile) var(--wave-h), 100% calc(100% - var(--wave-h) + var(--wave-overlap));
          mask-size: var(--wave-tile) var(--wave-h), 100% calc(100% - var(--wave-h) + var(--wave-overlap));
  -webkit-mask-position: 0 0, 0 100%;
          mask-position: 0 0, 0 100%;
  -webkit-mask-repeat: repeat-x, no-repeat;
          mask-repeat: repeat-x, no-repeat;
}

/* THE SHARED SELECTOR. Every one of these applies to all three copies; a value
   that differs between them breaks the crossover outright, and opacity counts as
   alignment just as much as position does — one half at a different density makes
   the drawing change weight as it crosses the edge.

   -110deg, ROTATION ONLY, NO MIRROR, and it is read off the asset rather than
   guessed. leaf-vine-sage has its bare stem at the drawing's foot, bottom-right,
   with the leafy tip at top-left. At -110deg the foot swings up to the RIGHT and
   the leafy end falls away to the left and below — which is "stem on the right
   side and leaves coming down", exactly. A mirror would swap stem and leaves end
   for end and undo it.

   230px is the site's size for a sage segment: .twocol-top-leaf, About's
   .beyond-corner pair and .chalk-intro-leaf are all 230, so the sage reads at one
   scale across every page. 24% of the 1080 box is 259, so the px value binds on
   desktop and the percentage only takes over on narrow windows.

   0.5 is the site's opacity for a coloured leaf on white paper — .vine-seg's
   base, .twocol-top-leaf, .beyond-corner-sage. The white copies take it too,
   because they must. */
.oto-sprig {
  /* OFF THE PAGE EDGE, and that is why this one value is not a percentage like
     everything else here. Lauren: "move it to the right more", then "so its coming
     from the side of the page" — which is the site's own idiom for a margin sprig
     (.club-tear-white: "20px past the right edge, so the sprig reads as entering
     from the margin rather than starting in mid-air").

     A PERCENTAGE CANNOT EXPRESS IT. Every other offset on this piece resolves
     against the card's box, which is what keeps the three copies in register — but
     the card is `min(1080px, 92%)` CENTRED, so its right edge sits 100px inside the
     page at 1280 and 180px inside at 1440. A fixed percentage of that box lands the
     stem in a different place relative to the page at every width, which is exactly
     what "coming from the side of the page" must not do.

     So this offset converts between the two frames explicitly. Solving
       element right edge = 100vw - 44px
     for a `right` measured from the card's edge gives (cardW - 100vw) / 2 + 44px,
     and the 44 is derived rather than picked: the painted stem ends 69px right of
     the element's own box once the -110deg rotation is applied, so 44 puts the ink
     25px past the page edge at EVERY width. Re-derive it if the angle or the width
     changes; it is a function of both.

     The three copies stay in register because they all take this same expression —
     it is still one value on one shared selector, just one that happens to know
     about the viewport.

     IT COSTS NO SCROLLBAR. Each copy is bounded by its own clip: the band's mask
     stops at the band's 100% width, .oto-sprig-clip is overflow: hidden, and the
     card's torn-paper mask ends at the card. Nothing paints past the page edge.

     AND IT MOVES MORE OF THE DRAWING INTO SAGE. The card's right edge is a colour
     boundary too — the same rule as the tear, running down a vertical edge instead
     of across a horizontal one — so pushing the sprig right takes its leaf tips off
     the lavender and onto the paper, where they turn sage. That is the construction
     working, not a fault. */
  right: calc((min(1080px, 92vw) - 100vw) / 2 + 44px);
  /* px, not %: the box above has no height for a percentage to resolve against,
     and px is what keeps the three copies identical across three contexts.

     -250 -> -320 -> -350 -> -400, 2026-08-25. Lauren: "lets move them higher so they
     sit more in the teal section above", "move it higher still", and then the one
     that mattered — "its ok if its not in lavender anymore."

     IT IS NO LONGER A CROSSOVER AT ALL. The split across teal, paper and lavender
     went 150/72/135 -> 220/72/65 -> 250/72/36 -> 300/58/0 -> 324/0/0. At -440 the
     drawing's painted tail stops ABOVE the band's torn bottom, so it never reaches
     the paper, the sage copy has nothing to show and the white copy inside the card
     has nothing to show either. What renders is one white sprig inside the teal band
     — which is a perfectly ordinary thing for this site to have, and is what the
     hero band carries too.

     TWO OF THE THREE COPIES ARE NOW INERT, and the clip wrapper with them. They are
     kept rather than deleted because the height has moved five times today and every
     one of those moves was a one-number edit; deleting them makes the next move a
     rebuild. The cost is two already-cached image requests and a masked empty div.
     STRIP THEM once this height is settled — .oto-sprig-clip, the .oto-sprig-box
     inside it, and the .oto-sprig child of .oto-expect-card.

     THE CEILING FROM HERE IS THE BAND'S OWN COPY. "Every time we make room for
     something we love…" ends at y3297 and reaches x952; the sprig clears it only
     because what it sends upward is the STEM, out at x1200+. Measure painted alpha,
     not the box, before raising it again — the box's upper-left corner is empty. */
  top: -480px;
  width: min(230px, 24%);
  opacity: 0.5;
  transform: rotate(-101deg);
}

/* ON A PHONE THE BAND HAS NO MARGIN, so this piece cannot stay where it is. At
   1280 the copy is a centred column with ~330px of clear teal either side and the
   sprig lives out in that; at 390 every line runs to x370 and the drawing landed
   straight across "Treating ourselves like we matter." — 441 painted pixels on one
   line of reversed-out copy, measured, the worst collision on the page.

   SO IT DROPS BELOW THE COPY, which is the only pocket the band has at any phone
   width: the copy always ends before the section's bottom padding does. Measured at
   390 the last line's ink stops at y4713 and the band runs to 4820, and the same
   gap exists at 320 and 699 because it is padding rather than anything that wraps.

   AND THE THREE-WAY CROSSOVER COMES BACK. It died on desktop when Lauren raised the
   sprig to -480 ("its ok if its not in lavender anymore") and two of the three
   copies have rendered nothing since. Down here the drawing crosses the band's torn
   bottom into the paper below it, so the white copy in the band and the sage copy in
   .oto-sprig-clip both paint and the colour change happens on the tear — which is
   what the piece was built to do. The card copy still shows nothing; the card starts
   72px below the band and the drawing stops short of it.

   The width is the min() collapse: 24% of a 359px box is 86px, so the sprig had
   quietly become a third of its drawn size. 150px is the phone value the mobile
   grammar asks for — proportionally LARGER against a 390px page than 230 is against
   1280. */
@media (max-width: 760px) {
  .oto-sprig {
    /* SAME EXPRESSION, NEW CONSTANT, and the constant is a function of the width.
       The 44px in the desktop rule is `0.3 * 230 - 25`: the painted stem overhangs
       the element's own box by 0.3 of its width once the -101deg rotation is
       applied, and 25 is how far past the page edge that ink is meant to reach. At
       150px wide that same derivation gives 20. Re-derive it again if either the
       width or the angle changes here — it is not a tuned number. */
    right: calc((min(1080px, 92vw) - 100vw) / 2 + 20px);
    /* px from .oto-sprig-box's top, which is the card's own top in all three
       contexts — 4892 at 390, i.e. 72px below the band's bottom edge at 4820. -180
       puts the painted drawing at roughly y4750-4950: clear of the copy above it,
       across the tear at 4820, and stopping short of the card. */
    top: -180px;
    width: 150px;
  }
}

/* ---------- The white butterfly over "Love", phones only — 2026-08-26 ----------
   Lauren: "lets add a small white sketch butterfly with open wings to the its all
   self love teal section on mobile", then "i think about the word love tilted to the
   right a little."

   MOBILE-ONLY, which the site allows — see `.pillars-teal-bfly` and
   `.believe-seam-flight`, both placed against layouts that only exist once things
   stack. The standing rule protects desktop art from vanishing on a phone, not the
   other way round. At 1280 this band already carries the sprig and there is no room
   above the heading; on a phone the heading sits alone with 102px of clear teal over
   it.

   OVER ONE GLYPH, AND THAT OFFSET IS A CONSTANT. `.oto-title`'s font-size is
   clamp()-ed and sits at its FLOOR — 27.52px — across the whole phone range, so the
   heading renders at one width and its glyphs do not move: measured, the dash in
   "Self-Love" is 40px right of the page centre at 320, 390 AND 430 alike. That is
   why this can be a px offset from centre rather than something that has to track
   the type. RE-MEASURE IT if the heading's clamp floor or its copy ever changes —
   the glyph is the anchor, not the number.

   `left: calc(50% + 76px)` with `translateX(-50%)`: the calc puts the box's LEFT
   EDGE over the word and the translate then centres the box on it. Order is
   `translateX(-50%) rotate(...)` as everywhere else here — rotate first, then shift
   the finished drawing half its width in screen axes.

   102px OF CLEAR TEAL is the whole pocket, between the band's top edge and the
   heading's ink. The drawing paints 55px tall at this size, so it sits in the middle
   of that with room either side rather than being wedged into it. */
.oto-deeper-bfly { display: none; }

@media (max-width: 760px) {
  .oto-deeper-bfly {
    display: block;
    /* px from the band's own top. That distance to the heading is the section's
       padding plus one line box and does not move — 102px at 320, 390 and 430.

       56, AND IT IS NOW THE TIGHT NUMBER HERE. Lauren asked it down after the tilt
       went to -24, and the tilt had already cost 2px of clearance on its own — a
       wider rotation makes the drawing's box taller. Painted bottom is 4px off the
       heading's ink at 390 and 5px at 320, which is close enough to read as resting
       on the word and close enough that any further move down needs measuring
       rather than nudging. 48px of teal still above it. */
    top: 64px;
    /* OVER THE DASH in "Self-Love", 2026-08-26. Lauren walked it in — the word
       "love", then its final "e", then the hyphen between the two halves.

       The dash's centre measures 40px right of the page centre. 43 rather than 40
       because the drawing is not centred inside its own box and the -24deg tilt
       moves it further, so the PAINTED centre sits about 3px left of the box's. Aim
       the ink, not the box, and re-measure after any change of size or angle —
       both move it, and both changed twice in the round that set this. */
    left: calc(50% + 43px);
    /* 42px, down from 66 through 52 — "small", asked twice. It is now the smallest
       butterfly on the page by some way: the sketch one over "You Don't Need To…" is
       51, the pair's is 94, the footer's 92. That is right for what it is, a mark on
       a single glyph rather than a piece carrying its own composition.

       `top` MOVES WITH IT. Bottom-anchored it is not — the box hangs from `top` — so
       shrinking lifts the painted bottom away from the heading. 64 holds the 4px
       clearance that 52/56 had; re-derive it again if the width changes. */
    width: 42px;
    /* 0.85, a shade under the footer butterfly's 0.78 sibling weight — white line
       art on the deep teal reads harder than it does on navy. */
    opacity: 0.85;
    /* -24, from 12 through -12. The first pass tilted it right; Lauren reversed it
       and then asked for more. Every change of angle moves the painted centre off
       the letter and changes the height, so `left` and `top` are re-measured with
       it — they are one setting, not three. */
    transform: translateX(-50%) rotate(-24deg);
    pointer-events: none;
  }
}

/* ---------- 8 · "What to Expect" ----------
   A light teal scrap, so the one section carrying logistics has a surface of
   its own — and so the lower half of the page has a colour moment now that the
   deep band has gone with its section.

   THE PACKAGE HAS HER OWN LABELS ON IT NOW. An earlier draft ran this as five
   numbered steps with line icons and no headings, because she had not written
   any and inventing them was not mine to do. "3 Private Sessions", "Joy
   Experiments", "Check-Ins" and "Follow-Up" are hers, so the section can be the
   row it always wanted to be. */
.oto-expect { position: relative; padding: var(--section) 0; }
.oto-expect .wrap { width: min(1080px, 92%); position: relative; }

.oto-expect-card {
  position: relative;
  /* The third tear on the page, so no two scraps carry the same edge. */
  --panel-tear: url("../images/art/torn-paper-c.svg");
  /* LAVENDER since 2026-08-24, Lauren: "make what to expect, lavender". It
     picks up the colour the Joy panel gave up when that went blue, so the page
     still runs teal / blue / lavender rather than losing a hue. Measured on
     --panel-lav: navy 8.2:1, --ink 5.4:1 — both clear, and both are what this
     card already uses. */
  background-color: var(--panel-lav);
  background-image: url("../images/art/paper-wash.png");
  background-size: cover;
  background-position: center;
  background-blend-mode: soft-light;
  padding: calc(var(--space-xl) + 0.8rem) clamp(1.8rem, 4vw, 3.4rem) calc(var(--space-xl) + 1rem);
}

.oto-expect-card .oto-title { color: var(--navy); margin-bottom: 1rem; }


.oto-expect-lead {
  max-width: 40rem;
  margin: 0 auto 2.6rem;
  color: var(--ink);
  font-size: var(--t-md);
}

/* Four across on desktop, two at tablet, one on a phone. Not the Club's
   `.receive7`, which carries a watercolour patch per item — those belong to
   that page's pillars, and this row has no art. What it borrows is the
   grammar: a small-caps label over a short description.

   EIGHT TRACKS FOR FOUR COLUMNS, since "Continuing Sessions" made the row odd
   on 2026-08-28. Five items in four columns strand the fifth at the left edge
   with three empty cells beside it. Doubling the track count and spanning every
   item across two costs nothing — an item measures 2c+g either way, so all four
   existing cells keep the exact width they had — and it buys the one thing four
   tracks cannot give: a leftover can sit at tracks 4–5, the true middle of
   eight, instead of at the left. The same trick at half scale runs the tablet
   band below.

   The centring rule is `:nth-child(5):last-child`, NOT `:last-child`. A sixth
   item would make the row even again and need no centring at all, and a bare
   `:last-child` would go on forcing the last cell into the middle of a full
   row. */
.oto-expect-grid {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  gap: clamp(1.4rem, 3vw, 2.4rem);
  text-align: center;
}

.oto-expect-grid > .item { grid-column: span 2; }
.oto-expect-grid > .item:nth-child(5):last-child { grid-column: 4 / span 2; }

.oto-expect-grid h3 {
  font-family: var(--font-body);
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  /* --navy, not --teal-ink, since the card went lavender on 2026-08-24.
     --teal-ink was chosen against --panel-teal and does not survive the move:
     measured 4.06:1 on --panel-lav, under the 4.5 that 15px labels need.
     --navy is 8.2:1 there, and is what every other coloured panel on the site
     uses for its small text.

     FIXED HERE RATHER THAN OVERRIDDEN. A `.oto-expect-card h3` rule was added
     further up first and did nothing: same specificity as this one and earlier
     in the file, so this won the tie silently. The measurement caught it. When
     a colour has a home, change it at home. */
  color: var(--navy);
  line-height: 1.35;
  margin-bottom: 0.55rem;
}

.oto-expect-grid p { font-size: 0.977rem; line-height: 1.6; color: var(--ink); }

/* The video line, new 2026-08-23. It is the only practical detail on the page
   that is not part of the package itself, so it sits UNDER the row rather than
   becoming another cell in it — in the row it would read as one more
   deliverable, which it is not. Quieter than the grid copy for the same
   reason. (It was "a fifth cell" when the row held four; the row holds five
   since 2026-08-28, and the argument is unchanged.) */
.oto-expect-foot {
  margin: 2.4rem auto 0;
  max-width: 34rem;
  /* CENTRED, 2026-08-25. `margin: auto` was already centring the BOX, which is why
     this looked like it might be centred and was not — the text inside it still ran
     left while every other line in the card was centred, so at 34rem the block sat
     visibly off-axis under a centred grid. The card does not centre its children
     for you: `.oto-title` needs `.center` for the same reason. */
  text-align: center;
  font-size: var(--t-sm);
  /* --navy for the same reason as the grid labels above: --teal-ink measures
     4.06:1 on the lavender this card took on 2026-08-24, and this line is
     16.8px, so it needs 4.5. */
  color: var(--navy);
}

/* The sign-off, new 2026-08-23. `.join-card .script` already gives it the
   seafoam that lifts off the deep teal card; this only sets the spacing, since
   the two `.join-note` paragraphs above it carry their own bottom margin and
   the form follows directly underneath. */
.oto-join-signoff { margin: 0.2rem 0 1.6rem; }

/* ---------- 9 · The interest card ----------
   `.club-join` / `.join-wrap` / `.join-card` is reused whole — it is the site's
   CTA card and the Self-Love Club's waitlist wears it, so the two pre-launch
   offers look like they come from the same place. Only two things differ. */
.oto-interest { padding-top: calc(var(--section) + 0.5rem); }

/* Her two sentences are both `.join-note`, and that class carries no bottom
   margin of its own — on the Club card it is the only one. */
.oto-interest .join-note + .join-note { margin-top: 0.9rem; }

/* ---------- The card goes BLUE on this page ----------
   Lauren, 2026-08-23: "make that block blue also." It matches the hero, which
   is a blue sky, so the page now opens and closes on the same colour.

   SCOPED TO `.oto-interest`, and that scoping is the whole point: `.join-card`
   is SHARED with the Self-Love Club's waitlist card, and restyling the bare
   class would have turned that one blue too. The two cards are meant to look
   like the same object; they are now the same object in two colourways.

   THE HUE IS ROTATED, NOT REPLACED. Both stops are the existing deep teals with
   their lightness and HSL saturation held and only the hue moved — 178 -> 206
   and 184 -> 212 — so the card is the same depth of colour it always was and
   every value reversed out of it still clears: cream 7.3:1 and 10.1:1, the
   seafoam script 6.4 and 8.9, the pale-teal button 5.4 and 7.4.

   THE BUTTON STAYS PALE TEAL. Lauren's standing rule is that every CTA of this
   kind is teal, and it reads as deliberate against the blue rather than as an
   oversight — but it is the one thing here that did not move, so it is the
   first thing to look at if the card feels mismatched. */
.oto-interest .join-card {
  background-image:
    url("../images/art/paper-wash.png"),
    radial-gradient(ellipse 60% 55% at 88% 8%, rgba(var(--c-blue), 0.22), transparent 66%),
    radial-gradient(ellipse 55% 60% at 6% 94%, rgba(var(--c-lav), 0.20), transparent 70%),
    linear-gradient(158deg, #2A577A 0%, #1C4069 100%);
}

/* ---------- 10 · "A Quick Note" ----------
   Deliberately the quietest thing on the page: no panel, no rule, small type,
   sitting under the card the way the footer's copyright sits under the footer.
   It is a disclaimer, and dressing it up would make it read as a selling
   point — so the heading is a small caps label rather than a display heading,
   even though it is an <h2> for the outline's sake. */
.oto-note {
  position: relative;
  padding: 0 0 var(--section);
  text-align: center;
}

.oto-note-title {
  font-family: var(--font-body);
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--teal-label);
  margin-bottom: 0.7rem;
}

.oto-note p {
  max-width: 44rem;
  margin-inline: auto;
  font-size: var(--t-xs);
  line-height: 1.75;
  color: rgba(64, 73, 78, 0.82);
}

/* ==========================================================================
   1:1 With Lauren — decoration

   THERE IS NONE YET. A full pass — butterflies, sprigs and dotted trails across
   all eleven sections — was built here and measured across 390/701/768/900/
   1024/1280/1440, then removed on 2026-08-23 at Lauren's call: the pieces go
   back on one at a time so each placement is a decision she has seen.

   Worth keeping from that pass, because it is what made the placements
   trustworthy rather than eyeballed:

     · Score a placement by PAINTED PIXELS, not boxes. Draw the asset into a
       canvas under its own computed transform, then count pixels with alpha >
       40 that fall inside a text RANGE rect (glyph runs, not block boxes — a
       centred paragraph's box is the full column and over-reports wildly).
     · Solve at the NARROW edge of each breakpoint band. The copy blocks here
       are capped at 34-40rem while the wrap is 92%, so the clear margins shrink
       as the window does: the deep band's left column is 60px at 768 against
       320px at 1280. A value that clears at the tight end clears everywhere
       above it, and the reverse is not true.
     · This page needs three bands, not two — the 701-900 range behaves like
       neither desktop nor phone, and four pieces wanted their own placement in
       it.
     · Setting `top` in one block against a `bottom` in another STRETCHES an
       absolutely positioned image instead of moving it. Every override has to
       reset the edge it is not using. Same trap recorded at `.vine-club-seam`.
   ========================================================================== */

/* ==========================================================================
   1:1 With Lauren — responsive
   ========================================================================== */

@media (max-width: 1000px) {
  /* Four across leaves each item ~200px inside the card's padding, which is
     narrower than the labels want. Two across instead — four tracks, every item
     spanning two, so the odd fifth centres at tracks 2–3 the same way it does at
     4–5 on desktop. */
  .oto-expect-grid { grid-template-columns: repeat(4, 1fr); }
  .oto-expect-grid > .item:nth-child(5):last-child { grid-column: 2 / span 2; }
}

@media (max-width: 760px) {
  .oto-hero { padding: 7.5rem 0 5rem; }
}

@media (max-width: 700px) {
  .oto-hero { padding: 7rem 0 4.5rem; }

  .oto-open-copy,
  .oto-do-copy { font-size: var(--t-base); }

  /* Four across becomes one column: at 390 a quarter of the card is 68px.
     The spans MUST be reset with it — a `span 2` left standing against a single
     track invents an implicit second column and the row silently goes back to
     two-up on a phone. */
  .oto-expect-grid { grid-template-columns: 1fr; }
  .oto-expect-grid > .item,
  .oto-expect-grid > .item:nth-child(5):last-child { grid-column: 1; }
  /* And the two short lists go back to a single run — two columns of one-word
     items on a 390px page is four words a row with a canyon between them. */
  .oto-list-2col { columns: 1; }
}


/* ============================================================
   COURGETTE — the handwritten accent, 2026-08-24
   ============================================================
   Applied BY HAND to a counted set of short lines. See --font-accent at the top
   of this file for what qualifies and what is ruled out.

   THIS BLOCK SITS LAST, AND THAT IS LOAD-BEARING — the same reason the weight
   block below it does. Several of the lines it targets already carry a
   font-family from a class of their own: `.script`, `.spark-closing-script` and
   `.oto-joy-title` all set `var(--font-script)` at one class of specificity,
   which is exactly what `.accent` has. Declared earlier in the file, `.accent`
   lost every one of those ties on source order and only the `.script` lines
   changed — measured, not assumed: "Joy is a compass." on the 1:1 page stayed
   Fraunces while the line above it turned over.

   Raising specificity would have worked too and is worse: it would mean writing
   `.accent.accent` or naming each host class, and the next line that takes this
   face would have to discover the rule again.

   It sits ON TOP of whatever treatment the line already has — the pull-quote's
   colour and size are untouched and only the face swaps, which is why this sets
   no colour.

   THE SIZE IS A MULTIPLE OF THE LINE'S OWN SIZE, and getting there took three
   passes because the first mechanism was quietly wrong. Lauren, 2026-08-23, in
   order: "the script font, it needs to be larger, its a bit small", then "can
   we make the script font bigger", then "i still want the script font bigger".

   WHY IT KEPT READING SMALL — this is the whole story. The rule used to say
   `font-size: 1.34em`, written on the belief that em would scale each line up
   from whatever size it already had. It does not. `em` resolves against the
   PARENT's font-size, not the element's own, so the moment `.accent` won the
   source-order tie it ALSO discarded the host's font-size and re-derived one
   from the paragraph wrapper. Every accent line on the site collapsed to the
   same value. Measured: `.oto-joy-title` is drawn at clamp(1.863rem, 3.4vw,
   2.7rem) — 43.2px at 1280 — and `.accent` was rendering it at 27.8px. The
   "bump" was a 36% CUT on that line and a cut on the plain `.script` lines too
   (29.8px down to 27.8px). Raising the em only clawed back ground the rule had
   taken, which is why two increases in a row still looked small.

   SO THE SIZE IS NOW BUILT, NOT INHERITED. Each host restates its own clamp
   into `--accent-base` just above, and the multiplier is applied to that. The
   host clamps are duplicated, which is the cost: if one of them changes, its
   twin here has to change with it. The alternative was per-host `font-size`
   overrides, which duplicates the same clamps AND scatters the multiplier
   across four rules; this way `--accent-scale` at the top of the file is still
   one number for the whole site.

   A LINE WITH NO ENTRY in that list falls back to `1em`, i.e. the parent's
   size — the old behaviour, and wrong for the same reason. Any new host must
   be added above rather than left to the fallback.

   THE LINE-HEIGHT IS RESTATED HERE, and it has to be. A handwriting face spends
   far more of its em on ascenders and descenders than the Fraunces these host
   classes were written for: Courgette's ink box runs 1.09em top to bottom,
   Dancing Script's ran a full 1.00em, and Fraunces spends noticeably less. The
   host line-heights these lines would otherwise inherit (1.4 on `.script`, 1.25
   on `.oto-joy-title`) were set for that roomier face, so 1.4 is pinned here and
   no host can hand an accent line something tighter.

   Measured across every wrapped accent line on the site: 9.1px of clear air at
   29.8px type, and 10.3px on the club's 33.7px lines, between one line's
   descenders and the next line's ascenders. That is ~0.31em — the same
   proportion the Dancing Script build had at 14.3px on 44.7px type, which is
   the number to compare against, NOT the raw pixels.

   MEASURE 'x', NEVER 'H'. This is the note that got the face changed, and it
   is the one to read before touching any size here.

   Measured on canvas at a 100px em, after document.fonts reported loaded:

                    x-height    cap-height    ink in 'nnnn'
     Courgette        0.505        0.759           6292
     Satoshi          0.484        0.716           3571
     Averia           0.467        0.677           4349
     Fraunces         0.444        0.700           4347
     Dancing Script   0.332        0.720           2995

   READ THE FIRST TWO COLUMNS AGAINST EACH OTHER. By cap-height these faces are
   all much the same, 0.68 to 0.76 — and an earlier note here measured exactly
   that, concluded the faces matched, and recorded that the size bumps were pure
   preference. It was wrong. Reading size lives in the LOWERCASE, and there
   Dancing Script's 0.332 against Fraunces' 0.444 means it drew 25% small at
   every nominal size it was given. It spends its em on ascenders and
   descenders instead — which is also why its ink box runs a full em, the fact
   the line-height note below is built on.

   THE STROKE MATTERS TOO and shows up in no height at all. Dancing Script laid
   down 2995 ink pixels where Fraunces lays 4347 — 31% less — so even at matched
   x-height it read fainter, on pale watercolour grounds that were already
   tight enough on contrast to force --teal-ink on the lavender panel.
   Courgette's 6292 is more than twice Dancing Script's.

   SO THE MULTIPLIER WENT AWAY. Under Dancing Script this block needed
   --accent-scale: 1.5 and Lauren still asked for more, five requests in. Under
   Courgette it is 1: the clamps on `.script`, `.oto-joy-title` and the rest
   were right all along and were being asked to carry a face that could not
   hold their sizes. If a future swap makes these lines look small again,
   measure 'x' on the new face before reaching for the scale.

   `em`, NOT a fixed size: every line this lands on has its own size, from the
   22.7px opening turn to the 29.8px Joy heading, and a single px value would
   flatten them into one.

   WHERE IT LANDS AT SCALE 1. At 1280 the plain `.script` lines are 29.8px with
   an x-height of 15.05, against body Satoshi's 10.3 — about 1.46x the body
   copy, which is pull-quote territory rather than heading territory, and
   within a hair of the apparent size Lauren approved on the last Dancing
   Script pass. The Joy panel heading is 38.4px, cap-height 29.2 against the
   page h1's 43.9: comfortably subordinate to the page title, which is the test
   it has to pass.

   NOTE THE NOMINAL SIZES FELL — 44.7px to 29.8px on the script lines — while
   the READING size held. Anyone comparing these two numbers without the
   x-height table above will conclude the type shrank by a third. It did not.
   Never compare nominal px across two different faces.

   `font-style: normal` is not tidiness: every line this lands on is a
   `.script`, which is set in italic. Courgette is already a slanted handwriting
   face — as Dancing Script was before it — and a synthetic oblique laid on top
   of one smears. Any face that lands here will have the same property, since
   the brief is for handwriting. */
/* --accent-base: each host's OWN font-size, restated so the multiplier below
   has something real to scale. Ordered by specificity so the hero tagline's
   entry wins over the plain `.script` one on the element they share. */
.script.accent,
.spark-closing-script.accent  { --accent-base: clamp(1.55rem, 2.592vw, 1.863rem); }
.oto-joy-title.accent         { --accent-base: clamp(1.863rem, 3.4vw, 2.7rem);
                                --accent-scale: var(--accent-scale-display); }
.hero .script.accent          { --accent-base: clamp(1.575rem, 2.61vw, 2.07rem); }

.accent {
  font-family: var(--font-accent);
  font-weight: 400;
  font-style: normal;
  font-variation-settings: normal;
  font-size: calc(var(--accent-base, 1em) * var(--accent-scale));
  line-height: 1.4;
  letter-spacing: 0.01em;
}

/* ============================================================
   DISPLAY HEADING WEIGHTS — 2026-08-19, still true 2026-08-23
   ============================================================
   The display face ships ONE weight, 400. Everything above sets Fraunces
   weights on the display headings — `h1` 700, `h2`/`h3` 600, and a dozen
   section rules — and a weight a font does not have is an invitation for the
   browser to draw a fake bold. Chrome declines and uses 400; Safari and iOS do
   not, and smear it.

   THIS BLOCK SURVIVED THE FONT SWAP UNCHANGED, and that is worth stating
   plainly: it was written for Calistoga, and Bubblegum Sans — which replaced it
   on 2026-08-23 — is also a single-weight 400 family. The reasoning transfers
   exactly, so nothing here needed touching and nothing here should be removed
   if the swap is reverted.

   The block sits LAST in the file because `.believe h2` and its friends
   out-specify a bare `h2`; restating the selectors in one place is what makes
   this a single edit and a single revert rather than fourteen.

   NOT in this list, deliberately:
     .pillar h3, .inside-card h3, .spark-items h3   Satoshi 700, her icon labels
     .script, .about-pillars figcaption, .spark-closing-script   Fraunces italic
     .hero .script                                  Fraunces, the hero tagline
   Those three groups are not the display face and must keep their own
   weights. */

/* ---------- DISPLAY WEIGHT, one value for the whole site ----------
   BACK IN USE, and now as a dial rather than a workaround. It was written to
   pin single-weight faces to 400 so Safari could not fake a bold. Sour Gummy
   has a real 100-900 axis, so it was briefly commented out and the stylesheet's
   own weights (h1 700, h2/h3 600) reached the display face — Lauren, 2026-08-23:
   "less bold."

   400 UNDER AVERIA SERIF LIBRE, which ships 300, 400 and 700. Those three are
   the only values this may take while it is in — 500 or 600 would be a fake
   bold, the exact failure this block exists to prevent, and the font URL only
   requests the three it has.

   Because every display selector on the site is restated here, one value moves
   all of them together, which is what makes a weight change a one-number edit
   rather than fourteen. */

h1,
h2,
h3,
.about-hero-title,
.about-title,
.contact-question,
.club-faq .faq-title,
.club-price,
.how-step .step-num,
.note-copy h2,
.believe h2,
.who-for h2,
.closing-band .note-copy h2,
.closing-band .reminders h2,
.reminders h2,
.faq-q,
.ml-form-success-message strong {
  font-weight: 400;
}

/* ---------- The butterfly at the panels' corner, 1:1 page ---------- 2026-08-25
   Placed where Lauren pointed: the junction of the teal panel's right edge and
   the blue panel's torn bottom.

   THE PERCENTAGES HOLD ACROSS DESKTOP WIDTHS, which is why they are used rather
   than pixels. Measured, that corner sits at 48% / 68% of `.oto-pair` at 1280
   AND at 1440 — the two panels scale proportionally, so the junction does not
   drift. The section is already `position: relative`.

   The trail runs right across the bare paper under the blue panel, which is the
   only empty stretch here: the blue copy stops at its panel's bottom and the
   teal list continues down the left. */
.oto-pair-bfly {
  position: absolute;
  /* 46%, not 43.5. Measured at 1280: the teal panel's copy reaches x569 and its
     edge is at x627, so the butterfly's left edge has to sit between them —
     43.5% put it at 557 and painted 252px across "You'd like someone there to
     encourage you". 46% is x589 at 1280 and x662 at 1440, clear of the text at
     both while still straddling the panel's edge. */
  left: 46%;
  top: 61%;
  width: min(132px, 10vw);
  opacity: 0.95;
  /* Tilted LEFT, her word — anticlockwise, so the near wing drops. Taken from
     -17 to -28 at her ask for "a little more". */
  transform: rotate(-28deg);
  /* 4, NOT 2. `.oto-panel-teal` also carries z-index 2, and at equal z-index the
     later element in the DOM wins — so the panel painted over the butterfly and
     only 46px of its 150 survived, sliced down the panel's edge. It looked like
     a deliberate crop rather than a bug, which is how it nearly shipped: the
     giveaway was the painted box starting 81px right of the element's own. */
  z-index: 4;
  pointer-events: none;
}

.oto-pair-path {
  position: absolute;

  /* A DIAGONAL, IN LINE WITH THE BUTTERFLY. Lauren: "so its in line with the
     butterfly, not just random" — which is the constraint that settles this
     angle's SIGN, after four passes treated it as taste. 82deg leaned
     down-right, 98 stood near-vertical, -20 read as a rule across the page and
     -38 sat beside the butterfly rather than under it.

     The butterfly is pinned to the panels' corner, so the trail's axis has to
     pass through it. Extended upward, a down-LEFT trail runs back into the teal
     panel — there is no paper there to draw on, which is why every left-leaning
     version ended up merely near it. A down-RIGHT trail extends back up-left to
     exactly where the butterfly sits and falls across the open paper right of
     the panel. So +38deg, with the upper end placed just below and right of the
     butterfly, on the line through its centre.

     The gap is deliberate — "it doesn't need to be right up on the butterfly".
     z-index 3 against the butterfly's 4 still stands, so if it is ever moved
     back up they will overlap correctly rather than butt together. */
  /* MOVED ALONG ITS OWN AXIS, never straight up or straight across. Moving only
     `top` — or only `left` — slides the trail off the line through the butterfly
     and undoes the alignment above; at 38deg, every pixel across needs 0.78 down
     to stay on it. That governed the earlier raise, and the small move right on
     2026-08-26 (+15px at 1280, so +12 down with it). */
  left: 53.2%;
  top: 72.8%;
  width: min(215px, 17vw);
  opacity: 0.7;
  transform: rotate(38deg);
  z-index: 3;
  pointer-events: none;
}


/* ---------- The sketch butterfly in "You Don't Need To…"'s left margin ------
   2026-08-25. Lauren: "add the blue sketch butterfly on the left side of that
   section" and "then have a dotted line trail under it".

   THE GUTTER IS THE WHOLE OPPORTUNITY HERE. Measured at 1280: every line in this
   section — heading, both list columns, all three paragraphs — starts at x336,
   so 0-336 is bare paper for the section's full 576px. It is the widest clear
   margin on the page, and it is why this is the one section that takes a margin
   piece rather than something tucked against an edge.

   PERCENTAGES, NOT PIXELS, for the same reason the pair uses them: the section's
   height changes with how the copy wraps, and a piece pinned in pixels drifts out
   of its own composition the moment a line reflows.

   A DIFFERENT DRAWING FROM THE PAIR'S, deliberately. `path-dotted-flat` is a
   shallow arc where `path-dotted-noloop` above is an S-curve, and it runs level
   where that one runs at 38deg. Reusing the same trail twice on one page would
   read as a repeated element rather than as a recurring motif — the home page's
   grammar asks for rhymes, not duplicates. */
/* THE SIDE-VIEW DRAWING, `bfly-blue-side`. The open-wing `bfly-sketch-blue` went
   in first and Lauren corrected it — see the note in the markup.

   96px, WHICH IS BIGGER THAN EVERY OTHER USE OF THIS DRAWING and is the point.
   It appears four other times on the site — .twocol-tips-bfly at 55, .spark-corner-bfly
   at 68, .pillars-blue-bfly at 70, .reflections-blue-bfly at 76 — always tucked
   against something it is commenting on. Here it is the only thing in a 336px
   margin and carries its own composition, so it takes the top of the 88-115 band
   the grammar gives sketch and side butterflies rather than the bottom.

   RIGHT OF ITS TRAIL, and the two now sit side by side rather than stacked.
   Lauren, 2026-08-25: "move the butterfly to right, and the dotted line to the
   left of it, like its trail." The drawing faces right by export, so a trail
   BEHIND it means to its left — the butterfly has flown in from the page edge
   toward the copy, and the dots are where it has been. Stacked, the same two
   pieces read as a butterfly hovering above an unrelated mark.

   PUSHED RIGHT TWICE, 9.4% -> 12% -> 18%. Lauren: "move the butterfly to the
   right a bit. more." The painted butterfly now spans x225-332 at 1280 against
   text ink that starts at x377 — 45px of clear paper on its nose side, down from
   121. That is the floor for this piece: the text BOX edge is at x336, and only
   the centring of these lines puts their ink 41px further in. A section whose copy
   was set left rather than centred could not carry the butterfly this far over.

   -6deg, and the shallowness is what distinguishes it. The other four sit at -12,
   -20 and -22, all tucked in at a lean; this one is nearly level because nothing
   is holding it up. Negative still, so the page keeps one hand — the drawing faces
   right by export, and a negative tilt lifts its nose toward the copy it looks at.

   FADED, NOT TONED FURTHER. It is line art whose colour lives entirely in thin
   strokes, and it already carries the 0.58 grade; a second tone pass is what turns
   a drawing like this grey rather than quiet. */
.oto-neednt-bfly {
  position: absolute;
  left: 18%;
  top: 21%;
  width: min(96px, 7.5vw);
  opacity: 0.9;
  transform: rotate(-6deg);
  pointer-events: none;
}

.oto-neednt-path {
  position: absolute;
  /* UNDER THE ABDOMEN, which is not the same as under the butterfly. Lauren,
     2026-08-25, in two goes: "no under it", then "under the butterflys butt."
     Centring the arc on the drawing's bounding box put it under the WINGS, which
     is where the box's middle is — the body is well right of that.

     SO THE ANCHOR IS A POINT IN THE DRAWING, NOT A BOX EDGE. Read off the asset
     with a percentage grid over it: the abdomen tips out at 60% across and 87%
     down of the 320x355 source. Carried through the element's own -6deg rotation
     that lands at x292, y212 within the section at 1280, and the arc's high end is
     placed just under it. Every number below is derived from that one point.

     SO THIS MOVES WHENEVER THE BUTTERFLY MOVES. It is not parked at a round
     percentage; it is 3.7 points of width left of `.oto-neednt-bfly`, because that
     is what puts its high end under the abdomen. Shift the butterfly and shift this
     by the same amount, or the trail comes out from under a wing instead.

     A REAL GAP BELOW IT, because a trail touching the thing that made it reads as
     one joined object rather than as a path. The paint under the abdomen stops at
     y212 and the arc's near end is at y222.

     110px, DOWN FROM 215. Lauren: "the dotted line need to be smaller." At 215 it
     was longer than the butterfly was tall and dominated the pair; at 110 it is
     just over one butterfly-width, so the butterfly is what the eye lands on and
     the dots are what explain it. That is 1.1 : 1 against the butterfly, well
     under the 2 : 1 the home page's flight-to-butterfly ratio runs at — this is a
     short tail, not a flight path across a section.

     NOT below the butterfly's painted BASE, y240 — that is the hindwing's lowest
     point, over on the left, and hanging the trail under it would put the arc back
     beneath the wings. */
  /* VERTICAL, and the maths is not the same as for a lean. Lauren: "turn it
     vertical." Under rotate(-90deg) a point at (dx, dy) from the element's centre
     lands at (dy, -dx) — so the anchor offset swaps axes, and `left`/`top` both
     fall out of one equation rather than one each:
       centre = anchor - (dy, -dx),  where (dx, dy) is the path's END in the source.
     For this drawing the last dot sits at 98.9% across and 8.5% down of the 900x352
     file, which is (+83, -28) from centre at a 150px width, so the centre goes 28px
     RIGHT of the abdomen and 83px below it. RE-DERIVE BOTH IF THE WIDTH CHANGES —
     unlike a horizontal placement, neither value survives a resize on its own.

     The loop lands just under the butterfly rather than at the far end, because the
     path's looping end is the end the butterfly flew out of. Reversed, the drawing
     reads as a line that happens to have a curl in the middle of nowhere.

     MOVED LEFT OFF THE ABDOMEN, 2026-08-25 — Lauren: "move it to left." The anchor is
     no longer the abdomen point; it is 45px left of it, which puts the loop under the
     hindwing instead of under the body. That is what buys the room the bigger size
     needs: the painted trail runs well clear of text ink at x377, where staying on the
     abdomen would have pushed its right edge past x390.

     AND DOWN, 2026-08-25 — "move it a little down." The anchor is 22px below where it
     was, so the trail starts further under the wing rather than at its edge. */
  left: 6.67%;
  top: 57.6%;
  /* 150 -> 195 -> 240, over two asks: "a bit bigger its reading small", then "a
     little bigger still looks kinda small."

     SIZING THIS ASSET IS SIZING THE LOOP, which is why it kept reading small at
     lengths that had looked fine on the flat arc. The curl is about a sixth of the
     drawing's length: 25px across at 150, 33 at 195, 40 at 240. Below roughly 35 it
     stops registering as a loop at all and the piece goes back to being a generic
     dotted line — so the run of dots was never what needed the extra size.

     240 IS NEAR THE CEILING. The rotated box is 222 x 247, and this section is only
     576 tall with the copy starting at y335; the trail now paints down to y455 with
     121px of paper under it. Past about 260 it either reaches the section floor or
     the copy, depending on which way the extra goes. */
  width: min(240px, 18.75vw);
  opacity: 0.7;
  /* -52deg: vertical, tilted 38deg to the RIGHT. Lauren, in three goes: "tilt right",
     "tilt a little to the right", "tilt to the right" — -90 to -72 to -62 to -52. It
     is now the mirror of `.oto-pair-path`'s +38 up at the panels, which is a
     coincidence of numbers rather than a decision, but it does mean the page's two
     dotted trails lean the same amount in opposite directions. The near end is pinned at the top, so
     tilting right swings the FOOT left; the trail leans back under the butterfly
     rather than dropping away from it, which is what makes it read as attached. Dead
     vertical at -90 it hung like a plumb line.

     LEFT AND TOP MOVE WITH THE ANGLE. The anchor is a point inside the drawing, so
     every degree of rotation moves that point and both offsets have to be re-derived
     to put it back — this is why the numbers here are never round. Change the angle
     alone and the trail slides off the wing it hangs from.

     MIND THE SIGN: from -90, tilting right means moving TOWARD zero, not further from
     it; -105 would tilt it left. This angle has been -8, -22, -12 and -90 across one
     session, so it is worth writing down which way the number runs.

     It also leans the opposite way from the pair's +38 trail, so the two dotted
     pieces on this page never read as one repeated at two sizes. */
  transform: rotate(-52deg);
  pointer-events: none;
}

/* ---------- On a phone the pair breaks up, 2026-08-26 ----------
   Lauren: "in the you dont need to section, move that blue sketch butterfly above
   the title in the middle. and hide the dotted loop line."

   THE GUTTER THIS PAIR WAS BUILT FOR DOES NOT EXIST HERE. At 1280 every line in the
   section starts at x336, so 0-336 is bare paper for its full height — the widest
   clear margin on the page, and the whole reason the butterfly and its trail sit out
   there side by side. On a phone the list collapses to one column and every block
   runs full width: measured at 390 the leftmost ink is at x74 and the paragraphs
   below reach x21. Earlier passes kept trying to fit the pair into what was left of
   that margin, which is how the trail ended up brushing two lines of the list.

   SO THE BUTTERFLY TAKES A DIFFERENT JOB, not a smaller version of the same one. A
   centred mark above the heading is a position a phone actually has, and it is one
   the site already uses. It is the same drawing doing the same work — commenting on
   the section — against the layout that is there.

   AND THE TRAIL IS GONE. Lauren named it, which is the only way a decoration comes
   off this site — the standing rule is resize or reposition, never `display: none`
   at a breakpoint, because hiding decor deletes the visual story for most of her
   visitors. Named removals are a per-piece call and this is the fourth (see
   `.note-dot-path`, `.note-leaf-corner`, `.spark-corner-bfly`). It also stops making
   sense on its own once the butterfly moves: the trail is anchored to a point in the
   butterfly's abdomen, so with the butterfly centred above the heading there is
   nothing for it to trail from.

   The DESKTOP rules for both are untouched — the pair still works at 1280, where the
   margin it was built for is still there. */
@media (max-width: 760px) {
  /* CENTRED ON THE HEADING, and `left: 50%` alone does not centre a box — it puts
     its LEFT EDGE at the middle. The translate is what centres it, and the order
     matters: `translateX(-50%) rotate(-6deg)` rotates first and then shifts the
     finished drawing half its own width left, in screen axes. Written the other way
     round the translation happens in the rotated frame and the piece lands off to
     one side. Same trap as `.oto-corner-leaf`'s scaleX/rotate order. */
  .oto-neednt-bfly {
    /* px from the section's own top, NOT a percentage of it. The section's height
       changes with how the copy wraps — it is 681px at 390 and 630 at 430 — but the
       distance from its top edge to the heading does not, because that is the
       section's 3.5rem padding and one line box. A percentage here is the drift
       failure the mobile-anchoring notes record; px is stable.

       -5 lets it sit just above the section's own edge. The paper is continuous
       there — .oto-neednt has no background of its own — so the boundary is not a
       visible line and nothing crops it. It clears the heading's ink at y3570 by
       11px and the previous section's last line at y3332 by far more. */
    top: -5px;
    left: 50%;
    transform: translateX(-50%) rotate(-6deg);
    width: 13vw;
  }
  /* Removed by name, above. */
  .oto-neednt-path { display: none; }
}

/* On a phone the two panels STACK, so the corner this pair was placed against
   stops existing — the blue panel's bottom edge runs the full width and the teal
   panel is above it, not beside it. Rather than leave them floating at a
   junction that is no longer there, both move into the gap between the stacked
   panels, keeping the same gesture: butterfly on the left, trail off to its
   right. */
/* ON A PHONE THE PANELS STACK, so the corner this pair was placed against stops
   existing. They move to the seam between the two stacked panels — the same
   gesture, butterfly then trail, against the join that does exist here.

   MEASURED, because the gap is tight: the teal panel ends at y1980 and the blue
   begins at y2028, a 48px band of bare paper, and the section runs 1023-2601.
   A 26vw butterfly centred on that seam reaches ~29px into each panel, which
   their own bottom and top padding absorbs. Placed by eye instead, at 49.5%, it
   painted 1,341 pixels across "You don't necessarily have something you need to
   fix." — the widest collision anywhere on the page. */
/* THE WRAPPER IS INERT ON A DESKTOP. `display: contents` makes this div generate no
   box, so the two images inside it keep resolving against `.oto-pair` — the desktop
   offsets above are untouched by the markup change that added it. It only becomes a
   box, and an origin, on a phone. */
.oto-pair-seam { display: contents; }

/* ---------- On a phone they move to the seam, 2026-08-26 ----------
   Lauren: "move that and the dotted line image down, so it sits between the two
   sections."

   AND A PERCENTAGE CANNOT EXPRESS "THE SEAM". `.oto-pair`'s height is set by how the
   two panels' copy wraps, so the join between them sits at a different fraction of
   the section at every width — measured, 63.5% at 390 against 61.0% at 430, which
   put the pair 50px low there and dropped both pieces onto the blue panel. Tuning
   that percentage at one width is what moved them off the seam at the next.

   SO THE ORIGIN IS THE SEAM ITSELF. `.oto-pair-seam` is a zero-height grid item
   between the two panels; it lands on the teal panel's bottom edge by flow at every
   width and costs the layout nothing. The gap below it is `.oto-panel-blue`'s own
   3rem margin-top, so it is a constant 48px — the one measurement here that does not
   move. Offsets below are px from that edge.

   THEY READ ACROSS THE JOIN, NOT DOWN THROUGH IT — side by side along the seam
   rather than stacked, butterfly first and trail running off to its right. That is
   the desktop gesture (butterfly, then trail) put against the only join a phone has.

   THE TWO ARE HELD TO DIFFERENT RULES, deliberately. The band is 48px and the
   butterfly paints 79px tall, so it cannot fit and is not asked to: it straddles the
   join and overhangs into both panels, which is what makes it read as sitting ON the
   seam. The trail is sized to fit the band exactly and stay off both panels —
   Lauren's call, and it is why one is in vw and the other in px. */
@media (max-width: 760px) {
  .oto-pair-seam { display: block; position: relative; height: 0; }

  /* SIZED TO THE BAND. At 26vw and 31vw the pair did not fit and the trail's foot
     painted into "Joy is a compass" and the paragraph under it. */
  /* `top` IS PX FROM THE SEAM, AND IT IS NOT THE PAINTED TOP. Both drawings are
     rotated, so the painted ink starts above the element's own box — 12px for the
     butterfly at this size. Re-derive these two if either width changes; they are
     measured, not offsets you can reason about from the numbers.

     +4 centres the painted butterfly on the 48px band: it paints 1982-2061 at 390
     against a gap of 1994-2042, so it overhangs into the teal above and the blue
     below and reads as sitting ON the join rather than in the gap. It is the
     subject, so it is the piece allowed to overhang.

     19% / 37%, both moved right together, 2026-08-26 — Lauren: "move them both to
     the right more", then "move the dotted line tiled down left". The two started
     at 7% and 30% and went right by the same 12 points, which is what preserves the
     gap between the butterfly and the head of its trail; the trail then came back
     5 points left and 14px down on its own.

     24vw, up from 21 — "make the butterfly a little bit bigger". It grows from its
     `left` edge, so this also closed the gap to the trail: the trail's head now
     starts 6px INSIDE the butterfly's painted box and disappears behind its wing.
     That is why the z-index pair matters — 4 against the trail's 3 — and it reads
     as the trail coming out from behind the butterfly rather than butting against
     it. */
  .oto-pair-bfly { left: 19%; top: 4px;  width: 24vw; }
  /* 12deg, AND IT IS READ OFF THE DRAWING RATHER THAN CHOSEN. Lauren: "i want the
     left end of the line to sit horizontal, its supposed to look like the
     butterflies trail." The left end is the end nearest the butterfly, so it is the
     end that has to leave level — a trail streams off the thing that made it, it
     does not start at an angle.

     path-dotted-noloop is a wave, not a straight line, so "horizontal" is a
     statement about its LEADING SEGMENT and nothing else. Sampling the asset's ink
     centroid in eight bands across its 900px width gives (51,333) (168,308)
     (282,347) (397,383) (491,270) (612,188) (729,148) (847,64): a gentle rise, a
     dip, then a strong climb. The first band to the second runs at -12.19deg, so
     rotate(12deg) cancels it and the dots leave the butterfly level before the wave
     lifts them away. RE-MEASURE THAT, don't adjust it by eye — a linear fit over the
     whole drawing says -19deg and the last two bands say -35, and neither is the end
     that matters.

     IT WAS 38, THEN 48. Both were the same misreading in different amounts: "tilt it
     down and left a little" was taken as steepening, which drops the tail — but it
     also swings the NEAR end up, which is exactly what stopped it reading as a
     trail. The flat angle is the one with a reason attached; the others were taste.

     120px, restored. At 48deg the drawing painted 54px tall and had to come down to
     92 to fit the band at all; level it paints 36 at 120 and still clears both
     panels. The size was a consequence of the angle, so it moved back when the angle
     did — worth knowing before shrinking this again.

     ---- Why this one is sized in px while the butterfly is in vw ----

     Lauren, 2026-08-26: "the dotted line needs to move to the right more and keep
     that so its only in the white space." THE BAND IS A CONSTANT 48px AT EVERY
     WIDTH — it is `.oto-panel-blue`'s own 3rem margin-top, not anything that scales
     — so a piece measured in vw grows out of it as the viewport widens. At 26vw it
     fitted at 390 and painted 4px onto the blue at 430, which is exactly the kind of
     failure that only shows at the width you did not tune. Sized in px it behaves
     the same everywhere the band does.

     120px, DERIVED FROM THE ANGLE. Painted height runs about 0.30 x the width at
     12deg, so 120 paints 36px tall inside a 48px band. Re-derive it if the tilt
     changes — at 48deg the same ratio was 0.485 and the ceiling was 92px. Steepening
     costs length, and that is the whole trade this piece makes.

     AND THE BAND IS NOT A RECTANGLE. Both panels are torn-paper, so the white
     between them varies with x — measured at 390 it is 64-70px tall around x60-180
     and narrows to a flat 49 from x240 rightward. Moving right means moving into
     the narrow part, which is why "further right" and "only in the white" had to be
     solved together rather than one after the other.

     Verified per column against both panels' masks — sampling each mask's own alpha
     rather than the boxes, since the boxes say the gap is 1994-2042 and the ink says
     otherwise. 0 painted pixels on either panel at 320, 390 and 430. */
  .oto-pair-path { left: 47.5%; top: -4px; width: 120px; transform: rotate(12deg); }
}
