/* ============================================================
 * THE SYSTEM, IN 6, sits right under the hero
 * Knowledge Base · Channels · CRM · CDP · Campaigns & Journeys · Loyalty
 * ============================================================ */

const restCards = [
  {
    title: "Knowledge Base",
    promise: "The hotel's brain, every fact, every property, in any language.",
    bullets: [
      "Deep crawl across website, booking engine, PDFs, PMS, and Drive.",
      "Group + per-property AI stores, dedup'd and continuously updated.",
    ],
    href: "platform/knowledge.html",
    visual: "kb",
  },
  {
    title: "Channels",
    promise: "Every guest conversation, on every channel, in one shared inbox.",
    bullets: [
      "WhatsApp, Web Chatbot, Meta Socials, Voice, and email in both directions.",
      "One AI agent across all of them, with one history and one logic.",
    ],
    href: "platform/inbox.html",
    visual: "channels",
    links: [
      { href: "platform/inbox.html", label: "Inboxes" },
      { href: "platform/voice.html", label: "Voice Agent" },
    ],
  },
  {
    title: "CRM",
    /* Two sides now, so the card leads with the split rather than
       describing only the guest one. Same shape as Channels above: the
       links carry the two destinations and the card itself stops being a
       single anchor. */
    promise: "One CRM for the guests who stay and the accounts that send them.",
    bullets: [
      "B2C: every guest profile anchored to real reservations, across every channel.",
      "B2B: agencies, tour operators and corporate accounts, with the bookings they produced attributed to them.",
    ],
    href: "platform/crm.html",
    visual: "crm",
    links: [
      { href: "platform/crm.html", label: "B2C CRM" },
      { href: "platform/crm-b2b.html", label: "B2B CRM" },
    ],
  },
  {
    title: "CDP",
    promise: "One guest, even when your PMS says otherwise.",
    bullets: [
      "Automatic deduplication across heterogeneous PMS instances.",
      "Anonymous contacts promoted to CRM the moment they're reachable.",
    ],
    href: "platform/cdp.html",
    visual: "cdp",
  },
  {
    title: "Campaigns & Journeys",
    promise: "Email and WhatsApp campaigns plus omnichannel automation.",
    bullets: [
      "Pre-stay, in-stay, and post-stay journeys triggered by real booking data.",
      "AI-assisted templates and visual editors for both channels.",
    ],
    href: "platform/journeys.html",
    visual: "campaigns",
  },
  {
    title: "Loyalty",
    promise: "A loyalty engine sophisticated enough for any hotel group.",
    bullets: [
      "Rule-based tiers, points, and benefits, modeled for the largest groups.",
      "Fully integrated with PMS and booking engines, in real time.",
    ],
    href: "platform/loyalty.html",
    visual: "loyalty",
  },
];

/* ------------------------------------------------------------------
 * The six diagrams.
 *
 * Each one performs ITS OWN idea, and only while its card is hovered.
 * The motifs are deliberately different — radial ingestion, flow along
 * paths, rows revealing depth, convergence, traversal, progressive fill —
 * so six cards on one screen do not read as one template repeated.
 *
 * At rest every diagram is completely still, and still composed: nothing
 * is mid-flight, half-drawn or frozen. Everything animating is either a
 * transition back to its rest value, or a looping element that is
 * opacity:0 when not hovered, so a paused frame is never visible.
 *
 * Hover is the trigger, but :focus-within matches it — a keyboard user
 * tabbing to the card's link gets the same thing. Under
 * prefers-reduced-motion the whole layer resolves to its END state
 * instantly, so the meaning survives without the movement.
 * ------------------------------------------------------------------ */
const RestVisual = ({ kind }) => {
  /* KNOWLEDGE — radial ingestion. Sources sit apart and the brain is
     empty; on hover the feeds draw inward and the core fills. */
  if (kind === "kb") return (
    <svg viewBox="0 0 200 80" className="rest-vis rv-kb" preserveAspectRatio="xMidYMid meet" aria-hidden="true">
      {[
        { x: 18, y: 12, w: 30, label: "WEB", d: "M 48 17.5 C 70 17.5, 78 32, 88 38" },
        { x: 18, y: 56, w: 30, label: "PDF", d: "M 48 61.5 C 70 61.5, 78 47, 88 42" },
        { x: 152, y: 12, w: 30, label: "PMS", d: "M 152 17.5 C 130 17.5, 122 32, 112 38" },
        { x: 152, y: 56, w: 30, label: "DOCS", d: "M 152 61.5 C 130 61.5, 122 47, 112 42" },
      ].map((s, i) => (
        <g key={s.label}>
          <rect x={s.x} y={s.y} width={s.w} height="11" rx="2.5"
                fill="var(--bg-elev-2)" stroke="var(--hairline-strong)" strokeWidth="0.6" />
          <text x={s.x + s.w / 2} y={s.y + 7.6} fontSize="5.6" textAnchor="middle"
                fill="var(--ink-3)" fontFamily="var(--f-mono)" letterSpacing="0.06em">{s.label}</text>
          <path className="kb-feed" style={{ "--i": i }} d={s.d}
                fill="none" stroke="var(--accent)" strokeWidth="0.9" strokeLinecap="round" />
        </g>
      ))}
      {/* the brain: an outline at rest, filled once the feeds arrive */}
      <circle className="kb-halo" cx="100" cy="40" r="22" fill="var(--accent)" opacity="0" />
      <circle className="kb-ring" cx="100" cy="40" r="15" fill="none"
              stroke="var(--accent)" strokeWidth="0.8" opacity="0.35" />
      <circle className="kb-core" cx="100" cy="40" r="8" fill="none"
              stroke="var(--accent)" strokeWidth="1.4" />
      <circle className="kb-dot" cx="100" cy="40" r="3.4" fill="var(--accent)" opacity="0" />
    </svg>
  );

  /* CHANNELS — flow along paths. Six lines, no traffic at rest; on hover
     a message runs each one into the inbox and the inbox answers. */
  if (kind === "channels") {
    const chans = [
      { y: 11, c: "var(--c-whatsapp)", l: "WHATSAPP" },
      { y: 22, c: "var(--c-instagram)", l: "SOCIAL" },
      { y: 33, c: "var(--c-email)", l: "EMAIL" },
      { y: 45, c: "var(--c-booking)", l: "BOOKING" },
      { y: 56, c: "var(--c-voice)", l: "VOICE" },
      { y: 67, c: "var(--c-web)", l: "WEB" },
    ];
    return (
      <svg viewBox="0 0 200 80" className="rest-vis rv-ch" preserveAspectRatio="xMidYMid meet" aria-hidden="true">
        {chans.map((ch, i) => {
          const d = `M 56 ${ch.y} C 92 ${ch.y}, 108 40, 140 40`;
          return (
            <g key={ch.l}>
              <circle cx="12" cy={ch.y} r="2.4" fill={ch.c} />
              <text x="18" y={ch.y + 2.1} fontSize="5" fill="var(--ink-3)"
                    fontFamily="var(--f-mono)" letterSpacing="0.06em">{ch.l}</text>
              <path d={d} stroke={ch.c} strokeWidth="0.7" fill="none" opacity="0.28" />
              <circle className="ch-msg" style={{ "--i": i }} r="1.9" fill={ch.c} opacity="0">
                <animateMotion dur="1.9s" repeatCount="indefinite" path={d} begin={`${i * 0.16}s`} />
              </circle>
            </g>
          );
        })}
        <rect className="ch-inbox" x="142" y="29" width="44" height="22" rx="4"
              fill="var(--bg-elev-2)" stroke="var(--accent)" strokeWidth="1" />
        <text x="164" y="42.6" fontSize="6" textAnchor="middle" fill="var(--accent)"
              fontFamily="var(--f-mono)" letterSpacing="0.1em">INBOX</text>
      </svg>
    );
  }

  /* CRM — rows revealing depth. Three plain guest rows; on hover each
     opens to show the real bookings the profile is anchored to. */
  if (kind === "crm") return (
    <svg viewBox="0 0 200 80" className="rest-vis rv-crm" preserveAspectRatio="xMidYMid meet" aria-hidden="true">
      {[
        { y: 8, name: "A. Müller", val: "€1,840", stays: 3 },
        { y: 32, name: "K. Petrov", val: "€2,120", stays: 4 },
        { y: 56, name: "M. Tan", val: "€640", stays: 1 },
      ].map((r, i) => (
        <g key={r.name} className="crm-row" style={{ "--i": i }}>
          <rect x="10" y={r.y} width="180" height="15" rx="3.5"
                fill="var(--bg-elev-2)" stroke="var(--hairline-strong)" strokeWidth="0.6" />
          <rect className="crm-flag" x="10" y={r.y} width="2.5" height="15" rx="1.25" fill="var(--accent)" opacity="0" />
          <circle cx="21" cy={r.y + 7.5} r="3.2" fill="var(--ink-4)" className="crm-avatar" />
          <text x="29" y={r.y + 10} fontSize="6.6" fill="var(--ink-2)">{r.name}</text>
          <text x="184" y={r.y + 10} fontSize="6.4" textAnchor="end"
                fontFamily="var(--f-mono)" fill="var(--ink-3)" className="crm-val">{r.val}</text>
          {/* the bookings underneath — the whole point of the card */}
          {Array.from({ length: r.stays }).map((_, j) => (
            <rect key={j} className="crm-stay" style={{ "--j": j }}
                  x={104 + j * 11} y={r.y + 4.5} width="8" height="6" rx="1.4"
                  fill="var(--accent)" opacity="0" />
          ))}
        </g>
      ))}
    </svg>
  );

  /* CDP — convergence. Three near-duplicate records, misaligned and
     spelled differently; on hover they slide together into one. */
  if (kind === "cdp") return (
    <svg viewBox="0 0 200 80" className="rest-vis rv-cdp" preserveAspectRatio="xMidYMid meet" aria-hidden="true">
      {[
        { y: 10, x: 16, name: "a.muller@…", src: "PMS·1" },
        { y: 33, x: 30, name: "A. Müller", src: "PMS·2" },
        { y: 56, x: 22, name: "MULLER A.", src: "PMS·3" },
      ].map((d, i) => (
        <g key={d.src} className="cdp-dupe" style={{ "--i": i, "--dx": `${86 - d.x}px`, "--dy": `${33 - d.y}px` }}>
          <rect x={d.x} y={d.y} width="76" height="15" rx="3.5"
                fill="var(--bg-elev-2)" stroke="var(--hairline-strong)" strokeWidth="0.6" />
          <text x={d.x + 7} y={d.y + 10} fontSize="6.2" fill="var(--ink-3)">{d.name}</text>
          <text x={d.x + 70} y={d.y + 10} fontSize="4.6" textAnchor="end"
                fill="var(--ink-4)" fontFamily="var(--f-mono)">{d.src}</text>
        </g>
      ))}
      {/* the resolved single record */}
      <g className="cdp-one">
        <rect x="112" y="26" width="76" height="28" rx="5"
              fill="var(--accent)" stroke="var(--accent)" strokeWidth="1" />
        <text x="150" y="39" fontSize="7" textAnchor="middle" fill="var(--accent-ink)" fontWeight="600">A. Müller</text>
        <text x="150" y="48" fontSize="5" textAnchor="middle" fill="var(--accent-ink)"
              fontFamily="var(--f-mono)" letterSpacing="0.08em" opacity="0.85">ONE GUEST</text>
      </g>
    </svg>
  );

  /* JOURNEYS — traversal. A quiet timeline; on hover a marker walks
     pre → stay → post and lights each touchpoint as it passes. */
  if (kind === "campaigns") {
    const path = "M 12 52 C 46 52, 46 30, 76 30 S 118 54, 146 54 S 178 34, 190 34";
    return (
      <svg viewBox="0 0 200 80" className="rest-vis rv-jr" preserveAspectRatio="xMidYMid meet" aria-hidden="true">
        <g fontFamily="var(--f-mono)" fontSize="5" fill="var(--ink-4)" letterSpacing="0.1em">
          <text x="30" y="12">PRE-STAY</text>
          <text x="88" y="12">IN-STAY</text>
          <text x="150" y="12">POST</text>
        </g>
        <line x1="78" y1="6" x2="78" y2="74" stroke="var(--hairline)" strokeWidth="0.5" strokeDasharray="1.5 3" />
        <line x1="142" y1="6" x2="142" y2="74" stroke="var(--hairline)" strokeWidth="0.5" strokeDasharray="1.5 3" />
        <path d={path} fill="none" stroke="var(--hairline-strong)" strokeWidth="1" />
        <path className="jr-trail" d={path} fill="none" stroke="var(--accent)" strokeWidth="1.4" strokeLinecap="round" />
        {[
          { cx: 30, cy: 44, c: "var(--c-whatsapp)", i: 0 },
          { cx: 76, cy: 30, c: "var(--c-email)", i: 1 },
          { cx: 112, cy: 43, c: "var(--c-whatsapp)", i: 2 },
          { cx: 160, cy: 45, c: "var(--c-email)", i: 3 },
        ].map((t) => (
          <g key={t.cx} className="jr-tp" style={{ "--i": t.i }}>
            <circle cx={t.cx} cy={t.cy} r="4.6" fill={t.c} opacity="0.18" className="jr-tp-halo" />
            <circle cx={t.cx} cy={t.cy} r="2.6" fill={t.c} />
          </g>
        ))}
        <circle className="jr-head" r="3" fill="var(--accent)" opacity="0">
          <animateMotion dur="3.4s" repeatCount="indefinite" path={path} />
        </circle>
      </svg>
    );
  }

  /* LOYALTY — progressive fill. Four empty tiers; on hover they fill in
     sequence and platinum lands in brand fuchsia. */
  if (kind === "loyalty") return (
    <svg viewBox="0 0 200 80" className="rest-vis rv-ly" preserveAspectRatio="xMidYMid meet" aria-hidden="true">
      {/* The tier name sits in its own column, NOT inside the bar. Inside,
          it had to be light to read against a filled bar — so at rest, with
          the fill scaled to zero, three of the four labels vanished into the
          empty track. A label column is legible in both states and reads
          quieter, which suits the tier ladder better anyway. */}
      {[
        { y: 10, w: 26, label: "BRONZE", top: false },
        { y: 29, w: 56, label: "SILVER", top: false },
        { y: 48, w: 86, label: "GOLD", top: false },
        { y: 67, w: 122, label: "PLATINUM", top: true },
      ].map((b, i) => (
        <g key={b.label} className={`ly-tier${b.top ? " ly-top" : ""}`} style={{ "--i": i }}>
          <text className="ly-label" x="12" y={b.y + 2} fontSize="5.4" fontFamily="var(--f-mono)"
                letterSpacing="0.1em" fill="var(--ink-3)">{b.label}</text>
          <rect x="62" y={b.y - 4.5} width="126" height="9" rx="2.5"
                fill="var(--bg-elev-2)" stroke="var(--hairline)" strokeWidth="0.5" />
          <rect className="ly-fill" x="62" y={b.y - 4.5} width={b.w} height="9" rx="2.5"
                fill={b.top ? "var(--accent)" : "var(--ink-3)"} opacity={b.top ? 1 : 0.4} />
        </g>
      ))}
    </svg>
  );

  return null;
};

const SectionRest = () => (
  <section className="section-pad rest-section" id="system-overview">
    <div className="container">
      <div className="rest-head">
        <Reveal><div className="eyebrow">The platform</div></Reveal>
        <Reveal delay={120}>
          <h2 className="h-1" style={{ marginTop: 24, maxWidth: 900 }}>
            Everything a hotel group needs, <span className="italic-accent">in one platform.</span>
          </h2>
        </Reveal>
        <Reveal delay={220}>
          <p className="lead" style={{ marginTop: 24, maxWidth: 640 }}>
            Six layers of the system, all sharing the same intelligence and the same data, so guest context never gets lost between teams or tools.
          </p>
        </Reveal>
      </div>

      <div className="rest-grid">
        {restCards.map((c, i) => {
          const inner = (
            <>
              <div className="rest-vis-wrap"><RestVisual kind={c.visual} /></div>
              <div className="rest-num">0{i + 1} / {c.title.toUpperCase()}</div>
              <h3 className="rest-title">{c.title}</h3>
              <p className="rest-promise">{c.promise}</p>
              <ul className="rest-bullets">
                {c.bullets.map((b, j) => <li key={j}>{b}</li>)}
              </ul>
              {c.links ? (
                <div className="rest-links">
                  {c.links.map((l) => (
                    <a key={l.href} href={l.href} className="rest-link rest-link-pill" onClick={(e) => e.stopPropagation()}>
                      {l.label} <IconArrow size={12} className="arrow" />
                    </a>
                  ))}
                </div>
              ) : (
                <span className="rest-link">Learn more <IconArrow size={13} className="arrow" /></span>
              )}
            </>
          );
          return (
            <Reveal key={c.title} delay={i * 60}>
              {c.links ? (
                <div className="rest-card rest-card-split">{inner}</div>
              ) : (
                <a href={c.href} className="rest-card">{inner}</a>
              )}
            </Reveal>
          );
        })}
      </div>
    </div>

    <style>{`
      .rest-section { background: var(--bg); }
      .rest-head { margin-bottom: 64px; }
      .rest-grid {
        display: grid;
        grid-template-columns: repeat(3, 1fr);
        gap: 16px;
      }
      .rest-card {
        display: flex; flex-direction: column;
        padding: 24px;
        background: var(--bg-elev-1);
        border: 1px solid var(--hairline);
        border-radius: 16px;
        transition: all .25s ease;
        height: 100%;
      }
      .rest-card:hover {
        border-color: var(--accent);
        background: color-mix(in srgb, var(--accent) 4%, var(--bg-elev-1));
        transform: translateY(-2px);
      }
      .rest-card:hover .arrow { transform: translateX(3px); }

      /* ============================================================
       * DIAGRAM MOTION — off until hover, off again after.
       *
       * Two mechanisms, chosen per idea:
       *   TRANSITION  for state changes (KB fills, CDP merges, CRM
       *               opens, Loyalty fills). Reverses on unhover, so
       *               every intermediate frame is composed.
       *   LOOP        for flow (Channels traffic, Journeys marker).
       *               Kept at opacity 0 at rest, so the paused frame is
       *               invisible and nothing is ever caught mid-flight.
       *
       * :focus-within matches :hover so keyboard users get it too.
       * --e is the section's easing: exponential deceleration, never
       * bounce or elastic (those read as dated and draw attention to
       * the animation instead of the idea).
       * ============================================================ */
      .rest-section { --e: cubic-bezier(0.22, 1, 0.36, 1); }

      /* ---- Knowledge: feeds draw in, the brain fills ---- */
      .rv-kb .kb-feed {
        stroke-dasharray: 60; stroke-dashoffset: 60; opacity: 0;
        transition: stroke-dashoffset .62s var(--e), opacity .3s ease;
        transition-delay: calc(var(--i) * 70ms);
      }
      .rest-card:hover .rv-kb .kb-feed,
      .rest-card:focus-within .rv-kb .kb-feed { stroke-dashoffset: 0; opacity: 0.75; }
      .rv-kb .kb-dot { transition: opacity .4s ease .34s, transform .5s var(--e) .34s; transform-origin: 100px 40px; transform: scale(0.4); }
      .rest-card:hover .rv-kb .kb-dot,
      .rest-card:focus-within .rv-kb .kb-dot { opacity: 1; transform: scale(1); }
      .rv-kb .kb-halo { transition: opacity .6s ease .3s, transform .8s var(--e) .3s; transform-origin: 100px 40px; transform: scale(0.55); }
      .rest-card:hover .rv-kb .kb-halo,
      .rest-card:focus-within .rv-kb .kb-halo { opacity: 0.1; transform: scale(1); }
      .rv-kb .kb-ring { transition: opacity .5s ease .25s, transform .7s var(--e) .25s; transform-origin: 100px 40px; }
      .rest-card:hover .rv-kb .kb-ring,
      .rest-card:focus-within .rv-kb .kb-ring { opacity: 0.6; transform: scale(1.08); }

      /* ---- Channels: messages run the lines into the inbox ---- */
      .rv-ch .ch-msg { opacity: 0; animation-play-state: paused; transition: opacity .25s ease; }
      .rest-card:hover .rv-ch .ch-msg,
      .rest-card:focus-within .rv-ch .ch-msg { opacity: 1; animation-play-state: running; }
      .rv-ch .ch-inbox { transition: stroke-width .3s ease, filter .3s ease; }
      .rest-card:hover .rv-ch .ch-inbox,
      .rest-card:focus-within .rv-ch .ch-inbox { stroke-width: 1.6; }

      /* ---- CRM: rows open to show the bookings underneath ---- */
      .rv-crm .crm-stay {
        transition: opacity .34s var(--e), transform .34s var(--e);
        transform: translateX(-5px);
        transition-delay: calc((var(--i) * 110ms) + (var(--j) * 55ms));
      }
      .rest-card:hover .rv-crm .crm-stay,
      .rest-card:focus-within .rv-crm .crm-stay { opacity: 0.9; transform: translateX(0); }
      .rv-crm .crm-flag { transition: opacity .3s ease; transition-delay: calc(var(--i) * 110ms); }
      .rest-card:hover .rv-crm .crm-flag,
      .rest-card:focus-within .rv-crm .crm-flag { opacity: 1; }
      .rv-crm .crm-avatar, .rv-crm .crm-val { transition: fill .35s ease; transition-delay: calc(var(--i) * 110ms); }
      .rest-card:hover .rv-crm .crm-avatar,
      .rest-card:focus-within .rv-crm .crm-avatar { fill: var(--accent); }
      .rest-card:hover .rv-crm .crm-val,
      .rest-card:focus-within .rv-crm .crm-val { fill: var(--accent); }

      /* ---- CDP: the duplicates slide together into one record ---- */
      .rv-cdp .cdp-dupe {
        transition: transform .66s var(--e), opacity .5s ease;
        transition-delay: calc(var(--i) * 55ms);
      }
      .rest-card:hover .rv-cdp .cdp-dupe,
      .rest-card:focus-within .rv-cdp .cdp-dupe {
        transform: translate(var(--dx), var(--dy)) scale(0.9);
        opacity: 0;
      }
      .rv-cdp .cdp-one { opacity: 0; transform: scale(0.94); transform-origin: 150px 40px;
        transition: opacity .45s ease .22s, transform .6s var(--e) .22s; }
      .rest-card:hover .rv-cdp .cdp-one,
      .rest-card:focus-within .rv-cdp .cdp-one { opacity: 1; transform: scale(1); }

      /* ---- Journeys: a marker walks pre → stay → post ---- */
      .rv-jr .jr-trail {
        stroke-dasharray: 240; stroke-dashoffset: 240; opacity: 0;
        transition: stroke-dashoffset 1.5s var(--e), opacity .3s ease;
      }
      .rest-card:hover .rv-jr .jr-trail,
      .rest-card:focus-within .rv-jr .jr-trail { stroke-dashoffset: 0; opacity: 1; }
      .rv-jr .jr-head { opacity: 0; animation-play-state: paused; transition: opacity .3s ease; }
      .rest-card:hover .rv-jr .jr-head,
      .rest-card:focus-within .rv-jr .jr-head { opacity: 1; animation-play-state: running; }
      .rv-jr .jr-tp-halo { transform: scale(0.5); transform-origin: center; transform-box: fill-box;
        transition: transform .45s var(--e), opacity .45s ease;
        transition-delay: calc(var(--i) * 260ms); opacity: 0; }
      .rest-card:hover .rv-jr .jr-tp-halo,
      .rest-card:focus-within .rv-jr .jr-tp-halo { transform: scale(1); opacity: 1; }

      /* ---- Loyalty: tiers fill in sequence up to platinum ---- */
      .rv-ly .ly-fill {
        transform: scaleX(0); transform-origin: 62px center;
        transition: transform .5s var(--e);
        transition-delay: calc(var(--i) * 110ms);
      }
      .rest-card:hover .rv-ly .ly-fill,
      .rest-card:focus-within .rv-ly .ly-fill { transform: scaleX(1); }
      .rv-ly .ly-label { transition: fill .35s ease; transition-delay: calc(var(--i) * 110ms); }
      .rest-card:hover .rv-ly .ly-top .ly-label,
      .rest-card:focus-within .rv-ly .ly-top .ly-label { fill: var(--accent); }

      /* Reduced motion: resolve to the END state with no movement, so the
         idea each diagram carries survives for users who cannot take the
         animation. Looping elements stay hidden — a static dot mid-path
         would say nothing. */
      @media (prefers-reduced-motion: reduce) {
        .rest-vis * { transition: none !important; animation: none !important; }
        .rv-kb .kb-feed { stroke-dashoffset: 0; opacity: 0.75; }
        .rv-kb .kb-dot { opacity: 1; transform: scale(1); }
        .rv-kb .kb-ring { opacity: 0.6; }
        .rv-crm .crm-stay { opacity: 0.9; transform: none; }
        .rv-crm .crm-flag { opacity: 1; }
        .rv-cdp .cdp-dupe { opacity: 0.25; }
        .rv-cdp .cdp-one { opacity: 1; transform: none; }
        .rv-jr .jr-trail { stroke-dashoffset: 0; opacity: 1; }
        .rv-ly .ly-fill { transform: scaleX(1); }
      }
      .rest-vis-wrap {
        height: 110px;
        margin-bottom: 22px;
        background: var(--bg);
        border: 1px solid var(--hairline);
        border-radius: 10px;
        overflow: hidden;
        padding: 6px;
      }
      .rest-vis { width: 100%; height: 100%; display: block; }
      .rest-num {
        font-family: var(--f-mono);
        font-size: 10px;
        color: var(--ink-4);
        letter-spacing: 0.12em;
        margin-bottom: 8px;
      }
      .rest-title {
        font-family: var(--f-display);
        font-size: 26px;
        letter-spacing: -0.01em;
        margin: 0 0 8px;
        line-height: 1.1;
      }
      .rest-promise {
        font-size: 14px; color: var(--ink); font-weight: 500;
        line-height: 1.4; margin: 0 0 14px;
        min-height: 40px;
      }
      .rest-bullets { list-style: none; margin: 0 0 20px; padding: 0; flex: 1; }
      .rest-bullets li {
        font-size: 12.5px; color: var(--ink-3);
        line-height: 1.5;
        padding-left: 14px;
        position: relative;
      }
      .rest-bullets li + li { margin-top: 6px; }
      .rest-bullets li::before {
        content: "";
        position: absolute; left: 0; top: 9px;
        width: 4px; height: 1px;
        background: var(--accent);
      }
      .rest-link {
        display: inline-flex; align-items: center; gap: 8px;
        font-size: 13px;
        font-weight: 500;
        color: var(--accent);
      }
      .rest-link .arrow { transition: transform .2s ease; }
      .rest-card a.rest-link:hover .arrow { transform: translateX(3px); }

      /* Split card with multiple sub-links */
      .rest-card-split { cursor: default; }
      .rest-links {
        display: flex; flex-wrap: wrap; gap: 6px;
        margin-top: auto; padding-top: 4px;
      }
      .rest-link-pill {
        flex: 1; min-width: 0;
        padding: 9px 12px;
        border: 1px solid var(--hairline);
        border-radius: 8px;
        background: var(--bg);
        color: var(--ink) !important;
        font-size: 12.5px; font-weight: 500;
        justify-content: space-between;
        transition: all .15s ease;
      }
      .rest-link-pill:hover {
        border-color: var(--accent);
        color: var(--accent) !important;
        background: color-mix(in srgb, var(--accent) 6%, var(--bg));
      }
      @media (max-width: 1000px) {
        .rest-grid { grid-template-columns: repeat(2, 1fr); }
      }
      @media (max-width: 640px) {
        .rest-grid { grid-template-columns: 1fr; }
      }
    `}</style>
  </section>
);

window.SectionRest = SectionRest;
