// 3C Detailing — The Winter Menu (season 2026–27)
//
// Source of truth: "Winter Package.pdf" in 3c Assets / 01 Fliers and Posters.
// One data block feeds BOTH surfaces — the first-visit popup and the pricing
// section — so a price can never be right in one place and stale in the other.
// That is the whole reason this is a file and not markup in two components.
//
// 🚨 Seasonal Ceramic is NOT a new product. It is the same "Seasonal Coating"
// the pricing matrix already sells, quoted here at its Sedan price. If its
// price moves, it moves in PRICE_PACKAGES / BOOKING_SERVICES too — three
// places, because the matrix scales by vehicle and this menu quotes one
// starting figure.
//
// ⚠️ Every price is "starting" — base vehicle, taxes additional, scaling with
// size and condition exactly like the standard tiers. The flier says so in its
// footnote and so does the section, because a winter price presented as final
// is the one a customer will hold you to on a Suburban.

const WINTER_SEASON = '2026-27';

// When the popup is allowed to appear at all.
//
// 📌 It opens in SEPTEMBER, not November. The first section of the menu is
// pre-season prep — "armor up before the first salt" — which is worthless
// advice once the salt is down. The season the menu SELLS is November–March;
// the window in which selling it works starts earlier.
const WINTER_WINDOW = { from: '2026-09-01', to: '2027-03-31' };

const WINTER_PHONE = '(845) 901-5573';
const WINTER_TEL = '+18459015573';

const WINTER_MENU = {
  season: WINTER_SEASON,
  months: 'November – March',
  intro: 'Hudson Valley winters run on road salt, brine and slush. This menu is built to fight corrosion and hold a finish through the cold — not to sell a summer detail with a snowflake on it.',

  // ── 01 / Pre-season prep ────────────────────────────────────────────────
  prep: {
    num: '01 / Pre-season prep',
    title: 'Armor up before the first salt.',
    lede: 'The goal is a sacrificial protective layer on every surface salt touches — so winter grime rinses off instead of etching in.',
    cards: [
      {
        id: 'winter-exterior',
        eyebrow: 'Exterior only · Foundation+',
        name: 'Winter Exterior + Iron Decon',
        price: 212,
        was: 235,
        note: '10% winter discount',
        // No booking id: this package is not in BOOKING_SERVICES. Handing the
        // modal an id it does not know is silently ignored (it opens with
        // nothing selected), so these open the picker honestly instead.
        bookId: null,
        features: [
          'Full hand wash & decon',
          'Iron remover — pulls embedded salt & brake fallout',
          'Wheels, tires & glass',
          'Wheel wells & wheel barrels cleaned',
          'Hybrid ceramic sealant — 6 months of salt protection',
        ],
      },
      {
        id: 'seasonal-ceramic',
        eyebrow: 'Ceramic',
        badge: 'Most protection',
        name: 'Seasonal Ceramic',
        // 10% off the $950 list — the discount the flier promised, taken
        // against the price that actually gets invoiced.
        //
        // 🚨 The flier’s $810 was 10% off the $900 this site used to show, and
        // that $900 had been $50 under the shop since the 2026-06-11 bump. With
        // the lists aligned, the same 10% lands at $855. If Seasonal moves
        // again this has to move with it — it is a derived number kept by hand.
        price: 855,
        was: 950,
        note: '10% winter discount',
        // The percentage is now stated by the struck price, so the call to
        // action carries the deadline instead of repeating the number.
        offer: 'Book now — winter only',
        bookId: 'seasonal',
        features: [
          'Single-step gloss enhancement',
          '~1 year of ceramic protection — covers the season',
          'Slick, salt-shedding surface',
          'Easier winter washing, deeper gloss',
          'Door jambs detailed',
          'Mats cleaned & treated',
        ],
      },
      {
        id: 'salt-stain-reset',
        eyebrow: 'Cabin protection',
        name: 'Salt-Stain Reset',
        price: 185,
        bookId: null,
        features: [
          'Carpet & mat salt-stain hot extraction',
          'Rubber / all-weather mat treatment',
          'Express surface wipe + vacuum',
        ],
      },
    ],
  },

  // ── 02 / In-season maintenance ──────────────────────────────────────────
  maintenance: {
    num: '02 / In-season maintenance',
    title: 'The part that actually keeps salt off.',
    lede: 'Protection fails if salt sits. These fast, recurring washes are the engine of a winter book — priced to run every 2–3 weeks, November through March.',
    cards: [
      {
        id: 'salt-off-express',
        eyebrow: 'Express · ~45 min',
        name: 'Salt-Off Express',
        price: 110,
        unit: 'per visit',
        bookId: null,
        features: [
          'pH-neutral hand wash',
          'Heated wheel-well salt flush',
          'Wheel & tire deep clean',
          'Glass repellent top-up',
        ],
      },
      {
        id: 'salt-off-plus',
        eyebrow: 'Plus · ~90 min',
        badge: 'Best value',
        name: 'Salt-Off Plus',
        price: 165,
        unit: 'per visit',
        bookId: null,
        features: [
          'Everything in Express',
          'Fresh spray-sealant re-coat (restores protection)',
          'Door jambs & sills cleared of salt',
          'Interior quick vac + mat rinse',
        ],
      },
    ],
  },

  // ── Winter Wash Club ────────────────────────────────────────────────────
  club: {
    title: 'Lock the cadence. Keep the discount.',
    lede: 'Members hold their slot every two weeks all season and keep 10% off every add-on and detail through March — the cheapest way to run a winter car.',
    tiers: [
      { name: 'Bronze Winter', included: '1 × Salt-Off Express / month', rate: 80 },
      { name: 'Silver Winter', included: '2 × Salt-Off Express / month', rate: 140 },
      { name: 'Gold Winter', included: '2 × Salt-Off Plus / month + priority booking', rate: 250 },
    ],
  },

  // ── 03 / Off-season storage ─────────────────────────────────────────────
  storage: {
    num: '03 / Off-season storage',
    title: 'Park it for the winter.',
    lede: "For the cars that shouldn't see salt at all. Secure indoor storage in Kingston and Albany, November through March.",
    name: 'Winter Vehicle Storage',
    eyebrow: 'Off-season · monthly',
    // Real rates by vehicle type (Ryder, 2026-09-07), replacing the single
    // 'from $200' anchor the flier and the promo bar both carried. $150 is now
    // the from-price everywhere it appears — the bar, the storage band and this
    // card all have to agree, or the cheapest option reads as the dearest.
    //
    // Ordered by price, which is also the order someone scanning for their own
    // vehicle expects. Every type the feature list offers to store now has a
    // rate; if a type is ever added there, it needs one here too.
    priceLead: 'Starting at',
    price: '$150/mo',
    priceSub: 'Kingston & Albany · by vehicle type',
    rates: [
      { k: 'Motorcycles', v: 150 },
      { k: 'Cars', v: 250 },
      { k: 'Trucks', v: 300 },
      { k: 'Boats', v: 350 },
      // ⚠️ A STRING, not a number. RVs vary too much to carry one rate, so
      // this row prints the text as-is and the renderer suppresses the "/mo"
      // suffix — a "Call for pricing/mo" would be worse than no price at all.
      { k: 'RVs', v: 'Call for pricing' },
    ],
    features: [
      'Secure, monitored indoor storage',
      'Kingston & Albany locations',
      'Cars · trucks · boats · RVs · motorcycles',
      'Battery tender & tire-flat-spot checks',
      'Scheduled access by appointment',
      'Covered, dry, salt-free bays',
    ],
    // Work that can happen WHILE the vehicle is stored. It is the argument for
    // storing with a shop rather than a unit: the car comes out ready instead
    // of needing a garage visit first.
    mechanical: {
      title: 'Service it while it sits.',
      lede: 'Mechanical work can be carried out during storage, so it comes out of the bay ready to drive rather than needing a garage first.',
      items: [
        'Oil & filter change',
        'Tire rotation',
        'Fluid top-off',
        'Other work on request',
      ],
    },
    facts: [
      { k: 'Term', v: '6 months', sub: 'November – April' },
      { k: 'Locations', v: '2', sub: 'Kingston & Albany' },
      { k: 'Minimum stay', v: '1 month', sub: 'Month-to-month after' },
      { k: 'Pairs with', v: 'Pre-storage detail', sub: 'Wash & seal before it sits' },
    ],
  },

  footnote: 'All prices in USD, base vehicle, taxes additional — winter pricing scales with vehicle size & condition, matching our standard pricing tiers.',
};

/* ─── shared bits ─── */

const wEyebrow = {
  fontFamily: 'var(--mono)', fontSize: 10, letterSpacing: '.18em',
  textTransform: 'uppercase', color: 'var(--ink-dim)',
};
const wBadge = {
  display: 'inline-block', fontFamily: 'var(--mono)', fontSize: 9.5,
  letterSpacing: '.16em', textTransform: 'uppercase', color: '#fff',
  background: 'var(--accent)', padding: '4px 8px', borderRadius: 3, alignSelf: 'flex-start',
};
const wPrice = {
  fontFamily: 'var(--serif)', fontSize: 38, fontWeight: 500,
  letterSpacing: '-.025em', color: 'var(--ink)', lineHeight: 1,
};

function WinterCard({ card, onBook }) {
  return (
    <div style={{
      border: '1px solid var(--line)', borderRadius: 12, padding: 26,
      background: 'var(--bg-card)', display: 'flex', flexDirection: 'column', gap: 12,
    }}>
      {card.badge && <span style={wBadge}>{card.badge}</span>}
      <span style={wEyebrow}>{card.eyebrow}</span>
      <span style={{
        fontFamily: 'var(--serif)', fontSize: 22, fontWeight: 500,
        letterSpacing: '-.02em', color: 'var(--ink)', lineHeight: 1.15,
      }}>{card.name}</span>
      <ul style={{ listStyle: 'none', margin: '4px 0 0', padding: 0, display: 'flex', flexDirection: 'column', gap: 0 }}>
        {card.features.map((f) => (
          <li key={f} style={{
            fontSize: 13.5, lineHeight: 1.45, color: 'var(--ink-dim)',
            padding: '8px 0', borderTop: '1px solid var(--line)',
          }}>{f}</li>
        ))}
      </ul>
      <div style={{ marginTop: 'auto', paddingTop: 14, display: 'flex', flexDirection: 'column', gap: 4 }}>
        <span>
          <span style={wPrice}>${card.price.toLocaleString()}</span>
          <span style={{ ...wEyebrow, marginLeft: 8 }}>{card.unit || 'starting'}</span>
        </span>
        {card.was && (
          <span style={{ ...wEyebrow, color: 'var(--ink-dim)' }}>
            <s>${card.was}</s> · {card.note}
          </span>
        )}
        {card.offer && (
          <span style={{ ...wEyebrow, color: 'var(--accent)' }}>{card.offer}</span>
        )}
        <button
          className="book"
          style={{ marginTop: 10 }}
          onClick={() => onBook(card.bookId ? { serviceId: card.bookId } : null)}
        >
          Reserve
        </button>
      </div>
    </div>
  );
}

/* ─── THE WINTER MENU (pricing section) ─── */

function WinterMenu({ onBook }) {
  const m = WINTER_MENU;
  const grid = (n) => ({
    display: 'grid',
    gridTemplateColumns: `repeat(auto-fit, minmax(${n}px, 1fr))`,
    gap: 16,
  });
  return (
    <section className="section winter-menu" id="winter" style={{ background: 'var(--bg)' }}>
      <div className="shell">
        <div className="section-head">
          <div>
            <span className="section-num">Winter · {m.months} · Season {m.season}</span>
            <h2 className="h-display">The <em>Winter</em> Menu.</h2>
          </div>
          <p className="lede">{m.intro}</p>
        </div>

        {/* 01 — pre-season */}
        <div style={{ marginTop: 8 }}>
          <div className="section-head" style={{ marginBottom: 22 }}>
            <div>
              <span className="section-num">{m.prep.num}</span>
              <h2 className="h-display" style={{ fontSize: 'clamp(24px,3vw,34px)' }}>{m.prep.title}</h2>
            </div>
            <p className="lede">{m.prep.lede}</p>
          </div>
          <div style={grid(260)}>
            {m.prep.cards.map((c) => <WinterCard key={c.id} card={c} onBook={onBook} />)}
          </div>
        </div>

        {/* 02 — in-season */}
        <div style={{ marginTop: 40, paddingTop: 32, borderTop: '1px solid var(--line)' }}>
          <div className="section-head" style={{ marginBottom: 22 }}>
            <div>
              <span className="section-num">{m.maintenance.num}</span>
              <h2 className="h-display" style={{ fontSize: 'clamp(24px,3vw,34px)' }}>{m.maintenance.title}</h2>
            </div>
            <p className="lede">{m.maintenance.lede}</p>
          </div>
          <div style={grid(280)}>
            {m.maintenance.cards.map((c) => <WinterCard key={c.id} card={c} onBook={onBook} />)}
          </div>
        </div>

        {/* Winter Wash Club */}
        <div style={{ marginTop: 40, paddingTop: 32, borderTop: '1px solid var(--line)' }}>
          <div className="section-head" style={{ marginBottom: 22 }}>
            <div>
              <span className="section-num">Winter Wash Club</span>
              <h2 className="h-display" style={{ fontSize: 'clamp(24px,3vw,34px)' }}>{m.club.title}</h2>
            </div>
            <p className="lede">{m.club.lede}</p>
          </div>
          <table className="matrix">
            <thead>
              <tr>
                <th style={{ width: '30%' }}>Tier</th>
                <th>Included monthly</th>
                <th>Rate</th>
                <th></th>
              </tr>
            </thead>
            <tbody>
              {m.club.tiers.map((t) => (
                <tr className="row-pkg" key={t.name}>
                  <td><span className="pkg-name">{t.name}</span></td>
                  <td><span className="pkg-desc">{t.included}</span></td>
                  <td><span className="pkg-price">${t.rate}<span style={{ ...wEyebrow, marginLeft: 6 }}>/mo</span></span></td>
                  <td><a className="book" href={`tel:${WINTER_TEL}`}>Join</a></td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>

        {/* 03 — storage */}
        <div style={{ marginTop: 40, paddingTop: 32, borderTop: '1px solid var(--line)' }}>
          <div className="section-head" style={{ marginBottom: 22 }}>
            <div>
              <span className="section-num">{m.storage.num}</span>
              <h2 className="h-display" style={{ fontSize: 'clamp(24px,3vw,34px)' }}>{m.storage.title}</h2>
            </div>
            <p className="lede">{m.storage.lede}</p>
          </div>
          <div style={{
            border: '1px solid var(--line)', borderRadius: 12, padding: 26, background: 'var(--bg-card)',
          }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 20, flexWrap: 'wrap' }}>
              <div>
                <span style={wEyebrow}>{m.storage.eyebrow}</span>
                <div style={{
                  fontFamily: 'var(--serif)', fontSize: 26, fontWeight: 500,
                  letterSpacing: '-.02em', color: 'var(--ink)', marginTop: 6,
                }}>{m.storage.name}</div>
              </div>
              <div style={{ textAlign: 'right' }}>
                {m.storage.priceLead && (
                  <div style={{ ...wEyebrow, marginBottom: 4 }}>{m.storage.priceLead}</div>
                )}
                <span style={{ ...wPrice, fontSize: 34 }}>{m.storage.price}</span>
                {m.storage.priceSub && (
                  <div style={{ ...wEyebrow, marginTop: 6 }}>{m.storage.priceSub}</div>
                )}
              </div>
            </div>
            {/* The rate card. Sits above the features because "what does it
                cost for MY thing" is the question people arrive with. */}
            {m.storage.rates && (
              <div style={{ ...grid(150), marginTop: 18, paddingTop: 18, borderTop: '1px solid var(--line)' }}>
                {m.storage.rates.map((r) => (
                  <div key={r.k}>
                    <span style={wEyebrow}>{r.k}</span>
                    <div style={{ fontFamily: 'var(--serif)', fontSize: typeof r.v === 'number' ? 24 : 17, fontWeight: 500, color: 'var(--ink)', marginTop: 4, lineHeight: 1.15 }}>
                      {typeof r.v === 'number' ? '$' + r.v : r.v}
                      {typeof r.v === 'number' && <span style={{ ...wEyebrow, marginLeft: 4 }}>/mo</span>}
                    </div>
                  </div>
                ))}
              </div>
            )}
            <div style={{ ...grid(220), marginTop: 18 }}>
              {m.storage.features.map((f) => (
                <div key={f} style={{
                  fontSize: 13.5, lineHeight: 1.45, color: 'var(--ink-dim)',
                  padding: '10px 0', borderTop: '1px solid var(--line)',
                }}>{f}</div>
              ))}
            </div>
            {m.storage.mechanical && (
              <div style={{ marginTop: 18, paddingTop: 18, borderTop: '1px solid var(--line)' }}>
                <div style={{ fontFamily: 'var(--serif)', fontSize: 20, fontWeight: 500, color: 'var(--ink)', lineHeight: 1.15 }}>
                  {m.storage.mechanical.title}
                </div>
                <div style={{ fontSize: 13.5, lineHeight: 1.5, color: 'var(--ink-dim)', margin: '6px 0 12px', maxWidth: 560 }}>
                  {m.storage.mechanical.lede}
                </div>
                <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
                  {m.storage.mechanical.items.map((x) => (
                    <span key={x} style={{ ...wEyebrow, border: '1px solid var(--line)', borderRadius: 999, padding: '6px 12px', color: 'var(--ink)' }}>{x}</span>
                  ))}
                </div>
              </div>
            )}
            <div style={{ ...grid(160), marginTop: 18, paddingTop: 18, borderTop: '1px solid var(--line)' }}>
              {m.storage.facts.map((f) => (
                <div key={f.k}>
                  <span style={wEyebrow}>{f.k}</span>
                  <div style={{
                    fontFamily: 'var(--serif)', fontSize: 20, fontWeight: 500,
                    color: 'var(--ink)', marginTop: 4, lineHeight: 1.15,
                  }}>{f.v}</div>
                  <div style={{ fontSize: 12.5, color: 'var(--ink-dim)', marginTop: 2 }}>{f.sub}</div>
                </div>
              ))}
            </div>
            <a className="book" href={`tel:${WINTER_TEL}`} style={{ marginTop: 18, display: 'inline-block' }}>
              Reserve a storage slot
            </a>
          </div>
        </div>

        <div className="matrix-foot" style={{ marginTop: 28 }}>
          <span>↳ Reserve a winter slot — {WINTER_PHONE}</span>
          <span>{m.footnote}</span>
        </div>
      </div>
    </section>
  );
}

/* ─── FIRST-VISIT POPUP ─── */

// Shown once per visitor per SEASON. The key carries the season, so next
// year's menu announces itself again to someone who dismissed this one —
// a permanent "seen it" flag would silently retire the feature after a
// single winter.
const WINTER_SEEN_KEY = '3c_winter_seen_' + WINTER_SEASON;

function winterInSeason(now) {
  const d = now || new Date();
  const iso = d.getFullYear() + '-'
    + String(d.getMonth() + 1).padStart(2, '0') + '-'
    + String(d.getDate()).padStart(2, '0');
  return iso >= WINTER_WINDOW.from && iso <= WINTER_WINDOW.to;
}

function WinterPopup({ onBook }) {
  const [open, setOpen] = React.useState(false);
  const m = WINTER_MENU;

  React.useEffect(() => {
    if (!winterInSeason()) return undefined;
    let seen = false;
    try { seen = !!localStorage.getItem(WINTER_SEEN_KEY); } catch (_) {}
    if (seen) return undefined;
    // A beat after first paint. Firing on load puts a modal over a page the
    // visitor has not seen yet, which reads as an ad rather than an offer.
    const t = setTimeout(() => setOpen(true), 1200);
    return () => clearTimeout(t);
  }, []);

  // Remember the dismissal on the way OUT, not on the way in: a popup that
  // marks itself seen before it renders would be skipped forever by anyone
  // whose tab was closed in that first second.
  const close = React.useCallback(() => {
    setOpen(false);
    try { localStorage.setItem(WINTER_SEEN_KEY, String(Date.now())); } catch (_) {}
  }, []);

  React.useEffect(() => {
    if (!open) return undefined;
    const onKey = (e) => { if (e.key === 'Escape') close(); };
    document.addEventListener('keydown', onKey);
    const prev = document.body.style.overflow;
    document.body.style.overflow = 'hidden';
    return () => {
      document.removeEventListener('keydown', onKey);
      document.body.style.overflow = prev;
    };
  }, [open, close]);

  if (!open) return null;

  const headline = [
    m.prep.cards[0], m.prep.cards[1], m.prep.cards[2],
    m.maintenance.cards[0], m.maintenance.cards[1],
  ];

  return (
    <div className="modal-bg open" onClick={close} role="dialog" aria-modal="true" aria-label="The Winter Menu">
      <div className="modal" onClick={(e) => e.stopPropagation()} style={{ maxWidth: 620 }}>
        <button className="modal-close" onClick={close} aria-label="Close"><Icon.x /></button>

        <span className="section-num" style={{ display: 'block' }}>
          {m.months} · Season {m.season}
        </span>
        <h2 className="h-display" style={{ fontSize: 'clamp(30px,5vw,44px)', margin: '6px 0 14px' }}>
          The <em>Winter</em> Menu.
        </h2>
        <p style={{ color: 'var(--ink-dim)', fontSize: 14.5, lineHeight: 1.6, margin: '0 0 20px' }}>
          {m.intro}
        </p>

        <div style={{ borderTop: '1px solid var(--line)' }}>
          {headline.map((c) => (
            <div key={c.id} style={{
              display: 'flex', justifyContent: 'space-between', alignItems: 'baseline',
              gap: 14, padding: '11px 0', borderBottom: '1px solid var(--line)',
            }}>
              <span style={{ fontSize: 14.5, color: 'var(--ink)', fontWeight: 500 }}>
                {c.name}
                {c.badge && <span style={{ ...wEyebrow, color: 'var(--accent)', marginLeft: 8 }}>{c.badge}</span>}
              </span>
              <span style={{ whiteSpace: 'nowrap', fontSize: 14.5, color: 'var(--ink)' }}>
                ${c.price.toLocaleString()}
                <span style={{ ...wEyebrow, marginLeft: 6 }}>{c.unit || 'starting'}</span>
              </span>
            </div>
          ))}
          <div style={{
            display: 'flex', justifyContent: 'space-between', alignItems: 'baseline',
            gap: 14, padding: '11px 0', borderBottom: '1px solid var(--line)',
          }}>
            <span style={{ fontSize: 14.5, color: 'var(--ink)', fontWeight: 500 }}>Winter Wash Club</span>
            <span style={{ whiteSpace: 'nowrap', fontSize: 14.5, color: 'var(--ink)' }}>
              from ${m.club.tiers[0].rate}<span style={{ ...wEyebrow, marginLeft: 6 }}>/mo</span>
            </span>
          </div>
        </div>

        <div style={{ display: 'flex', gap: 10, marginTop: 22, flexWrap: 'wrap' }}>
          <button
            className="btn btn-primary"
            onClick={() => {
              close();
              const el = document.getElementById('winter');
              if (el) el.scrollIntoView({ behavior: 'smooth', block: 'start' });
            }}
          >
            See the full winter menu
          </button>
          <a className="btn btn-ghost" href={`tel:${WINTER_TEL}`} onClick={close}>
            Call {WINTER_PHONE}
          </a>
        </div>
        <button
          onClick={close}
          style={{
            background: 'none', border: 0, padding: '12px 0 0', cursor: 'pointer',
            fontFamily: 'var(--mono)', fontSize: 10.5, letterSpacing: '.16em',
            textTransform: 'uppercase', color: 'var(--ink-dim)',
          }}
        >
          Not now
        </button>
      </div>
    </div>
  );
}

Object.assign(window, { WINTER_MENU, WinterMenu, WinterPopup, winterInSeason });
