/* ---------- Fonts (self-hosted) ---------- */
      @font-face { font-family: "SamsungOne"; src: url("/assets/fonts/SamsungOne-400.woff") format("woff"); font-weight: 400; font-display: swap; }
      @font-face { font-family: "SamsungOne"; src: url("/assets/fonts/SamsungOne-700.woff") format("woff"); font-weight: 700; font-display: swap; }
      @font-face { font-family: "Manrope"; src: url("/assets/fonts/Manrope.woff2") format("woff2"); font-weight: 200 800; font-display: swap; }
      @font-face { font-family: "Instrument Serif"; src: url("/assets/fonts/InstrumentSerif-400.woff2") format("woff2"); font-weight: 400; font-style: normal; font-display: swap; }
      @font-face { font-family: "Instrument Serif"; src: url("/assets/fonts/InstrumentSerif-400-italic.woff2") format("woff2"); font-weight: 400; font-style: italic; font-display: swap; }


      :root {
        --teal: #2db79c;
        --teal-deep: #1b7a66;
        --teal-bright: #45cdb2;
        --bg: #ffffff;
        --bg-soft: #f3f8f5;
        --mint: #e9f5ef;
        --surface: #ffffff;
        --ink: #0b0b0c;
        --ink-soft: #565656;
        --line: #e8ebe9;
        --hero-ink: #f4f7f5;
        --dark-panel: #101013;
        --shadow: 0 24px 48px -26px rgba(11, 11, 12, 0.15);
        --radius: 20px;
      }
      @media (prefers-color-scheme: dark) {
        :root {
          --teal-deep: #45cdb2;
          --bg: #0a0c0b;
          --bg-soft: #0f1512;
          --mint: #0d1a15;
          --surface: #131916;
          --ink: #f4f6f5;
          --ink-soft: #a9b4ae;
          --line: #232d28;
          --dark-panel: #050807;
          --shadow: 0 24px 48px -26px rgba(0, 0, 0, 0.55);
        }
      }

      * { box-sizing: border-box; }
      html { scroll-behavior: smooth; overscroll-behavior-y: none; }
      body {
        margin: 0;
        font-family: "SamsungOne", "Manrope", system-ui, -apple-system, "Segoe UI", sans-serif;
        background: var(--bg);
        color: var(--ink);
        font-size: 16.5px;
        line-height: 1.65;
        -webkit-font-smoothing: antialiased;
      }
      h1, h2, h3 { font-family: inherit; line-height: 1.15; margin: 0; letter-spacing: -0.015em; }
      p { margin: 0; }
      a { color: inherit; }
      img { max-width: 100%; display: block; }
      .wrap { max-width: 1200px; margin: 0 auto; padding: 0 24px; }
      section { padding: 176px 0; }
      /* Fragment jumps (nav, menu, footer) land clear of the sticky header */
      section[id], main[id] { scroll-margin-top: 84px; }
      ::selection { background: color-mix(in srgb, var(--teal) 26%, transparent); }
      section[id] { scroll-margin-top: 76px; }

      .section-head { margin-bottom: 88px; position: relative; z-index: 0; }
      .section-head h2 { font-size: clamp(34px, 4.6vw, 54px); font-weight: 600; letter-spacing: -0.025em; line-height: 1.08; }

      /* Serif accent words inside headlines (Incroy-style) */
      .serif-accent {
        font-family: "Instrument Serif", Georgia, serif;
        font-style: italic; font-weight: 400; color: var(--teal);
        letter-spacing: 0;
      }

      /* ---------- Progressive disclosure ---------- */
      .d-body { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 0.7s cubic-bezier(0.33, 1, 0.68, 1); }
      .d-inner { overflow: hidden; min-height: 0; }
      .disc.open .d-body { grid-template-rows: 1fr; }
      .chev { flex: none; color: var(--teal-deep); transition: transform 0.55s cubic-bezier(0.33, 1.15, 0.64, 1); }
      .disc.open .chev { transform: rotate(180deg); }

      /* Bubble bloom: an expandable pill opens like a soft bubble —
         a gentle swell with barely-there overshoot and no jiggle,
         on a slower, silky ease; closing eases back the same way.
         Classes are added by JS on toggle (skipped under
         prefers-reduced-motion). */
      @keyframes bubblePop {
        0% { transform: scale(0.982, 0.968); }
        42% { transform: scale(1.007, 1.009); }
        68% { transform: scale(0.998, 0.997); }
        100% { transform: scale(1, 1); }
      }
      @keyframes bubbleSettle {
        0% { transform: scale(1.005, 1.007); }
        60% { transform: scale(0.997, 0.996); }
        100% { transform: scale(1, 1); }
      }
      .disc.blooming { animation: bubblePop 0.85s cubic-bezier(0.33, 1, 0.68, 1); transform-origin: center 30%; }
      .disc.settling { animation: bubbleSettle 0.7s cubic-bezier(0.33, 1, 0.68, 1); transform-origin: center 30%; }

      /* ---------- Buttons ---------- */
      .btn {
        display: inline-flex; align-items: center; justify-content: center; gap: 8px;
        font-weight: 600; font-size: 15.5px; min-height: 48px;
        text-decoration: none; cursor: pointer; border: 0;
        padding: 12px 28px; border-radius: 999px;
        transition: transform 0.45s cubic-bezier(0.34, 1.9, 0.64, 1), background 0.25s ease, border-color 0.25s ease, color 0.25s ease;
      }
      .btn:active { transform: scale(0.95, 0.9); }
      .btn-teal { background: var(--teal); color: #06231c; }
      .btn-teal:hover { background: var(--teal-bright); }
      .btn-dark, .btn-ghost { background: var(--ink); color: var(--bg); }
      .btn-dark:hover, .btn-ghost:hover { background: color-mix(in srgb, var(--ink) 82%, var(--teal)); }
      .btn-sm { padding: 9px 20px; font-size: 14.5px; min-height: 40px; }

      /* ---------- Nav ---------- */
      /* The header rests at the top of the screen; once the
         visitor scrolls down a little it glides up out of the
         way (the script toggles .nav-hidden by scroll
         direction), and the first upward scroll anywhere on
         the site glides it back. The slide is a transform
         only — the sticky box keeps its place in the flow,
         so nothing beneath it ever shifts — and whenever
         the menu is open or keyboard focus is inside it,
         the header stays put. */
      .nav {
        position: sticky; top: 0; z-index: 50;
        background: color-mix(in srgb, var(--bg) 86%, transparent);
        backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
        border-bottom: 1px solid transparent;
        transition: transform 0.45s cubic-bezier(0.22, 1, 0.36, 1), border-color 0.25s ease;
      }
      .nav.nav-hidden { transform: translateY(-102%); }
      /* Keyboard focus inside the header keeps it on screen
         (:focus-visible only matches keyboard-driven focus,
         so a tapped tab or link never pins it open against a
         scroll). */
      .nav.nav-hidden:has(:focus-visible) { transform: none; }
      @media print { .nav.nav-hidden { transform: none; } }
      .nav.scrolled { border-bottom-color: var(--line); }
      .nav-inner { display: flex; align-items: center; justify-content: space-between; gap: 20px; height: 64px; }
      /* The logo link never flex-shrinks: a squeezed flex item would cap
         the image at the shrunken width while its height stays fixed,
         visibly squashing the wordmark */
      .nav-logo { flex: none; }
      .nav-logo img { height: 25px; width: auto; }
      .nav-links { display: flex; align-items: center; gap: 28px; }
      .nav-links a { text-decoration: none; font-weight: 700; font-size: 14.5px; color: var(--ink-soft); transition: color 0.2s; }
      .nav-links a:hover { color: var(--teal-deep); }
      .nav-links a.btn { color: #06231c; }
      .menu-btn { display: none; flex: none; background: none; border: 0; cursor: pointer; padding: 8px; color: var(--ink); }
      /* Menu button: a 3x3 grid of small teal dots (Incroy-style).
         While the menu is open the dots reshape into an X — the
         edge dots fold away and the corners draw in toward the
         center dot; closing the menu reverses the morph. */
      .menu-dots { display: grid; grid-template-columns: repeat(3, 5px); gap: 4px; padding: 2px; }
      .menu-dots i {
        width: 5px; height: 5px; border-radius: 50%; background: var(--teal);
        transition: transform 0.5s cubic-bezier(0.34, 1.35, 0.64, 1), opacity 0.3s ease;
      }
      .menu-btn.open .menu-dots i:nth-child(2),
      .menu-btn.open .menu-dots i:nth-child(4),
      .menu-btn.open .menu-dots i:nth-child(6),
      .menu-btn.open .menu-dots i:nth-child(8) { transform: scale(0.2); opacity: 0; }
      .menu-btn.open .menu-dots i:nth-child(1) { transform: translate(2.5px, 2.5px) scale(1.15); }
      .menu-btn.open .menu-dots i:nth-child(3) { transform: translate(-2.5px, 2.5px) scale(1.15); }
      .menu-btn.open .menu-dots i:nth-child(5) { transform: scale(1.15); }
      .menu-btn.open .menu-dots i:nth-child(7) { transform: translate(2.5px, -2.5px) scale(1.15); }
      .menu-btn.open .menu-dots i:nth-child(9) { transform: translate(-2.5px, -2.5px) scale(1.15); }
      /* Menu pop-up: a compact floating card under the dot-grid
         button — the main destinations plus a WhatsApp chat
         link at the bottom, set large with generous spacing.
         A transparent full-screen backdrop sits behind it
         while open, so a tap anywhere else dismisses. */
      .mobile-menu {
        display: none;
        position: absolute; top: calc(100% + 10px);
        right: max(16px, calc((100vw - 1200px) / 2 + 24px));
        width: 256px; max-width: calc(100vw - 32px);
        background: var(--surface); border: 1px solid var(--line);
        border-radius: 20px; box-shadow: var(--shadow); padding: 10px;
      }
      .mobile-menu a, .mobile-menu .mm-view {
        display: block; width: 100%; text-align: left;
        padding: 13px 16px; border-radius: 12px;
        font-size: 21px; font-weight: 700; letter-spacing: -0.01em; line-height: 1.25;
        color: var(--ink); text-decoration: none;
        transition: background 0.18s ease, color 0.18s ease;
      }
      .mobile-menu a:hover, .mobile-menu .mm-view:hover { background: var(--bg-soft); color: var(--teal-deep); }
      .mobile-menu.open { display: block; animation: bubbleIn 0.45s cubic-bezier(0.22, 1, 0.36, 1); transform-origin: top right; }
      .menu-backdrop { position: fixed; inset: 0; z-index: 49; background: transparent; }
      .menu-backdrop[hidden] { display: none; }

      /* ---------- Hero: the statement is the whole opening ----------
         The hero is a tall runway; its content stays pinned
         (sticky) while scrolling scrubs the statement into view:
         the line — "Design that makes your business impossible
         to ignore." — is set very large in Instrument Serif,
         centered. The first screen shows only "Design", its
         letters rippling in a gentle wave; as the visitor
         scrolls, the wave settles and the remaining words appear
         one by one, scrubbed by scroll position, until the
         completed headline stands alone, centered, on its own
         screen. No overflow clipping on the section — that
         would break the pin. */
      .hero {
        position: relative;
        height: 200vh; height: 200svh;
        padding: 0;
      }
      .hero-sticky {
        position: sticky; top: 64px;
        height: calc(100vh - 64px); height: calc(100svh - 64px);
        display: flex; align-items: center; justify-content: center;
      }
      .hero-sticky::before {
        content: ""; position: absolute; inset: 0; pointer-events: none;
        background-image: radial-gradient(circle, color-mix(in srgb, var(--teal) 26%, transparent) 1.4px, transparent 1.9px);
        background-size: 30px 30px; background-position: center;
        -webkit-mask-image: radial-gradient(ellipse 58% 54% at 50% 46%, #000 18%, transparent 68%);
        mask-image: radial-gradient(ellipse 58% 54% at 50% 46%, #000 18%, transparent 68%);
        opacity: 0.34;
      }
      /* The estimator follows the hero in plain document flow:
         no overlap, no cover-slide — once the hero runway ends
         the hero scrolls away with the page and this section
         simply comes next, on the normal page background. Its
         content carries the site's standard .reveal on the
         section wrap, so the whole section fades up gently as
         one piece as it comes into view — that fade-up is the
         transition from the first page into what follows. */
      /* will-change: the hero scrub drives this block's
         transform every frame (the centering shift that eases
         away as the words land) */
      .hero-inner { position: relative; width: 100%; text-align: center; will-change: transform; }
      /* One statement, set in Instrument Serif at a calm, very
         large size — the final words in teal italic serif */
      .hero-statement {
        font-family: "Instrument Serif", Georgia, serif;
        font-weight: 400; letter-spacing: -0.01em;
        font-size: clamp(46px, 8.6vw, 112px);
        line-height: 1.16;
        max-width: 1040px; margin: 0 auto;
      }
      .hero h1 .accent { color: var(--teal); font-style: italic; }

      /* The first screen is the word "Design" alone: it sits on
         its own centered line at the top of the statement, and
         its letters ripple in a gentle traveling wave (each
         letter offset a beat from the last), looping while the
         visitor hasn't scrolled. The hero scrub eases --wave-amp
         to 0 as scrolling starts, so the wave settles flat
         before the rest of the statement lights up. */
      .hero h1 .design-word { display: block; }
      .hero h1 .design-word .dw {
        display: inline-block;
        animation: designWave 2.8s ease-in-out infinite;
        animation-delay: calc(var(--li, 0) * -0.22s);
      }
      @keyframes designWave {
        0%, 100% { transform: translateY(0); }
        50% { transform: translateY(calc(var(--wave-amp, 1) * -0.075em)); }
      }
      .hero h1.wave-off .design-word .dw { animation: none; }
      .sr-only {
        position: absolute; width: 1px; height: 1px;
        overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
      }

      /* ---------- Assembly: a design assembling itself ----------
         Between the hero and the estimator, a scroll runway
         giving about a screen and a half of scroll travel
         with a sticky stage on the
         plain page background. On the stage sits an abstract
         composition built only from graphic pieces in the
         site's palette — no images at all: a large brand-teal
         circle, a soft mint ring, a near-black bar, a small
         teal square, and a big Instrument Serif "Aa" at the
         center. At the top of the runway the pieces sit
         scattered — pushed out toward the edges, rotated,
         some shrunk — and JS (below) scrubs every piece into
         place as the visitor scrolls: offsets shrink to zero,
         rotations settle flat, scales land at their final
         size, until the composition stands assembled partway
         down the runway. As each piece lands, a very soft
         shadow gathers under it (the --sh custom property,
         scrubbed by the same JS), so the finished arrangement
         reads as a designed poster with a hint of depth
         rather than flat clip shapes. The scrub is a
         palindrome across the runway with no rest in the
         middle: the pieces assemble over the first half,
         and the instant the composition stands complete,
         continued scrolling flows straight into the
         disassembly — the pieces retrace their paths back
         outward over the second half until the stage leaves
         and the estimator arrives, one continuous
         through-motion with no pin, no hold, and no break
         at the peak. Scrolling back replays the whole
         palindrome in exact mirror. All
         of it is a pure function of scroll position — nothing
         is timed, nothing plays on its own. The stage clips
         its own overflow, so scattered pieces can never
         widen the page. Under prefers-reduced-motion the
         runway collapses (rules below) and the finished
         composition rests static. */
      .assemble {
        position: relative;
        height: 250vh; height: 250svh;
        padding: 0;
      }
      .assemble-stage {
        position: sticky; top: 64px;
        height: calc(100vh - 64px); height: calc(100svh - 64px);
        display: flex; align-items: center; justify-content: center;
        overflow: hidden;
      }
      /* The composition is a square artboard; every piece is
         placed in percentages of it, so the layout scales
         whole from phone to desktop. Sizes that should track
         the artboard use cqw (the artboard is a container). */
      .assemble-comp {
        position: relative; flex: none;
        width: min(560px, 88vw);
        aspect-ratio: 1 / 1;
        container-type: inline-size;
      }
      /* will-change: the scroll scrub drives every piece's
         transform each frame while the runway passes.
         --sh (0..1) is scrubbed by the same JS: each piece's
         soft shadow fades in as the piece lands, and sits at
         full strength in the assembled state (the default 1
         is what the static reduced-motion / no-JS state
         shows). */
      .piece { position: absolute; will-change: transform; --sh: 1; }
      .piece-circle {
        width: 50%; aspect-ratio: 1 / 1; left: 1%; top: 4%;
        background: var(--teal); border-radius: 50%;
        box-shadow: 0 calc(18px * var(--sh)) calc(36px * var(--sh)) rgb(13 60 50 / calc(0.24 * var(--sh)));
      }
      .piece-ring {
        width: 42%; aspect-ratio: 1 / 1; right: -1%; top: 37%;
        border-radius: 50%;
        border: 16px solid color-mix(in srgb, var(--teal) 34%, var(--bg));
        border-width: clamp(10px, 2.8cqw, 16px);
        filter: drop-shadow(0 calc(12px * var(--sh)) calc(16px * var(--sh)) rgb(13 60 50 / calc(0.18 * var(--sh))));
      }
      .piece-bar {
        width: 50%; height: 6%; left: 7%; bottom: 15%;
        background: var(--dark-panel); border-radius: 6px;
        box-shadow: 0 calc(14px * var(--sh)) calc(28px * var(--sh)) rgb(11 11 12 / calc(0.20 * var(--sh)));
      }
      .piece-square {
        width: 11%; aspect-ratio: 1 / 1; right: 11%; bottom: 8%;
        background: var(--teal); border-radius: 20%;
        box-shadow: 0 calc(12px * var(--sh)) calc(24px * var(--sh)) rgb(13 60 50 / calc(0.22 * var(--sh)));
      }
      /* The central piece: the serif glyph, its second letter
         in the teal italic the site uses for accent words */
      .piece-glyph {
        inset: 0; z-index: 2;
        display: grid; place-items: center;
        font-family: "Instrument Serif", Georgia, serif;
        font-weight: 400; line-height: 1;
        font-size: clamp(120px, 28vw, 270px);
        font-size: 50cqw;
        color: var(--ink);
        text-shadow: 0 calc(12px * var(--sh)) calc(28px * var(--sh)) rgb(11 11 12 / calc(0.10 * var(--sh)));
      }
      .piece-glyph .glyph-a { color: var(--teal); font-style: italic; }

      /* ---------- Estimator ---------- */
      .est-box { max-width: 720px; margin: 0 auto; }
      .est-form { display: flex; gap: 10px; }
      .est-form input {
        flex: 1; min-width: 0; font: inherit; font-size: 16.5px; color: var(--ink);
        background: var(--surface); border: 1.5px solid var(--line); border-radius: 999px;
        padding: 14px 22px; appearance: none;
      }
      .est-form input:focus {
        outline: none; border-color: var(--teal);
        box-shadow: 0 0 0 4px color-mix(in srgb, var(--teal) 18%, transparent);
      }
      .est-form .btn { flex: none; }
      .chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 22px; }
      .chip {
        font: inherit; font-size: 14px; font-weight: 600; color: var(--ink-soft);
        background: var(--bg-soft); border: 1px solid transparent; border-radius: 999px;
        padding: 9px 17px; cursor: pointer; min-height: 40px;
        transition: background 0.18s ease, color 0.18s ease, transform 0.45s cubic-bezier(0.34, 1.9, 0.64, 1);
      }
      .chip:hover { background: var(--mint); color: var(--teal-deep); }
      .chip:active { transform: scale(0.92, 0.88); }
      .est-result { margin-top: 42px; }
      .est-result[hidden] { display: none; }
      .est-result.show { animation: bubbleIn 0.85s cubic-bezier(0.22, 1, 0.36, 1); }
      @keyframes estIn { from { opacity: 0; transform: translateY(12px) scale(0.99); } to { opacity: 1; transform: none; } }
      /* Sheets and result cards bloom in like a soft bubble: a gentle
         swell up to size with only a whisper of overshoot, on a
         slower, silky ease — no bounce */
      @keyframes bubbleIn {
        0% { opacity: 0; transform: scale(0.955, 0.94) translateY(10px); }
        58% { opacity: 1; transform: scale(1.005, 1.007) translateY(-1px); }
        100% { opacity: 1; transform: scale(1, 1) translateY(0); }
      }
      .est-card {
        background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
        padding: 34px 32px; box-shadow: var(--shadow);
      }
      .est-card .est-tag { font-size: 13.5px; font-weight: 700; color: var(--teal-deep); }
      .est-card h3 { font-size: 24px; font-weight: 600; margin-top: 8px; }
      .est-card .est-why { margin-top: 8px; color: var(--ink-soft); font-size: 16px; max-width: 520px; }
      .est-meta { display: flex; flex-wrap: wrap; gap: 28px 44px; margin-top: 24px; padding-top: 22px; border-top: 1px solid var(--line); }
      .est-meta .m-label { font-size: 12.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-soft); }
      .est-meta .m-value { font-size: 21px; font-weight: 700; margin-top: 2px; }
      .est-meta .m-note { font-size: 13.5px; font-weight: 700; color: var(--teal-deep); }
      .est-card .btn { margin-top: 26px; }

      /* ---------- Services: an elegant tap-to-open list ----------
         Each row shows only its large italic serif number, title
         and one-liner. Tapping the row blooms it open (the .disc
         bubble motion, accordion-style — opening one closes the
         others) to reveal the short detail and its "See ___"
         button inside. Hairline rules between rows, generous air,
         a soft tint on hover/press, and each row rising in as
         it scrolls into view (the entrance rules below). */
      .svc-list { max-width: 920px; margin: 0 auto; --svc-numw: 168px; --svc-gap: 48px; --svc-pad: 10px; }
      .svc-row { border-top: 1px solid var(--line); }
      .svc-row:first-child { border-top: 0; }
      .svc-head {
        display: grid; grid-template-columns: var(--svc-numw) 1fr auto; gap: 8px var(--svc-gap);
        align-items: center; width: 100%;
        padding: 40px var(--svc-pad);
        background: none; border: 0; border-radius: 20px;
        font: inherit; color: inherit; text-align: left; cursor: pointer;
        transition: background 0.3s ease;
      }
      .svc-row:first-child .svc-head { padding-top: 26px; }
      .svc-head:hover { background: color-mix(in srgb, var(--teal) 6%, transparent); }
      .svc-head:active { background: color-mix(in srgb, var(--teal) 11%, transparent); }
      .svc-head:focus-visible { outline: 3px solid var(--teal); outline-offset: -3px; }
      .svc-num {
        font-family: "Instrument Serif", Georgia, serif; font-style: italic; font-weight: 400;
        font-size: clamp(66px, 7.6vw, 98px); line-height: 0.92;
        color: var(--teal-deep);
      }
      .svc-title { display: block; font-size: clamp(23px, 2.6vw, 29px); font-weight: 600; letter-spacing: -0.02em; line-height: 1.15; }
      .svc-line { display: block; margin-top: 7px; font-size: 17.5px; font-weight: 600; }
      .svc-more { padding: 0 var(--svc-pad) 44px calc(var(--svc-pad) + var(--svc-numw) + var(--svc-gap)); }
      .svc-detail { color: var(--ink-soft); font-size: 16px; max-width: 520px; }
      .svc-more .btn { margin-top: 20px; }
      /* The entrance: each row comes out on its own, the
         moment IT scrolls into view — softly rising and
         fading into place on a smooth ease with no bounce —
         so scrolling down the list, every row is seen
         arriving: the first as you reach it, then the next
         few as you come to them. Rows that enter in the same
         observer beat stagger ~90ms apart (JS sets that
         delay inline, for that beat only). The rise travels
         a little further and settles a touch longer than it
         used to — the same feeling, slightly more present.
         The entrance REPLAYS on every pass, both directions:
         once a row has fully left the viewport, JS quietly
         snaps it back to this pre-state (no transition, while
         it is off screen, so nothing flickers), and the next
         time it enters — from below or from above — it rises
         and fades in again. A row that is even partly on
         screen never resets, and an entrance never restarts
         mid-play. (The earlier version keyed all six rows
         off the LIST entering, so the lower rows finished
         their entrance below the fold, unseen — it read as
         no effect at all; a later one played each row once
         and never again.) Under prefers-reduced-motion and
         in print the rows simply show (see those blocks
         below). */
      .js .svc-list .svc-row {
        opacity: 0; transform: translateY(38px);
        transition: opacity 0.95s ease, transform 1.08s cubic-bezier(0.22, 1, 0.36, 1);
      }
      .js .svc-list .svc-row.in { opacity: 1; transform: none; }
      /* The quiet reset: applied for a single frame while the
         row is fully off screen, so dropping .in snaps it back
         to the pre-state instead of fading where no one can
         see — and the next entrance starts clean. */
      .js .svc-list .svc-row.snap { transition: none !important; }

      /* ---------- Packages ---------- */
      .packages { background: var(--bg); }
      .pkg-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 32px; align-items: stretch; max-width: 920px; margin: 0 auto; }
      .pkg {
        background: var(--surface); border: 1px solid var(--line); border-radius: 24px;
        padding: 58px 48px 46px; display: flex; flex-direction: column; position: relative;
        cursor: pointer;
        box-shadow: 0 10px 28px -24px rgba(11, 11, 12, 0.10);
        transition: transform 0.45s cubic-bezier(0.34, 1.45, 0.64, 1), box-shadow 0.3s ease, border-color 0.3s ease;
      }
      /* The cards rise in on a soft spring — a longer, gentler
         settle than the standard reveal, rising further and
         un-scaling as they land — then transform hands back to
         the hover/press rules above */
      .js .pkg.reveal {
        transition: opacity 0.85s ease, transform 1.1s cubic-bezier(0.34, 1.45, 0.64, 1);
        transition-delay: var(--rd, 0s);
      }
      .js .pkg.reveal:not(.in) { transform: translateY(30px) scale(0.965); }
      .js .pkg.reveal.in {
        transition: transform 0.45s cubic-bezier(0.34, 1.45, 0.64, 1), box-shadow 0.3s ease, border-color 0.3s ease;
      }
      .pkg:hover { transform: translateY(-4px); border-color: var(--teal); box-shadow: 0 22px 44px -28px rgba(16, 54, 44, 0.18); }
      .pkg:active { transform: translateY(-1px) scale(0.98, 0.97); }
      .pkg:focus-visible { outline: 3px solid var(--teal); outline-offset: 3px; }
      /* The featured card stays light like its pair — a whisper of
         teal in the ground and a softer teal hairline set it apart,
         nothing heavier */
      .pkg.featured { background: color-mix(in srgb, var(--teal) 4%, var(--surface)); border-color: color-mix(in srgb, var(--teal) 38%, var(--line)); }
      .pkg.featured:hover { border-color: var(--teal); box-shadow: 0 22px 44px -28px rgba(16, 54, 44, 0.20); }
      .pkg h3 { font-size: 26px; font-weight: 600; letter-spacing: -0.02em; }
      .pkg .pkg-sub { margin-top: 10px; font-size: 15.5px; line-height: 1.55; color: var(--ink-soft); max-width: 340px; }
      /* The price is set in the site's serif, on a shared baseline
         row of one fixed height, so both cards keep the same rhythm
         whether the price is a figure or words */
      .price { margin: 36px 0 6px; min-height: 58px; display: flex; align-items: baseline; }
      .price .amount { font-family: "Instrument Serif", Georgia, serif; font-weight: 400; font-size: 58px; line-height: 1; letter-spacing: 0; }
      .price .amount.text { font-size: 42px; }
      .price .cur { font-size: 15px; font-weight: 700; color: var(--ink-soft); margin-left: 7px; }
      .price-note { font-size: 13.5px; font-weight: 700; color: var(--teal-deep); }
      .pkg ul { list-style: none; margin: 30px 0 36px; padding: 24px 0 0; border-top: 1px solid var(--line); display: grid; gap: 12px; }
      .pkg li { display: flex; gap: 10px; font-size: 15px; align-items: flex-start; }
      .pkg li svg { flex: none; margin-top: 3px; }
      .pkg-foot { margin-top: auto; display: flex; align-items: center; justify-content: space-between; gap: 14px; }
      .pkg-time { font-size: 13.5px; font-weight: 700; color: var(--ink-soft); }
      .pkg-more {
        flex: none; display: inline-flex; align-items: center; gap: 7px;
        font-size: 14.5px; font-weight: 700; color: var(--teal-deep);
      }
      .pkg-more svg { transition: transform 0.22s ease; }
      .pkg:hover .pkg-more svg { transform: translateX(3px); }
      .badge {
        position: absolute; top: -12px; left: 48px;
        background: var(--teal); color: #06231c;
        font-size: 11.5px; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase;
        padding: 5px 12px; border-radius: 999px;
      }
      .pkg-footnote { margin-top: 36px; text-align: center; color: var(--ink-soft); font-size: 14.5px; }
      .pkg-footnote strong { color: var(--ink); }

      /* ---------- Package modal ---------- */
      .pkg-overlay {
        position: fixed; inset: 0; z-index: 90;
        background: rgba(8, 26, 21, 0.46);
        backdrop-filter: blur(5px); -webkit-backdrop-filter: blur(5px);
        display: flex; overflow-y: auto; padding: 20px 14px;
        animation: overlayFade 0.45s ease;
      }
      .pkg-overlay[hidden] { display: none; }
      @keyframes overlayFade { from { opacity: 0; } to { opacity: 1; } }
      /* The sheet blooms open with the same soft spring as the
         cards' entrance: up from slightly small, a whisper of
         overshoot, then it settles flat */
      @keyframes sheetBloom {
        0% { opacity: 0; transform: scale(0.94, 0.925) translateY(16px); }
        55% { opacity: 1; transform: scale(1.008, 1.01) translateY(-2px); }
        78% { transform: scale(0.998, 0.997) translateY(0); }
        100% { opacity: 1; transform: scale(1, 1) translateY(0); }
      }
      .pkg-sheet {
        margin: auto; width: 100%; max-width: 480px;
        background: var(--surface); border: 1px solid var(--line); border-radius: 24px;
        padding: 30px 30px 32px; box-shadow: var(--shadow);
        animation: sheetBloom 0.95s cubic-bezier(0.22, 1, 0.36, 1);
      }
      .pkg-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }
      .pkg-tag { font-size: 12.5px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--teal-deep); }
      .pkg-sheet h3 { font-size: 26px; font-weight: 700; margin-top: 6px; letter-spacing: -0.02em; }
      .pkg-close {
        flex: none; width: 42px; height: 42px; border-radius: 50%;
        background: var(--bg-soft); border: 1px solid var(--line); color: var(--ink);
        display: grid; place-items: center; cursor: pointer;
        transition: transform 0.4s cubic-bezier(0.34, 1.8, 0.64, 1), background 0.2s ease;
      }
      .pkg-close:active { transform: scale(0.88); }
      .pkg-blurb { margin-top: 10px; color: var(--ink-soft); font-size: 16px; }
      .pkg-price-row {
        display: flex; flex-wrap: wrap; gap: 20px 48px;
        margin-top: 24px; padding: 20px 0;
        border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
      }
      .pkg-price-row .m-label { font-size: 12.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-soft); }
      .pkg-price { font-size: 22px; font-weight: 700; margin-top: 2px; }
      .pkg-price-note { font-size: 13.5px; font-weight: 700; color: var(--teal-deep); }
      .pkg-inc-label { margin-top: 22px; font-size: 12.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-soft); }
      .pkg-inc { list-style: none; margin: 12px 0 0; padding: 0; display: grid; gap: 11px; }
      .pkg-inc li { display: flex; gap: 10px; font-size: 15.5px; align-items: flex-start; }
      .pkg-inc li svg { flex: none; margin-top: 3px; }
      .pkg-actions { display: grid; gap: 10px; margin-top: 26px; }
      .pkg-actions .btn { justify-content: center; min-height: 50px; }
      .btn-wa { background: var(--ink); color: var(--bg); }
      .btn-wa:hover { background: color-mix(in srgb, var(--ink) 82%, var(--teal)); }

      /* ---------- Process ---------- */
      .process { background: var(--mint); }
      .eyebrow {
        font-size: 13px; font-weight: 700; letter-spacing: 0.14em;
        text-transform: uppercase; color: var(--ink-soft); margin-bottom: 18px;
      }
      .squig { position: relative; white-space: nowrap; }
      .squiggle {
        position: absolute; left: 0; bottom: -0.24em;
        width: 100%; height: 0.26em; color: var(--teal);
      }
      /* The steps stack on scroll: each step is a card on the mint
         ground, sticky at its own offset — as the visitor scrolls,
         step 1 holds in place, step 2 slides up and lands over it,
         then 3 over 2, then 4 over 3, piling into a neat stack
         with a sliver of each earlier card peeking above the next.
         While the next step travels over it, JS scrubs the covered
         step's settle straight from scroll position — a slight
         shrink toward its top edge and a touch of dimming — so
         the pile glides in one continuous motion in both
         directions: no timed animation, no class snap, no spring.
         Fully covered, a step rests at scale 0.965 and
         brightness/saturate 0.96. */
      .steps-list { max-width: 920px; margin: 0 auto; padding-bottom: 24px; --peek: 14px; }
      .pstep {
        position: sticky; top: calc(82px + var(--si, 0) * var(--peek));
        display: grid; grid-template-columns: 168px 1fr; gap: 10px 48px;
        background: var(--surface);
        border: 1px solid color-mix(in srgb, var(--teal-deep) 18%, var(--line));
        border-radius: 26px;
        padding: 46px 48px;
        margin-bottom: 30px;
        box-shadow: 0 22px 42px -26px rgba(13, 60, 48, 0.28);
        transform-origin: 50% 0;
      }
      .pstep:last-child { margin-bottom: 0; }
      .pstep:nth-child(1) { --si: 0; }
      .pstep:nth-child(2) { --si: 1; }
      .pstep:nth-child(3) { --si: 2; }
      .pstep:nth-child(4) { --si: 3; }
      .pstep-num {
        font-family: "Instrument Serif", Georgia, serif; font-style: italic; font-weight: 400;
        font-size: clamp(66px, 7.6vw, 98px); line-height: 0.92;
        color: var(--teal-deep);
      }
      .pstep h3 { font-size: clamp(23px, 2.6vw, 29px); font-weight: 600; letter-spacing: -0.02em; }
      .pstep-line { margin-top: 7px; font-size: 17.5px; font-weight: 600; }
      .pstep-detail { margin-top: 8px; color: var(--ink-soft); font-size: 16px; max-width: 520px; }

      /* ---------- About: the one big teal moment ---------- */
      /* The teal lives on its own sheet layer (.about-sheet),
         not on the section, so the ending can play as one
         flowing sequence. The sheet is sized to a full
         screen plus the headline hold (and the section's top
         padding past the wrap's sticky offset), so as the
         visitor scrolls in, its curved top rises over the
         Process cards and the teal takes over the whole
         screen — headline and text sitting fully on the
         green, nothing else visible. Scrolling on through
         the text, the paragraph brightens word by word (see
         the scrub below) and completes right as the text
         comes to rest: the wrapper pins at screen center
         (see the slow-downs block below), so the name and
         info rest in the middle of the green, exactly where
         the section's gentle slow-down lands, and the
         full-green screen lingers for the hold. The pin
         range is exactly that hold — when it ends, the
         wrapper releases where it sits and from there the
         text scrolls at the sheet's own pace for the whole
         rise: headline, paragraphs and green go up together
         as one locked piece across the runway (the
         .about-lead stretch plus the .about-lift stretch,
         trimmed so the finale follows the panel closely).
         The sheet is
         sized so that at the release its bottom edge sits
         at the screen's bottom edge, a full half-screen of
         green below the text's last line, and that offset
         never changes during the rise — while any of the
         text is visible, the green fully backs it; the text
         never sticks out past the sheet. During the hold
         the pinned wrapper carries no drift at all: the
         text sits perfectly still at screen center until
         the release. Beneath the rising panel the contact
         pill waits parked at the center of the screen (see
         the curtain scrub in the script) and is simply
         uncovered as the sheet's bottom edge rises past it;
         the footer is not parked and follows in plain flow,
         arriving last and docking under the pill as the
         page ends — where a shorter screen leaves no room
         for both, the pill rides up with the docking footer
         into the end composition instead of sliding under
         it. Every state is a reversible
         function of scroll position, no timing, no bounce. */
      .about {
        color: #ffffff;
        margin-top: -84px; position: relative; z-index: 1;
        padding: 176px 0 88px; text-align: center;
      }
      .about-sheet {
        position: absolute; left: 0; right: 0; top: 0;
        /* Full screen + the hold + (top padding − the
           centered sticky offset): the offset is half a
           screen minus half the text block, so the viewport
           term folds into the constant. At the moment the
           pinned text releases, the sheet's bottom edge sits
           exactly at the screen's bottom edge — from there
           text and sheet rise locked together, the edge
           holding its distance below the text until both
           have left the screen. */
        height: calc(66vh + 286px); height: calc(66svh + 286px);
        background: var(--teal);
        border-top-left-radius: 50% 84px;
        border-top-right-radius: 50% 84px;
      }
      /* The lift runway, in two stretches of one scroll
         room, both outside the text's pin range: across the
         whole runway the released text rides the sheet, the
         two rising together as one locked piece. The runway
         is trimmed short on purpose: it carries the locked
         rise and no more, so once the panel has left the
         screen the contact finale follows after only a
         small beat instead of a long empty stretch. */
      .about-lead { height: 20vh; height: 20svh; }
      .about-lift { height: 36vh; height: 36svh; }
      .about-name {
        font-family: "Instrument Serif", Georgia, serif; font-weight: 400;
        font-size: clamp(46px, 6.4vw, 80px); letter-spacing: -0.01em; line-height: 1.05;
      }
      .about-role { margin-top: 16px; font-weight: 700; font-size: 16px; color: rgba(255, 255, 255, 0.85); }
      .about-text { margin: 26px auto 0; max-width: 560px; font-size: 18px; color: rgba(255, 255, 255, 0.94); }
      .about-text strong { color: #ffffff; }
      .about-text .aw { opacity: 0.28; }

      /* ---------- Contact: one big pill, then a quiet page ----------
         Home ends with a single pill button whose label rotates
         through a few greetings every few seconds; tapping it opens
         the contact page — a full-screen overlay holding one big,
         mostly-empty box: a fill-in-the-sentence form, a send
         pill, and the direct ways to reach Accia underneath. */
      .contact-cta { text-align: center; padding: 96px 0 96px; }
      .hello-btn {
        display: inline-flex; align-items: center; justify-content: center; gap: 16px;
        font: inherit; font-weight: 600; letter-spacing: -0.01em;
        font-size: clamp(21px, 3.2vw, 29px); line-height: 1.2;
        color: #06231c; background: var(--teal);
        border: 0; border-radius: 999px; cursor: pointer;
        padding: 25px 44px; min-height: 78px;
        box-shadow: 0 26px 46px -24px rgba(13, 84, 66, 0.5);
        transition: transform 0.45s cubic-bezier(0.34, 1.9, 0.64, 1), background 0.25s ease;
      }
      .hello-btn:hover { background: var(--teal-bright); }
      .hello-btn:active { transform: scale(0.96, 0.93); }
      .hello-btn:focus-visible { outline: 3px solid var(--teal-deep); outline-offset: 4px; }
      /* The phrases stack in one grid cell, so the pill keeps the
         width of the longest phrase while they crossfade */
      .hello-phrases { display: grid; }
      .hello-phrase {
        grid-area: 1 / 1; white-space: nowrap;
        opacity: 0; transform: translateY(9px);
        transition: opacity 0.55s ease, transform 0.55s ease;
      }
      .hello-phrase.on { opacity: 1; transform: none; }
      .hello-arrow { display: inline-flex; flex: none; animation: helloNudge 2.8s ease-in-out infinite; }
      @keyframes helloNudge { 0%, 100% { transform: translateX(0); } 50% { transform: translateX(6px); } }

      .contact-overlay {
        position: fixed; inset: 0; z-index: 92;
        background: var(--bg);
        display: flex; overflow-y: auto;
        padding: 28px 20px calc(28px + env(safe-area-inset-bottom, 0px));
      }
      .contact-overlay[hidden] { display: none; }
      .contact-sheet {
        position: relative; margin: auto; width: 100%; max-width: 620px;
        background: var(--surface); border: 1px solid var(--line); border-radius: 32px;
        padding: 76px 64px 60px; box-shadow: var(--shadow);
        animation: bubbleIn 0.85s cubic-bezier(0.22, 1, 0.36, 1);
      }
      .contact-close {
        position: absolute; top: 20px; right: 20px;
        width: 42px; height: 42px; border-radius: 50%;
        background: var(--bg-soft); border: 1px solid var(--line); color: var(--ink);
        display: grid; place-items: center; cursor: pointer;
        transition: transform 0.4s cubic-bezier(0.34, 1.8, 0.64, 1), background 0.2s ease;
      }
      .contact-close:hover { background: var(--mint); }
      .contact-close:active { transform: scale(0.88); }
      .contact-sheet h2 { font-size: clamp(30px, 4.2vw, 40px); font-weight: 600; letter-spacing: -0.025em; line-height: 1.1; text-align: center; }
      .contact-line { margin-top: 14px; text-align: center; color: var(--ink-soft); font-size: 16.5px; }
      /* The form is a single sentence set in the site's
         serif: the visitor fills three blanks inside it —
         no boxes, no labels, just a soft hairline under each
         blank and a faint italic hint while it stands empty.
         The blanks size themselves to what's typed
         (field-sizing, with a fixed fallback width), and the
         "I need" blank grows downward as the message gets
         longer. One teal Send pill sits below the sentence. */
      #contactForm { margin-top: 52px; }
      .sentence {
        font-family: "Instrument Serif", Georgia, serif;
        font-weight: 400; letter-spacing: 0;
        font-size: clamp(27px, 3.9vw, 37px);
        line-height: 1.75;
      }
      .blank {
        font: inherit; color: var(--ink);
        background: transparent; border: 0; border-radius: 0;
        border-bottom: 1.5px solid color-mix(in srgb, var(--ink-soft) 45%, transparent);
        padding: 0 4px 2px; margin: 0 1px;
        text-align: center; appearance: none;
        field-sizing: content;
        transition: border-color 0.2s ease;
      }
      input.blank { min-width: 3.5ch; max-width: 100%; }
      textarea.blank {
        display: inline-block; vertical-align: bottom;
        min-width: 12ch; max-width: 100%;
        resize: none; overflow: hidden; line-height: inherit;
      }
      .blank::placeholder { color: color-mix(in srgb, var(--ink-soft) 58%, transparent); font-style: italic; }
      .blank:focus { outline: none; border-bottom-color: var(--teal); }
      #contactForm .btn { display: flex; margin: 48px auto 0; padding: 14px 46px; min-height: 54px; font-size: 16.5px; }
      .form-hint { margin-top: 24px; text-align: center; font-size: 14.5px; color: var(--ink-soft); }
      .form-hint[hidden] { display: none; }
      /* After sending, the sentence and the pill step aside
         and one quiet serif line takes their place */
      #contactForm.sent .sentence, #contactForm.sent .btn, #contactForm.sent .form-hint { display: none; }
      .form-ok { text-align: center; animation: bubbleIn 0.85s cubic-bezier(0.22, 1, 0.36, 1); }
      .form-ok[hidden] { display: none; }
      .sent-line {
        font-family: "Instrument Serif", Georgia, serif; font-weight: 400;
        font-size: clamp(27px, 3.9vw, 37px); line-height: 1.4;
      }
      .sent-line em { color: var(--teal); }
      .sent-note { margin-top: 12px; font-size: 14.5px; color: var(--ink-soft); }
      /* The direct ways to reach Accia rest quietly under
         the form: one small row of plain text links, no
         buttons competing with the sentence */
      .contact-direct {
        margin-top: 68px; display: flex; justify-content: center; align-items: center;
        gap: 14px; flex-wrap: wrap; font-size: 15px;
      }
      .contact-direct a { font-weight: 600; color: var(--ink-soft); text-decoration: none; transition: color 0.2s ease; }
      .contact-direct a:hover { color: var(--teal-deep); }
      .contact-direct .dot { color: color-mix(in srgb, var(--ink-soft) 55%, transparent); }

      /* ---------- Campaigns view: stacked campaign blocks ----------
         Every campaign lives on this one page as a block: its
         name as a headline, then its designs in a clean grid —
         the posters grid's rhythm, each image shown whole at
         its natural ratio (never cropped or squashed). Blocks
         stack with only a small separation: a hairline and
         modest spacing, so a new campaign appended below reads
         as the next set, not a new page. Tapping an image opens
         the campaign viewer (the poster viewer's chrome), whose
         counter runs within that campaign's own set. */
      .campaign-block + .campaign-block {
        margin-top: 54px; padding-top: 46px;
        border-top: 1px solid var(--line);
      }
      .campaign-name {
        font-size: clamp(28px, 3.4vw, 40px); font-weight: 600;
        letter-spacing: -0.02em; line-height: 1.1;
        margin-bottom: 26px;
      }
      .campaign-grid {
        display: grid; grid-template-columns: repeat(3, 1fr);
        gap: 24px; align-items: start;
      }
      .campaign-item {
        padding: 0; border: 0; background: var(--bg-soft); cursor: pointer;
        border-radius: 16px; overflow: hidden; display: block; width: 100%;
        -webkit-tap-highlight-color: transparent;
      }
      .campaign-item:focus-visible { outline: 3px solid var(--teal); outline-offset: 3px; }
      .campaign-item img { width: 100%; height: auto; }
      @media (max-width: 720px) {
        .campaign-block + .campaign-block { margin-top: 42px; padding-top: 36px; }
        .campaign-name { margin-bottom: 20px; }
        .campaign-grid { grid-template-columns: repeat(2, 1fr); gap: 14px; }
        .campaign-item { border-radius: 12px; }
      }

      /* ---------- Collection pages: back pill ----------
         Logos, Posters and Campaigns open as their own pages;
         a small pill at the top takes the visitor back Home.
         These sections sit closer to the nav than Home's airy
         sections so the pill reads as page chrome, and the pill
         itself carries the site's springy press feel. */
      .collection { padding-top: 56px; }
      .back-row { margin-bottom: 46px; }
      .back-pill {
        display: inline-flex; align-items: center; gap: 8px;
        font: inherit; font-size: 15px; font-weight: 700; color: var(--ink);
        background: var(--bg-soft); border: 1px solid var(--line); border-radius: 999px;
        padding: 10px 22px 10px 17px; min-height: 44px; cursor: pointer;
        transition: transform 0.45s cubic-bezier(0.34, 1.9, 0.64, 1), background 0.2s ease, border-color 0.2s ease, color 0.2s ease;
        -webkit-tap-highlight-color: transparent;
      }
      .back-pill:hover { background: var(--mint); border-color: var(--teal); color: var(--teal-deep); }
      .back-pill:active { transform: scale(0.94, 0.9); }
      .back-pill:focus-visible { outline: 3px solid var(--teal); outline-offset: 3px; }
      .back-pill svg { flex: none; transition: transform 0.25s ease; }
      .back-pill:hover svg { transform: translateX(-2px); }

      /* ---------- Logos view ---------- */
      .logos-view-grid {
        display: grid; grid-template-columns: 1fr 1fr; gap: 30px;
        max-width: 920px; margin: 0 auto;
      }
      .logo-panel {
        position: relative; width: 100%;
        background: var(--bg-soft); border: 0; border-radius: 24px;
        padding: 26px; cursor: pointer;
        display: grid; place-items: center;
        -webkit-tap-highlight-color: transparent;
      }
      .logo-panel:focus-visible { outline: 3px solid var(--teal); outline-offset: 3px; }
      .logo-panel img { width: 100%; height: auto; display: block; border-radius: 14px; }
      /* Each panel also carries its full-size slides as real
         <img> elements inside this hidden span, so every slide
         is a directly-referenced image in the document (the
         viewer reads the list from these). Never rendered. */
      .logo-slide-refs { display: none !important; }
      /* Multi-slide entries carry a small badge on the image corner:
         a stack icon and the slide count, so visitors can tell
         there is a set to scroll inside */
      .logo-multi {
        position: absolute; top: 36px; right: 36px;
        display: inline-flex; align-items: center; gap: 5px;
        padding: 5px 9px; border-radius: 999px;
        background: rgba(10, 26, 21, 0.62); color: #ffffff;
        font-size: 12px; font-weight: 700; line-height: 1;
        backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px);
        pointer-events: none;
      }
      @media (max-width: 720px) {
        .logos-view-grid { grid-template-columns: 1fr; gap: 20px; }
        .logo-panel { padding: 18px; }
        .logo-multi { top: 26px; right: 26px; }
      }

      /* ---------- Marivon identity page ----------
         The Marivon Group entry opens as its own page: the
         logo and all twenty brand-identity deck pages stacked
         at natural aspect, like flipping through the deck —
         full-width on phone, a comfortable reading width on
         desktop. Tapping a page opens the logo viewer on it. */
      .marivon-stack {
        display: flex; flex-direction: column; gap: 30px;
        max-width: 880px; margin: 0 auto; padding-bottom: 56px;
      }
      .marivon-page {
        display: block; width: 100%; padding: 0; border: 0;
        background: var(--bg-soft); border-radius: 18px; overflow: hidden;
        cursor: pointer; -webkit-tap-highlight-color: transparent;
      }
      .marivon-page:focus-visible { outline: 3px solid var(--teal); outline-offset: 3px; }
      .marivon-page img { width: 100%; height: auto; display: block; }
      @media (max-width: 720px) {
        .marivon-stack { gap: 20px; }
        .marivon-page { border-radius: 14px; }
      }

      /* ---------- Posters view ---------- */
      .poster-grid {
        display: grid; grid-template-columns: repeat(3, 1fr);
        gap: 24px; align-items: start;
      }
      .poster-item {
        padding: 0; border: 0; background: var(--bg-soft); cursor: pointer;
        border-radius: 16px; overflow: hidden; display: block; width: 100%;
        -webkit-tap-highlight-color: transparent;
      }
      .poster-item:focus-visible { outline: 3px solid var(--teal); outline-offset: 3px; }
      .poster-item img { width: 100%; height: auto; }
      @media (max-width: 720px) {
        .poster-grid { grid-template-columns: repeat(2, 1fr); gap: 14px; }
        .poster-item { border-radius: 12px; }
      }

      /* ---------- Poster viewer ---------- */
      .poster-overlay {
        position: fixed; inset: 0; z-index: 95;
        background: rgba(6, 14, 11, 0.94);
        backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
        display: flex; flex-direction: column;
        padding: 16px 16px calc(18px + env(safe-area-inset-bottom, 0px));
      }
      .poster-overlay[hidden] { display: none; }
      .poster-top {
        display: flex; align-items: center; justify-content: space-between; gap: 16px;
        width: 100%; max-width: 1100px; margin: 0 auto;
      }
      .poster-count { color: rgba(255, 255, 255, 0.85); font-weight: 700; font-size: 15px; letter-spacing: 0.02em; }
      .poster-close {
        flex: none; width: 42px; height: 42px; border-radius: 50%;
        background: rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.22); color: #ffffff;
        display: grid; place-items: center; cursor: pointer;
        transition: transform 0.4s cubic-bezier(0.34, 1.8, 0.64, 1), background 0.2s ease;
      }
      .poster-close:hover { background: rgba(255, 255, 255, 0.2); }
      .poster-close:active { transform: scale(0.88); }
      .poster-stage {
        flex: 1; min-height: 0; display: flex; align-items: center; justify-content: center;
        width: 100%; max-width: 1100px; margin: 10px auto 0;
      }
      .poster-stage img {
        max-width: 100%; max-height: 100%; width: auto; height: auto;
        border-radius: 12px; box-shadow: 0 30px 60px -20px rgba(0, 0, 0, 0.6);
        animation: bubbleIn 0.6s cubic-bezier(0.22, 1, 0.36, 1);
      }
      .poster-navrow { display: flex; justify-content: center; gap: 12px; margin-top: 14px; }
      .poster-arrow {
        width: 52px; height: 52px; border-radius: 50%;
        background: rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.22); color: #ffffff;
        display: grid; place-items: center; cursor: pointer;
        transition: transform 0.4s cubic-bezier(0.34, 1.8, 0.64, 1), background 0.2s ease;
      }
      .poster-arrow:hover { background: rgba(255, 255, 255, 0.2); }
      .poster-arrow:active { transform: scale(0.88); }

      /* ---------- Floating WhatsApp ---------- */
      .wa-float {
        position: fixed;
        right: 22px;
        bottom: calc(22px + env(safe-area-inset-bottom, 0px));
        z-index: 60;
        width: 50px; height: 50px;
        border-radius: 50%;
        background: #25d366;
        color: #ffffff;
        display: grid; place-items: center;
        box-shadow: 0 6px 16px -6px rgba(18, 140, 90, 0.38), 0 2px 6px rgba(10, 47, 40, 0.08);
        transition: opacity 0.5s ease, transform 0.5s cubic-bezier(0.22, 0.61, 0.36, 1), background 0.2s ease, box-shadow 0.25s ease;
      }
      .wa-float svg { width: 24px; height: 27px; display: block; }
      .wa-float:focus-visible { outline: 3px solid var(--teal); outline-offset: 3px; }
      /* Hidden through the whole page; rises in gently (scale + fade,
         no bounce) only once the end of the page — the contact area
         or the footer below it — reaches the screen, and fades softly
         away again when the visitor scrolls back up */
      .js .wa-float {
        opacity: 0; visibility: hidden; pointer-events: none;
        transform: translateY(12px) scale(0.9);
        transition: opacity 0.45s ease, transform 0.45s cubic-bezier(0.22, 0.61, 0.36, 1), background 0.2s ease, box-shadow 0.25s ease, visibility 0s linear 0.45s;
      }
      .js .wa-float.on {
        opacity: 1; visibility: visible; pointer-events: auto;
        transform: translateY(0) scale(1);
        transition: opacity 0.5s ease, transform 0.5s cubic-bezier(0.22, 0.61, 0.36, 1), background 0.2s ease, box-shadow 0.25s ease, visibility 0s;
      }
      .js .wa-float.on:hover {
        background: #1ec15a;
        transform: translateY(-2px) scale(1);
        box-shadow: 0 10px 22px -8px rgba(18, 140, 90, 0.42), 0 3px 8px rgba(10, 47, 40, 0.1);
      }
      .js .wa-float.on:active { transform: translateY(0) scale(1); }
      @media (max-width: 720px) {
        .wa-float { right: 16px; bottom: calc(16px + env(safe-area-inset-bottom, 0px)); width: 48px; height: 48px; }
        .wa-float svg { width: 23px; height: 26px; }
      }

      /* ---------- Back to top ---------- */
      /* A quiet white circle with a teal up arrow, fixed at the
         bottom-RIGHT, stacked directly above the WhatsApp float
         in the same corner — its bottom edge sits 12px clear of
         the WhatsApp button's top edge (22px base + 50px float
         + 12px gap), both aligned on the right edge. Hidden
         until the visitor reaches the very bottom of the
         current view (the .on state is driven by JS); it
         appears and leaves with a smooth fade and a small rise,
         no bounce, same as the WhatsApp float. */
      .top-btn {
        position: fixed;
        right: 22px;
        bottom: calc(84px + env(safe-area-inset-bottom, 0px));
        z-index: 60;
        width: 50px; height: 50px;
        border-radius: 50%;
        background: var(--surface);
        border: 1px solid var(--line);
        color: var(--teal-deep);
        display: grid; place-items: center;
        cursor: pointer;
        box-shadow: 0 6px 16px -6px rgba(10, 47, 40, 0.25), 0 2px 6px rgba(10, 47, 40, 0.08);
        opacity: 0; visibility: hidden; pointer-events: none;
        transform: translateY(8px);
        transition: opacity 0.45s ease, transform 0.45s cubic-bezier(0.22, 0.61, 0.36, 1), box-shadow 0.25s ease, color 0.2s ease, visibility 0s linear 0.45s;
      }
      .top-btn svg { width: 20px; height: 20px; display: block; }
      .top-btn.on {
        opacity: 1; visibility: visible; pointer-events: auto;
        transform: translateY(0);
        transition: opacity 0.5s ease, transform 0.5s cubic-bezier(0.22, 0.61, 0.36, 1), box-shadow 0.25s ease, color 0.2s ease, visibility 0s;
      }
      .top-btn.on:hover {
        color: var(--teal);
        box-shadow: 0 10px 22px -8px rgba(10, 47, 40, 0.3), 0 3px 8px rgba(10, 47, 40, 0.1);
      }
      .top-btn.on:active { transform: scale(0.94); }
      .top-btn:focus-visible { outline: 3px solid var(--teal); outline-offset: 3px; }
      /* Tap effect (the .fx state, added by JS for ~600ms on
         click and never under reduced motion): one soft teal
         ring pulses outward from the button while the arrow
         glyph glides up and re-enters from below once. Smooth
         easing only — no bounce, no spring. */
      .top-btn::after {
        content: ""; position: absolute; inset: 0; border-radius: 50%;
        border: 2px solid var(--teal); opacity: 0; pointer-events: none;
      }
      .top-btn.fx::after { animation: topRing 0.6s cubic-bezier(0.22, 0.61, 0.36, 1) forwards; }
      .top-btn.fx svg { animation: topArrow 0.6s cubic-bezier(0.22, 0.61, 0.36, 1); }
      @keyframes topRing {
        from { opacity: 0.55; transform: scale(1); }
        to { opacity: 0; transform: scale(1.6); }
      }
      @keyframes topArrow {
        0% { transform: translateY(0); opacity: 1; }
        42% { transform: translateY(-10px); opacity: 0; }
        58% { transform: translateY(10px); opacity: 0; }
        100% { transform: translateY(0); opacity: 1; }
      }
      @media (prefers-reduced-motion: reduce) {
        .top-btn.fx::after, .top-btn.fx svg { animation: none; }
      }
      @media (max-width: 720px) {
        .top-btn { right: 16px; bottom: calc(76px + env(safe-area-inset-bottom, 0px)); width: 48px; height: 48px; }
      }

      /* ---------- Loading screen ---------- */
      /* A brief veil on first load, on the site's plain page
         ground (white in light mode, the dark ground in dark
         mode). The preloader is one brand-teal line (#2DB79C)
         with a slightly hand-drawn character — the same
         gentle wave as the squiggle motif in the Process
         heading — that draws itself across the center of the
         screen, left to right, over ~1.2s. As the draw lands,
         a greeting rides in beneath it on a second copy of
         the same wave, so the word itself follows the line's
         curve: "Welcome" rises softly into place, rests a
         beat, lifts away, and "Bienvenue" rises into the
         same spot. Then the exit: the line and word swell
         toward the viewer in a gentle zoom and soften away
         as the whole screen lifts like a sheet — sweeping up
         and off the top on a long, smooth ease (no bounce,
         no overshoot), its bottom edge rounding softly and a
         faint shadow gathering under the lifting edge,
         revealing the page already sitting in its start
         state underneath. It only ever shows with JS on (the
         .js gate), and the script always dismisses it — on
         window load, with a hard fallback timer — so it can
         never trap the visitor. Under prefers-reduced-motion
         there is no draw, word or zoom and the script
         removes the veil at once. */
      .loader {
        position: fixed; inset: 0; z-index: 200;
        background: var(--bg);
        display: none;
        place-items: center;
        transition: transform 0.95s cubic-bezier(0.22, 1, 0.36, 1), border-radius 0.95s ease, visibility 0s linear 0.95s;
        will-change: transform;
      }
      .js .loader { display: grid; }
      /* Intro already played this tab session (the head script
         adds .intro-seen before first paint): never show it. */
      .intro-seen .loader { display: none !important; }
      .loader-inner {
        display: grid; justify-items: center;
        transition: transform 0.55s cubic-bezier(0.5, 0, 0.75, 0.4), opacity 0.5s ease;
      }
      .loader-art {
        width: clamp(264px, 64vw, 372px); height: auto; display: block;
        overflow: visible;
      }
      /* The line draws itself: the stroke's dash offset
         eases from fully hidden to fully drawn over ~1.2s
         (pathLength normalizes the dash math). A wider,
         faint copy of the same stroke draws in step beneath
         it, giving the line a soft halo as it travels. */
      .loader-line, .loader-line-glow {
        fill: none; stroke: var(--teal); stroke-linecap: round;
        stroke-dasharray: 100; stroke-dashoffset: 100;
        animation: loaderDraw 1.2s cubic-bezier(0.45, 0, 0.3, 1) 0.15s forwards;
      }
      .loader-line { stroke-width: 5; }
      .loader-line-glow { stroke-width: 12; opacity: 0.16; }
      @keyframes loaderDraw { to { stroke-dashoffset: 0; } }
      /* The greeting: the word is set on a textPath along a
         second copy of the line's own wave, just beneath it,
         so its letters follow the same curve as the line.
         "Welcome" rises softly into place as the draw lands,
         rests, then lifts away as "Bienvenue" rises into the
         same spot and rests until the exit. The site's
         elegant italic serif, in the deep teal. */
      .loader-word {
        font-family: "Instrument Serif", Georgia, serif;
        font-style: italic;
        font-size: 31px;
        letter-spacing: 0.06em;
        fill: var(--teal-deep);
        opacity: 0;
      }
      .word-en { animation: loaderWordEn 1s ease 1.15s forwards; }
      @keyframes loaderWordEn {
        0% { opacity: 0; transform: translateY(7px); }
        30% { opacity: 1; transform: translateY(0); }
        72% { opacity: 1; transform: translateY(0); }
        100% { opacity: 0; transform: translateY(-6px); }
      }
      .word-fr { animation: loaderWordIn 0.6s cubic-bezier(0.22, 1, 0.36, 1) 2.12s forwards; }
      @keyframes loaderWordIn {
        from { opacity: 0; transform: translateY(7px); }
        to { opacity: 1; transform: translateY(0); }
      }
      @media (prefers-reduced-motion: reduce) {
        .loader, .loader-line, .loader-line-glow, .loader-word { animation: none; }
        .loader-line, .loader-line-glow { stroke-dashoffset: 0; }
        .loader-word { opacity: 0; }
      }
      /* The curtain lift: the panel sweeps up until it is
         fully off the top of the screen; as it rises, its
         bottom edge rounds softly and a faint shadow gathers
         under the lifting edge, like a sheet being drawn up;
         the zoomed artwork rides a touch ahead of the panel,
         then the script removes the element from the DOM. */
      .loader.done {
        transform: translateY(-100%); visibility: hidden; pointer-events: none;
        border-radius: 0 0 42px 42px;
        box-shadow: 0 34px 60px -16px rgba(4, 40, 31, 0.5);
      }
      /* The zoom: a breath before the lift, the line and the
         greeting swell toward the viewer and soften away, so
         the exit feels like passing through the word; the
         zoomed state carries into the lift itself. */
      .loader.zoom .loader-inner { transform: scale(1.5); opacity: 0; }
      .loader.done .loader-inner { transform: translateY(-40px) scale(1.5); opacity: 0; }
      @media print {
        .loader, .top-btn { display: none !important; }
      }

      /* ---------- Footer ---------- */
      /* position: relative keeps the footer painting (and
         hit-testing) above the parked contact section's box,
         whose empty bottom padding overlaps the footer's top
         band at the end of the page: the section is
         transformed during the curtain exit (see the scrub
         in the script) while the footer stays in plain flow. */
      footer { position: relative; padding: 92px 0 60px; border-top: 1px solid var(--line); background: var(--bg); }
      .foot { display: flex; flex-wrap: wrap; gap: 36px 48px; align-items: flex-start; justify-content: space-between; }
      .foot-brand img { height: 36px; width: auto; }
      .foot-tag { margin-top: 16px; color: var(--ink-soft); font-size: 15.5px; max-width: 300px; }
      .foot-copy { margin-top: 10px; color: var(--ink-soft); font-size: 13.5px; }
      .foot-cols { display: flex; gap: 76px; flex-wrap: wrap; }
      .foot-col { display: grid; gap: 11px; align-content: start; }
      .foot-col a { text-decoration: none; font-weight: 600; font-size: 15px; color: var(--ink-soft); }
      .foot-col a:hover { color: var(--ink); }
      .foot-contact a { color: var(--teal); }
      .foot-contact a:hover { color: var(--teal-deep); }

      /* ---------- View tabs ---------- */
      .view-tabs {
        display: flex; gap: 2px; padding: 3px; flex: none;
        background: var(--bg-soft); border: 1px solid var(--line); border-radius: 999px;
      }
      .vtab {
        font: inherit; font-size: 14.5px; font-weight: 700; color: var(--ink-soft);
        background: transparent; border: 0; border-radius: 999px;
        padding: 7px 20px; cursor: pointer; min-height: 38px;
        transition: background 0.2s ease, color 0.2s ease, transform 0.45s cubic-bezier(0.34, 1.9, 0.64, 1);
      }
      .vtab:active { transform: scale(0.93); }
      .vtab.active { background: var(--surface); color: var(--ink); box-shadow: 0 2px 8px rgba(10, 47, 40, 0.12); }
      .mobile-menu .mm-view {
        background: none; border: 0; cursor: pointer; font-family: inherit;
      }

      /* ---------- Sliding views ---------- */
      .views { position: relative; }
      .views.sliding { overflow: hidden; }
      .view-abs { position: absolute; top: 0; left: 0; width: 100%; }
      .views.sliding .view-abs { transition: transform 0.52s cubic-bezier(0.22, 1, 0.36, 1); }

      /* ---------- Play / games ---------- */
      body { overflow-anchor: none; }
      :root { --bad: #c2504c; }
      @media (prefers-color-scheme: dark) { :root { --bad: #e0685f; } }
      .play-lede { margin-top: 10px; color: var(--ink-soft); font-size: 17px; max-width: 460px; }
      .game-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 28px; }
      .game-card { border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow); position: relative; }
      .g-play {
        display: flex; flex-direction: column; gap: 9px;
        width: 100%; min-height: 224px; padding: 28px 28px 26px;
        font: inherit; text-align: left; color: #ffffff;
        border: 0; cursor: pointer; background: transparent;
        -webkit-tap-highlight-color: transparent;
      }
      .g-name { font-size: 30px; font-weight: 700; letter-spacing: -0.02em; line-height: 1.1; }
      .g-line { font-size: 15.5px; color: rgba(255, 255, 255, 0.88); max-width: 300px; }
      .g-foot { margin-top: auto; display: flex; align-items: center; justify-content: space-between; gap: 14px; }
      .g-play .g-tag { font-size: 13px; font-weight: 700; letter-spacing: 0.03em; color: rgba(255, 255, 255, 0.78); }
      .g-btn {
        flex: none; background: #ffffff; color: #07332a;
        font-size: 15px; font-weight: 700; padding: 10px 22px; border-radius: 999px;
        transition: transform 0.18s ease;
      }
      .g-play:hover .g-btn { transform: scale(1.05); }
      .g-play:active .g-btn { transform: scale(0.98); }
      .game-card.g1 { background: radial-gradient(circle at 88% -10%, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0) 55%), linear-gradient(140deg, #43cdb0, #14755f); }
      .game-card.g2 { background: radial-gradient(circle at 88% -10%, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0) 55%), linear-gradient(140deg, #6ec3e8, #4a86c9); }
      .game-card.g3 { background: radial-gradient(circle at 88% -10%, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0) 55%), linear-gradient(140deg, #9fd06e, #2f9e6e); }
      .game-card.g4 { background: radial-gradient(circle at 88% -10%, rgba(255, 255, 255, 0.13), rgba(255, 255, 255, 0) 55%), linear-gradient(140deg, #2a8570, #0d3a30); }
      .game-overlay {
        position: fixed; inset: 0; z-index: 80;
        background: rgba(8, 26, 21, 0.46);
        backdrop-filter: blur(5px); -webkit-backdrop-filter: blur(5px);
        display: flex; overflow-y: auto; padding: 20px 14px;
      }
      .game-overlay[hidden] { display: none; }
      .game-sheet {
        margin: auto; width: 100%; max-width: 540px;
        background: var(--surface); border: 1px solid var(--line); border-radius: 24px;
        padding: 26px 26px 30px; box-shadow: var(--shadow);
        animation: bubbleIn 0.85s cubic-bezier(0.22, 1, 0.36, 1);
      }
      .game-top { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 18px; }
      .game-top h3 { font-size: 21px; font-weight: 700; }
      .game-close {
        flex: none; width: 42px; height: 42px; border-radius: 50%;
        background: var(--bg-soft); border: 1px solid var(--line); color: var(--ink);
        display: grid; place-items: center; cursor: pointer;
        transition: transform 0.4s cubic-bezier(0.34, 1.8, 0.64, 1), background 0.2s ease;
      }
      .game-close:active { transform: scale(0.88); }
      .g-how { color: var(--ink-soft); font-size: 16px; }
      .g-wide { width: 100%; justify-content: center; margin-top: 22px; min-height: 50px; }
      .g-meta {
        display: flex; align-items: center; justify-content: space-between; gap: 14px;
        font-size: 14px; font-weight: 700; color: var(--ink-soft); margin-bottom: 18px;
      }
      .g-final { text-align: center; padding: 8px 0 2px; }
      .g-score { font-size: 52px; font-weight: 700; letter-spacing: -0.02em; line-height: 1.05; }
      .g-score span { font-size: 22px; color: var(--ink-soft); font-weight: 700; }
      .g-final .g-how { margin-top: 8px; }
      .g-final .btn-ghost { margin-top: 10px; }
      /* Reaction Tap */
      .react-panel {
        width: 100%; min-height: 248px; padding: 24px 16px;
        display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;
        font: inherit; color: var(--ink); cursor: pointer;
        background: color-mix(in srgb, #f2a541 13%, var(--bg));
        border: 1.5px solid var(--line); border-radius: 16px;
        touch-action: manipulation; user-select: none; -webkit-user-select: none; -webkit-tap-highlight-color: transparent;
        transition: background 0.15s ease, border-color 0.15s ease;
      }
      .react-panel .rp-big { font-size: 36px; font-weight: 700; letter-spacing: -0.02em; line-height: 1.1; }
      .react-panel .rp-small { font-size: 15.5px; font-weight: 700; color: var(--ink-soft); }
      .react-panel.go { background: var(--teal); border-color: var(--teal); color: #06231c; }
      .react-panel.go .rp-small { color: #0a3a2f; }
      .react-panel.early { background: color-mix(in srgb, var(--bad) 12%, var(--bg)); border-color: var(--bad); }
      .react-panel.done { background: color-mix(in srgb, var(--teal) 14%, var(--bg)); border-color: var(--teal); }
      /* Memory Match */
      .mem-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
      .mem-card {
        padding: 0; border: 0; background: none; cursor: pointer;
        aspect-ratio: 3 / 4; perspective: 700px;
        -webkit-tap-highlight-color: transparent;
      }
      .mem-inner {
        display: block; position: relative; width: 100%; height: 100%;
        transform-style: preserve-3d;
        transition: transform 0.45s cubic-bezier(0.22, 0.61, 0.36, 1);
      }
      .mem-card.flipped .mem-inner { transform: rotateY(180deg); }
      .mem-face {
        position: absolute; inset: 0; display: grid; place-items: center;
        border-radius: 12px; backface-visibility: hidden; -webkit-backface-visibility: hidden;
      }
      .mem-back { background: linear-gradient(135deg, var(--teal-bright), var(--teal-deep)); }
      .mem-back::after { content: ""; width: 24px; height: 24px; border-radius: 50%; border: 3px solid rgba(255, 255, 255, 0.85); }
      .mem-front { background: var(--bg-soft); border: 1.5px solid var(--line); transform: rotateY(180deg); }
      .mem-front svg { width: 62%; height: 62%; }
      .mem-card.matched { cursor: default; }
      .mem-card.matched .mem-front { border-color: var(--teal); background: color-mix(in srgb, var(--teal) 13%, var(--bg)); }
      .g-hint { text-align: center; font-weight: 700; color: var(--ink-soft); font-size: 14.5px; margin-bottom: 16px; }
      /* Build the Mark */
      /* Difficulty pills: the view-tabs pill treatment — one
         soft capsule, the chosen level lifted on a white pill */
      .bm-diffs {
        display: flex; gap: 2px; padding: 3px;
        background: var(--bg-soft); border: 1px solid var(--line); border-radius: 999px;
        margin-bottom: 18px;
      }
      .bm-pill {
        flex: 1; font: inherit; font-size: 14.5px; font-weight: 700; color: var(--ink-soft);
        background: transparent; border: 0; border-radius: 999px;
        padding: 8px 10px; min-height: 40px; cursor: pointer;
        transition: background 0.2s ease, color 0.2s ease, transform 0.45s cubic-bezier(0.34, 1.9, 0.64, 1);
        -webkit-tap-highlight-color: transparent;
      }
      .bm-pill:active { transform: scale(0.93); }
      .bm-pill.active { background: var(--surface); color: var(--ink); box-shadow: 0 2px 8px rgba(10, 47, 40, 0.12); }
      .bm-pill:focus-visible { outline: 3px solid var(--teal); outline-offset: 2px; }
      /* The board: a soft dotted panel. The mark's outline
         sits centered as a ghost layer (its opacity is set per
         difficulty; Hard renders none at all); the solid pieces
         float above it, scattered, and are dragged home by
         pointer. Positions are percents of the board, set by JS;
         the transform centers each piece on its point and
         carries its rotation. */
      .bm-stage {
        position: relative; width: 100%; aspect-ratio: 10 / 8.4;
        background-color: var(--bg-soft);
        background-image: radial-gradient(circle, color-mix(in srgb, var(--teal) 16%, transparent) 1.3px, transparent 1.9px);
        background-size: 22px 22px;
        border: 1.5px solid var(--line); border-radius: 20px;
        overflow: hidden; user-select: none; -webkit-user-select: none;
        transition: border-color 0.4s ease;
      }
      .bm-stage.won { border-color: var(--teal); }
      .bm-ghost, .bm-piece { position: absolute; }
      .bm-ghost { pointer-events: none; transition: opacity 0.45s ease; }
      .bm-stage.won .bm-ghost { opacity: 0 !important; }
      .bm-ghost svg, .bm-piece svg { display: block; width: 100%; height: 100%; }
      .bm-ghost .bm-g-shape { fill: none; stroke: var(--ink); stroke-width: 2.5; }
      .bm-ghost .bm-g-glyph { fill: none; stroke: var(--ink); stroke-width: 1.1; font-family: "Instrument Serif", Georgia, serif; }
      .bm-piece {
        cursor: grab; touch-action: none;
        -webkit-tap-highlight-color: transparent;
        filter: drop-shadow(0 3px 6px rgba(10, 47, 40, 0.18));
      }
      .bm-piece.dragging { cursor: grabbing; filter: drop-shadow(0 10px 16px rgba(10, 47, 40, 0.28)); }
      .bm-piece.placed { cursor: default; pointer-events: none; filter: drop-shadow(0 2px 4px rgba(10, 47, 40, 0.14)); }
      .bm-f-teal { fill: var(--teal); }
      .bm-f-deep { fill: var(--teal-deep); }
      .bm-f-ink { fill: var(--ink); }
      .bm-s-ring { fill: none; stroke: color-mix(in srgb, var(--teal) 40%, var(--bg)); stroke-width: 15; }
      .bm-f-glyph { fill: var(--ink); font-family: "Instrument Serif", Georgia, serif; }
      /* The verdict line: quiet helper text while building,
         the game's answer in italic serif once built */
      .bm-msg {
        text-align: center; font-weight: 700; color: var(--ink-soft);
        font-size: 15px; margin: 16px 0 0; min-height: 26px;
      }
      .bm-msg.result {
        font-family: "Instrument Serif", Georgia, serif; font-style: italic;
        font-weight: 400; font-size: 27px; color: var(--ink); min-height: 34px;
      }
      .bm-stats { margin-top: 6px; text-align: center; font-weight: 700; color: var(--teal-deep); font-size: 15.5px; min-height: 24px; }
      .bm-next { width: 100%; justify-content: center; margin-top: 18px; min-height: 62px; font-size: 18px; }
      @media (prefers-reduced-motion: reduce) {
        .bm-stage, .bm-ghost { transition: none; }
      }
      /* Odd One Out */
      .odd-grid { display: grid; gap: 7px; max-width: 400px; margin: 0 auto; }
      .odd-cell {
        aspect-ratio: 1; border: 0; border-radius: 10px; cursor: pointer; padding: 0;
        transition: transform 0.15s ease, opacity 0.15s ease;
        -webkit-tap-highlight-color: transparent;
      }
      .odd-cell.miss { box-shadow: inset 0 0 0 3px var(--bad); opacity: 0.55; cursor: default; }
      .odd-cell.hit { box-shadow: inset 0 0 0 3px var(--teal); }
      @media (max-width: 720px) {
        .vtab { padding: 6px 8px; font-size: 13.5px; }
        .game-grid { grid-template-columns: 1fr; }
        .game-sheet { padding: 22px 18px 26px; }
        .g-play { min-height: 198px; padding: 24px 22px 22px; }
        .g-name { font-size: 28px; }
        .react-panel { min-height: 220px; }
        .react-panel .rp-big { font-size: 31px; }
        .mem-grid { gap: 8px; }
      }

      /* ---------- Scroll slow-downs ----------
         At two big moments the page briefly slows and
         breathes on what it is showing: the section's
         content wrapper is sticky, and an invisible spacer
         after it gives the wrapper room to stay pinned
         while a short stretch of scroll — about a sixth of
         a screen — is consumed; then the wrapper releases
         and the page flows on. Scrolling back up releases
         in reverse. Sticky positioning does the holding —
         no snap point, no bounce — and no drift is laid
         over either pin: while a wrapper is pinned it does
         not move at all, so the About text rests perfectly
         still and the pause reads purely as scroll pacing,
         a gentle slow-down, never a hard stick. (Packages
         used to pause here too; it now scrolls through at
         plain pace like any other section — no pin, no
         spacer.) The About wrapper's pin range is exactly
         its hold: the moment the hold ends it releases, so
         the text rides the sheet for the whole rise (see
         .about-sheet above). Under
         prefers-reduced-motion and in print the wrappers
         rest static and the spacers vanish: plain flow, no
         pinning at all. */
      .hold-spacer { height: 16vh; height: 16svh; }
      /* The About text rests at screen center while pinned:
         the sticky offset is half the viewport minus half
         the text block (~220px tall on desktop, ~195px on
         phone — the phone value is set in the 720px query). */
      .about .wrap { position: sticky; top: calc(50vh - 110px); top: calc(50svh - 110px); }
      .contact-cta .wrap { position: sticky; top: calc(50vh - 39px); top: calc(50svh - 39px); }
      /* While the curtain exit runs (the class is set by the
         curtain scrub in the script), the contact wrapper
         rests static: the scrub parks the whole finale at
         its end-of-page composition, so the wrapper's own
         pin must not also engage underneath the park. */
      body.curtain-on .contact-cta .wrap { position: static; }
      /* While parked, the finale's per-frame lift rides on its
         own compositor layer, so the pill's steady glide never
         waits on a repaint of the section beneath it. */
      body.curtain-on .contact-cta { will-change: transform; }

      /* ---------- Scroll motion ---------- */
      .js .reveal {
        opacity: 0;
        transform: translateY(18px);
        transition: opacity 0.9s ease, transform 0.95s cubic-bezier(0.34, 1.28, 0.64, 1);
        transition-delay: var(--rd, 0s);
      }
      .js .reveal.in { opacity: 1; transform: none; }
      @media print {
        .js .reveal { opacity: 1; transform: none; }
        /* No entrance in print: the service rows print plainly */
        .js .svc-list .svc-row { opacity: 1; transform: none; }
        /* No stacking in print: the steps print as a plain list */
        .pstep { position: static; }
        .hero { height: auto; }
        .hero-sticky { position: static; height: auto; padding: 60px 0; }
        .hero h1 .hw { opacity: 1 !important; filter: none !important; }
        /* No runway in print: the assembled composition prints
           as a still */
        .assemble { height: auto; }
        .assemble-stage { position: static; height: auto; padding: 60px 0; overflow: visible; }
        .piece { transform: none !important; }
        /* No slow-downs in print: no pinning, no spacers */
        .hold-spacer { display: none; }
        .about .wrap, .contact-cta .wrap { position: static; }
        /* No curtain lift in print: the teal sheet rests as
           the section's plain full background */
        .about-lift, .about-lead { display: none; }
        .about-sheet { height: auto; bottom: 0; }
        /* No parked finale in print: it prints in plain flow */
        .contact-cta, footer { transform: none !important; }
      }
      @media (prefers-reduced-motion: reduce) {
        html { scroll-behavior: auto; }
        *, *::before, *::after {
          transition-duration: 0.01ms !important;
          animation-duration: 0.01ms !important;
          animation-iteration-count: 1 !important;
        }
        .js .reveal { opacity: 1; transform: none; }
        /* No entrance under reduced motion: rows simply visible */
        .js .svc-list .svc-row { opacity: 1; transform: none; }
        /* No stacking under reduced motion: the steps rest as a
           plain, static list of cards */
        .pstep { position: static; }
        .hero { height: auto; }
        .hero-sticky { position: static; height: auto; padding: 96px 0 104px; }
        .hero h1 .hw { opacity: 1 !important; transform: none !important; filter: none !important; }
        /* No runway under reduced motion: the stage un-sticks
           and the finished composition simply rests, static */
        .assemble { height: auto; }
        .assemble-stage { position: static; height: auto; padding: 96px 0 104px; overflow: visible; }
        /* No slow-downs under reduced motion: the wrappers
           rest static and the spacers vanish — plain flow */
        .hold-spacer { display: none; }
        .about .wrap, .contact-cta .wrap { position: static; }
        /* No curtain lift under reduced motion: the teal
           sheet rests as the section's plain background */
        .about-lift, .about-lead { display: none; }
        .about-sheet { height: auto; bottom: 0; }
      }

      /* ---------- Polish: hero words ---------- */
      body { overflow-x: hidden; overflow-x: clip; }

      /* Hero headline words (spans added by JS) are lit by inline
         opacity from the scroll scrub — no CSS state needed */

      /* ---------- Responsive ---------- */
      /* The full nav row (logo + view tabs + six links + CTA) needs the
         full 1080px wrap; below that it would compress and clip, so the
         links move into the hamburger menu earlier */
      @media (max-width: 1100px) {
        .nav-links { display: none; }
        .menu-btn { display: block; }
      }
      @media (max-width: 960px) {
        .pkg-grid { grid-template-columns: 1fr; max-width: 520px; }
        .pkg.featured { order: -1; }
        section { padding: 128px 0; }
      }
      @media (max-width: 720px) {
        /* Phone nav: logo, tabs and menu button share one 64px row —
           sized down together so all three fit with room to spare */
        .nav-inner { gap: 10px; }
        .nav-logo img { height: 18px; }
        .collection { padding-top: 38px; }
        .back-row { margin-bottom: 36px; }
        .svc-list { --svc-numw: 76px; --svc-gap: 20px; --svc-pad: 2px; }
        .svc-head { padding: 30px var(--svc-pad); }
        .svc-row:first-child .svc-head { padding-top: 20px; }
        .svc-num { font-size: 52px; }
        .svc-line { font-size: 16.5px; }
        .svc-more { padding-bottom: 34px; }
        .steps-list { --peek: 11px; }
        .pstep {
          top: calc(76px + var(--si, 0) * var(--peek));
          grid-template-columns: 76px 1fr; gap: 6px 20px;
          padding: 30px 24px; border-radius: 22px; margin-bottom: 22px;
        }
        .pstep-num { font-size: 52px; }
        .sentence { line-height: 1.85; }
        .hero { padding: 0; }
        .contact-cta { padding: 76px 0 88px; }
        .hello-btn { padding: 20px 30px; min-height: 66px; gap: 12px; }
        .contact-sheet { padding: 56px 26px 46px; border-radius: 26px; }
        .about { padding: 140px 0 76px; margin-top: -64px; }
        .about .wrap { top: calc(50vh - 98px); top: calc(50svh - 98px); }
        .about-sheet {
          height: calc(66vh + 238px); height: calc(66svh + 238px);
          border-top-left-radius: 50% 64px;
          border-top-right-radius: 50% 64px;
        }
        .foot-cols { gap: 44px; }
        .est-form { flex-direction: column; }
        .est-form .btn { justify-content: center; }
        .est-card { padding: 26px 22px; }
        .pkg { padding: 40px 28px 34px; }
        .badge { left: 28px; }
        .price { min-height: 52px; }
        .price .amount { font-size: 52px; }
        .price .amount.text { font-size: 38px; }
        .pkg-sheet { padding: 24px 20px 26px; }
      }
      /* Narrow phones: one more small step down so the nav row still
         fits without squeezing anything */
      @media (max-width: 380px) {
        .nav-inner { gap: 8px; }
        .nav-logo img { height: 17px; }
        .vtab { padding: 6px 7px; font-size: 13px; }
      }
    
      /* ---------- Multi-page build ---------- */
      /* The view tabs and the menu entries are real links now;
         keep the button treatment they were designed with. */
      .vtab { text-decoration: none; display: inline-flex; align-items: center; justify-content: center; }
      a.contact-close { text-decoration: none; }
