/* ═══════════════════════════════════════════════════════════════════
   StayZelo — shared foundation. Loaded on EVERY page, before the page's
   own stylesheet (assets/site.css or the compiled assets/tailwind.css).

   The site runs two design systems side by side: six pages carry the
   Stitch/Tailwind build, the other ten the original site.css. Typography
   and motion are the two things that must NOT differ between them, so
   both live here, once, and both stylesheets consume these tokens rather
   than each keeping a copy that drifts.

   Contents
     1. @font-face — the one type family, self-hosted
     2. The type ramp, as custom properties
     3. Motion tokens and primitives
     4. Reduced motion and smooth scrolling
   ═══════════════════════════════════════════════════════════════════ */

/* ── 1. Fonts ─────────────────────────────────────────────────────── */
/* One family for the whole site. Latin-subset woff2, self-hosted, so no
   request leaves the origin at runtime. The upright file is a variable
   face covering 300–800, which is what lets the ramp below build its
   hierarchy out of weight rather than out of a second family. */
@font-face {
  font-family: 'Plus Jakarta Sans';
  src: url('/assets/fonts/plus-jakarta-sans-latin.woff2') format('woff2');
  font-weight: 300 800;
  font-style: normal;
  font-display: swap;
}
/* A drawn italic rather than a browser-sheared upright. Used by the hero's
   gold accent clause and by every <em> in the long-form pages. */
@font-face {
  font-family: 'Plus Jakarta Sans';
  src: url('/assets/fonts/plus-jakarta-sans-latin-italic.woff2') format('woff2');
  font-weight: 300 800;
  font-style: italic;
  font-display: swap;
}
/* Subset to the glyphs these pages actually use — 105KB rather than the
   ~4MB full icon font. Regenerate via the icon_names= parameter on the
   Google Fonts CSS endpoint if a new icon is introduced. Only the Stitch
   pages draw icons, but the declaration is inert until something asks
   for the family, so it costs the other pages nothing. */
@font-face {
  font-family: 'Material Symbols Outlined';
  src: url('/assets/fonts/material-symbols-subset.woff2') format('woff2');
  font-weight: 100 700;
  font-style: normal;
  font-display: block;
}

/* ── 2. Type ramp ─────────────────────────────────────────────────── */
/* Sizes are held at exactly what the site already shipped, so nothing
   re-lays out. What changes is weight, tracking and line-height: the
   headings used to be set in a serif at weight 500, which reads correctly
   for that face and much too light for a geometric sans. A sans also
   needs real negative tracking above ~28px, and the serif's generous
   line-heights leave display type looking unset once the x-height goes up.

   Hierarchy is therefore carried by size + weight + tracking + leading.
   There is no second family to carry it. */
:root {
  --ff: 'Plus Jakarta Sans', system-ui, -apple-system, 'Segoe UI', Roboto,
        'Helvetica Neue', Arial, sans-serif;

  /* Display — the hero headline. */
  --t-display:        3.5rem;      /* 56px */
  --t-display-lh:     3.75rem;     /* 60px */
  --t-display-ls:     -0.032em;
  --t-display-m:      2.25rem;     /* 36px */
  --t-display-m-lh:   2.625rem;    /* 42px */
  --t-display-m-ls:   -0.028em;

  /* h2 — section headings. */
  --t-h2:             2.5rem;      /* 40px */
  --t-h2-lh:          2.875rem;    /* 46px */
  --t-h2-ls:          -0.026em;
  --t-h2-m:           1.75rem;     /* 28px */
  --t-h2-m-lh:        2.125rem;    /* 34px */
  --t-h2-m-ls:        -0.022em;

  /* h3 — sub-section and large card headings. */
  --t-h3:             1.75rem;     /* 28px */
  --t-h3-lh:          2.125rem;    /* 34px */
  --t-h3-ls:          -0.020em;
  --t-h3-m:           1.25rem;     /* 20px */
  --t-h3-m-lh:        1.625rem;    /* 26px */
  --t-h3-m-ls:        -0.016em;

  /* h4 — card headings. */
  --t-h4:             1.25rem;     /* 20px */
  --t-h4-lh:          1.6875rem;   /* 27px */
  --t-h4-ls:          -0.015em;

  /* Title — the smallest heading step; also the active nav item. */
  --t-title:          1rem;        /* 16px */
  --t-title-lh:       1.5rem;      /* 24px */
  --t-title-ls:       -0.006em;

  /* Body. */
  --t-body-lg:        1.125rem;    /* 18px */
  --t-body-lg-lh:     1.875rem;    /* 30px */
  --t-body:           0.9375rem;   /* 15px */
  --t-body-lh:        1.5rem;      /* 24px */
  --t-body-sm:        0.8125rem;   /* 13px */
  --t-body-sm-lh:     1.25rem;     /* 20px */

  /* UI. */
  --t-button:         0.875rem;    /* 14px */
  --t-button-lh:      1.25rem;     /* 20px */
  --t-button-ls:      0.005em;
  --t-eyebrow:        0.75rem;     /* 12px */
  --t-eyebrow-lh:     1rem;        /* 16px */
  --t-eyebrow-ls:     0.12em;

  /* Weights. Named by role so a heading's weight is changed in one place
     rather than hunted down across two stylesheets. */
  --w-display:  800;
  --w-heading:  700;
  --w-subhead:  650;
  --w-medium:   600;
  --w-body:     400;

  /* ── 3. Motion tokens ──────────────────────────────────────────── */
  /* --ease-soft is the curve site.css already used for its scroll reveal;
     --ease-out is its slightly firmer sibling, for entrances and hovers. */
  --ease-out:     cubic-bezier(.22, .61, .36, 1);
  --ease-soft:    cubic-bezier(.2, .7, .3, 1);
  --dur-fast:     160ms;
  --dur:          220ms;
  --dur-reveal:   560ms;
  --reveal-shift: 16px;
}

/* ── 4. Motion ────────────────────────────────────────────────────── */

html { scroll-behavior: smooth; }

/* Every "hidden until animated" state lives inside this one query, so a
   reader who asks for reduced motion can never end up with an element
   stuck invisible. The reduce branch further down only has to undo
   transitions — it is not load-bearing for visibility. */
@media (prefers-reduced-motion: no-preference) {

  /* The page arriving: one orchestrated sequence per hero, not five
     scattered ones. Pure CSS, so it runs before any script parses and
     needs no .js gate — nothing is left hidden if the script never
     arrives, because the animation itself is what reveals it. */
  .hero-seq > * {
    opacity: 0;
    transform: translateY(14px);
    animation: heroIn .7s var(--ease-out) forwards;
  }
  .hero-seq > *:nth-child(1) { animation-delay: .08s; }
  .hero-seq > *:nth-child(2) { animation-delay: .16s; }
  .hero-seq > *:nth-child(3) { animation-delay: .24s; }
  .hero-seq > *:nth-child(4) { animation-delay: .32s; }
  .hero-seq > *:nth-child(5) { animation-delay: .40s; }
  .hero-seq > *:nth-child(6) { animation-delay: .48s; }

  /* A single element that should arrive with the hero rather than on
     scroll — the homepage's guest-menu mockup, which is already on
     screen at load and would otherwise pop in late. */
  .hero-late {
    opacity: 0;
    transform: translateY(18px);
    animation: heroIn .8s var(--ease-out) .42s forwards;
  }

  /* Scroll reveal.

     Gated on .js (stamped on <html> by an inline script in the head) so
     the hidden state only ever exists where the observer can undo it.
     Without the gate, any reader that does not run JS — GPTBot,
     ClaudeBot and PerplexityBot among them — gets a page of invisible
     content. .rise is the name the original pages already use; the two
     data- attributes are the names new markup uses. */
  .js [data-reveal],
  .js [data-reveal-group] > *,
  .js .rise {
    opacity: 0;
    transform: translateY(var(--reveal-shift));
  }
  .js [data-reveal].in,
  .js [data-reveal-group] > .in,
  .js .rise.in {
    opacity: 1;
    transform: none;
    transition: opacity var(--dur-reveal) var(--ease-soft),
                transform var(--dur-reveal) var(--ease-soft);
  }
}

@keyframes heroIn { to { opacity: 1; transform: none; } }

/* Nothing here animates anything but opacity and transform, so every
   reveal and hover stays on the compositor and holds up on a phone. */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation: none !important;
    transition: none !important;
  }
  /* Anything the motion block would have faded in stays plainly visible. */
  .hero-seq > *,
  .hero-late,
  [data-reveal],
  [data-reveal-group] > *,
  .rise {
    opacity: 1 !important;
    transform: none !important;
  }
}
