/* ==========================================================================
   Expand — expandmc.com
   Values come from the Figma file (Expand Site), one block per artboard:
   mobile 402×874 · tablet portrait 834×1194 · tablet landscape 1194×834 ·
   desktop 1280×832. Layout stays fluid between them.
   ========================================================================== */

/* Fonts ----------------------------------------------------------------------
   TRIAL FILES: martina-plantijn-regular.woff2 (Klim test font) and
   suisse-intl-regular.woff2 (Swiss Typefaces trial) must be replaced with the
   licensed web fonts before launch — drop the new files in with the same
   names. The trials lack a few glyphs (’ and @), which fall back to the next
   font in each stack until then. IBM Plex Sans is free (SIL OFL). */
@font-face {
  font-family: "Martina Plantijn";
  src: url("assets/fonts/martina-plantijn-regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Suisse Intl";
  src: url("assets/fonts/suisse-intl-regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Sans";
  src: url("assets/fonts/ibm-plex-sans-regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Tokens ------------------------------------------------------------------ */
:root {
  --green: #102b1e;
  --cream: #f2ebdd;
  --ink: #6b5a38;
  --white: #fff;

  --serif: "Martina Plantijn", Georgia, "Times New Roman", serif;
  --sans: "Suisse Intl", "IBM Plex Sans", "Helvetica Neue", Arial, sans-serif;
  --label: "IBM Plex Sans", "Helvetica Neue", Arial, sans-serif;

  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-soft: cubic-bezier(0.2, 0.65, 0.25, 1);
}

/* Base -------------------------------------------------------------------- */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  background: var(--cream);
}

body {
  margin: 0;
  background: var(--cream);
  color: var(--ink);
  font-family: var(--sans);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

img {
  display: block;
  max-width: none;
}

p {
  margin: 0;
}

a {
  color: inherit;
}

a:focus-visible {
  outline: 1px solid currentColor;
  outline-offset: 4px;
}

/* focus target for the scroll cue — no ring around the whole section */
.manifesto:focus {
  outline: none;
}

/* Small caps-style labels (IBM Plex Sans, uppercase). The footer keeps the
   Figma spec (12 / 16, −0.24 tracking); the hero corners are opened up a
   little so they breathe on the texture. */
.hero__bar,
.hero__scroll,
.manifesto__footer {
  font-family: var(--label);
  font-size: 12px;
  font-weight: 400;
  line-height: 16px;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  white-space: nowrap;
}

.hero__bar,
.hero__scroll {
  font-size: 13px;
  line-height: 18px;
  letter-spacing: 0.04em;
}

/* ==========================================================================
   Hero
   ========================================================================== */
.hero {
  /* mobile — iPhone 16 & 17 Pro, 402 × 874 */
  --pad-l: 17px;
  --pad-r: 17px;
  --bar-top: 49px;
  --scroll-bottom: 50px;
  --e-w: 99.8963%;          /* 401.583 / 402 */
  --e-left: 0%;
  --e-tx: 0%;
  --e-top: 50.05%;          /* E is vertically centred */
  --e-ty: -50%;
  --tex-pos: 50% 0%;        /* which part of the texture shows (matches Figma) */
  --mark-z: 3;              /* starship sits above the texture */

  position: relative;
  /* full screen, including behind mobile Safari's toolbar (large viewport) */
  height: 100vh;
  height: 100lvh;
  min-height: 420px;
  overflow: hidden;
  container-type: size;
  isolation: isolate;
  background: var(--green);
  color: var(--white);
}

/* Big “E” swoosh (Figma: path1, flipped vertically) */
.hero__e {
  position: absolute;
  z-index: 0;
  top: var(--e-top);
  left: var(--e-left);
  width: var(--e-w);
  height: var(--e-h, auto);
  aspect-ratio: 1281.02 / 806.976;   /* used when --e-h is auto */
  translate: var(--e-tx) var(--e-ty);
}

.hero__e svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}

.hero__e-shape {
  fill: #173c2a;
}

/* cream copy on top: only visible during the intro, faded out as the E grows */
.hero__e-cream {
  opacity: 0;
  fill: #efe8db;
}

/* Light floating over the E: two soft glows masked to the E's exact shape.
   They sit under the corduroy, so they catch the ribs like light on fabric.
   (Motion is added in the block at the bottom; without it they stay put.) */
.hero__e-glint {
  position: absolute;
  inset: 0;
  overflow: hidden;
  -webkit-mask: url("assets/img/e-mask.svg") 0 0 / 100% 100% no-repeat;
  mask: url("assets/img/e-mask.svg") 0 0 / 100% 100% no-repeat;
  pointer-events: none;
}

.hero__e-glint::before,
.hero__e-glint::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  background: radial-gradient(closest-side,
    rgba(239, 232, 219, var(--glow)) 0%,
    rgba(239, 232, 219, calc(var(--glow) * 0.45)) 50%,
    rgba(239, 232, 219, 0) 100%);
}

/* main glow: drifts along the swoosh, lower stroke ↔ tip */
.hero__e-glint::before {
  --glow: 0.17;
  width: 52%;
  height: 88%;
  transform: translate(38.5%, 2.3%);
}

/* second, fainter glow: circles through the bowl */
.hero__e-glint::after {
  --glow: 0.1;
  width: 34%;
  height: 60%;
  transform: translate(67.6%, 96.7%);
}

/* intro: the small E that draws itself, centred (main.js sets its width) */
.hero__loader {
  display: none;
  position: absolute;
  z-index: 1;
  top: 50%;
  left: 50%;
  width: 36%;
  aspect-ratio: 1281.02 / 806.976;
  translate: -50% -50%;
  fill: #efe8db;
}

.intro .hero__loader {
  display: block;
}

.hero__loader svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
}

/* intro reveal strokes (see main.js) */
.e-stroke {
  stroke-dasharray: 1;
}

/* Starship mark */
.hero__mark {
  position: absolute;
  z-index: var(--mark-z);
  top: calc(var(--bar-top) + 6.5px);   /* centred on the two 18px lines */
  left: 50%;
  width: 52.1533px;
  height: 22.998px;
  translate: -50% 0;
}

/* Corduroy: woven at the screen's own resolution by assets/js/corduroy.js,
   then blended hard-light at 25% over everything except the type (as in Figma). */
.hero__texture {
  position: absolute;
  z-index: 2;
  inset: 0;
  opacity: 0.25;
  mix-blend-mode: hard-light;
  pointer-events: none;
}

.hero__texture canvas {
  display: block;
  width: 100%;
  height: 100%;
  opacity: 0;
  transition: opacity 1.2s ease;
}

.hero__texture.is-woven canvas {
  opacity: 1;
}

/* Without JS (or workers): Figma's render of the fabric as an image */
.no-js .hero__texture,
.no-weave .hero__texture {
  background: url("assets/img/texture-2x.webp") var(--tex-pos) / cover no-repeat;
  background-image: image-set(
    url("assets/img/texture-1x.avif") 1x type("image/avif"),
    url("assets/img/texture-2x.avif") 2x type("image/avif"),
    url("assets/img/texture-1x.webp") 1x type("image/webp"),
    url("assets/img/texture-2x.webp") 2x type("image/webp")
  );
}

/* Top bar: location left, brand + contact right */
.hero__bar {
  position: absolute;
  z-index: 4;
  top: var(--bar-top);
  left: max(var(--pad-l), env(safe-area-inset-left));
  right: max(var(--pad-r), env(safe-area-inset-right));
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
}

.hero__contact {
  text-align: right;
}

.hero__contact a {
  text-decoration: underline;
  text-decoration-thickness: from-font;
  text-underline-position: from-font;
}

.only-wide {
  display: none;
}

/* Scroll cue */
.hero__scroll {
  position: absolute;
  z-index: 4;
  bottom: var(--scroll-bottom);
  bottom: calc(var(--scroll-bottom) + 100lvh - 100svh);   /* above mobile toolbars */
  left: 50%;
  translate: -50% 0;
  text-decoration: none;
}

.hero__scroll::before {
  /* bigger tap target without moving the text */
  content: "";
  position: absolute;
  inset: -16px -24px;
}

.hero__scroll span {
  display: block;
}

/* ==========================================================================
   Manifesto
   ========================================================================== */
.manifesto {
  /* mobile — 402 wide, content flows */
  --pad-top: 36px;
  --pad-bottom: 67.87px;
  --pad-x: 36px;
  --title-size: clamp(28px, 8.96vw, 36px);
  --gap-flag: 22px;         /* flag → title */
  --gap-title: 38px;        /* title → body */
  --gap-body: 32px;         /* body → rule */
  --gap-rule: 25px;         /* rule → footer */

  display: flex;
  flex-direction: column;
  align-items: center;
  padding: var(--pad-top) var(--pad-x) var(--pad-bottom);
  background: var(--cream);
  overflow-x: clip;
}

.manifesto__col {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
  max-width: 617px;
}

.manifesto__flag {
  width: 38px;
  height: 25px;
}

.manifesto__title {
  margin: var(--gap-flag) 0 0;
  width: max-content;
  max-width: calc(100vw - 16px);
  font-family: var(--serif);
  font-size: var(--title-size);
  font-weight: 400;
  line-height: 1.2;
  line-height: round(1.2em, 1px); /* Figma snaps line heights to whole pixels */
  text-align: center;
}

.manifesto__body {
  width: 100%;
  margin-top: var(--gap-title);
  font-size: 16px;
  line-height: 21px;       /* 130%, snapped to whole pixels like Figma */
}

.manifesto__body p + p {
  margin-top: 21px;
}

.manifesto__body a {
  text-decoration: none;
}

.manifesto__body a:hover {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}

.manifesto__rule {
  width: 100%;
  height: 0;
  margin: var(--gap-body) 0 0;
  border: 0;
  border-top: 1px solid var(--ink);
}

.manifesto__footer {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  width: 100%;
  margin-top: var(--gap-rule);
}

.manifesto__footer p {
  flex: 0 0 164px;
}

.manifesto__footer .manifesto__tagline {
  flex-basis: 98px;
  text-align: right;
}

.manifesto__cowboy {
  flex: none;
  width: 60.851px;
  height: 38.1333px;
}

.manifesto__cowboy img {
  width: 100%;
  height: 100%;
  transform: scaleY(-1);
}

/* ==========================================================================
   Breakpoints
   ========================================================================== */

/* Tablet portrait — iPad Pro 11", 834 × 1194 */
@media (min-width: 600px) and (orientation: portrait) {
  .hero {
    --pad-l: 57px;
    --pad-r: 57px;
    --bar-top: 42px;
    --scroll-bottom: 63px;
    --e-w: 101.0658%;       /* 842.889 / 834 */
    --e-top: 52.47%;
    --tex-pos: 25% 0%;
  }

  .manifesto {
    --pad-top: 32px;
    --pad-bottom: 75.87px;  /* keeps the design's 174 / 218 split at 1194 tall */
    --title-size: 48px;
    --gap-flag: 36px;
    --gap-title: 61px;
    --gap-body: 89px;
    --gap-rule: 37px;

    min-height: 100vh;
    min-height: 100svh;
    justify-content: center;
  }
}

/* Tablet landscape — iPad Pro 11", 1194 × 834 */
@media (min-width: 600px) and (orientation: landscape) {
  .hero {
    --pad-l: 46px;
    --pad-r: 46px;
    --bar-top: 47px;
    --scroll-bottom: 34px;
    /* E spans the frame like Figma (1214.35 × 764.98 in 1194 × 834, 35 from
       the top). On other window shapes it stretches to keep that fit, capped
       at 25% wider / 15% taller than its natural proportions. */
    --e-w: calc(100cqw * 1.017043);
    --e-h: clamp(calc(100cqw * 0.640692 / 1.25), 91.72cqh, calc(100cqw * 0.640692 * 1.15));
    --e-left: 0%;
    --e-tx: 0%;
    --e-top: 4.197%;
    --e-ty: 0%;
  }

  .manifesto {
    --pad-top: 32px;
    --pad-bottom: 35.87px;
    --title-size: 48px;
    --gap-flag: 28px;
    --gap-title: 42px;
    --gap-body: 40px;
    --gap-rule: 29px;

    min-height: 100vh;
    min-height: 100svh;
    justify-content: center;
  }
}

/* Desktop — MacBook Air, 1280 × 832 */
@media (min-width: 1240px) and (orientation: landscape) {
  .hero {
    --pad-l: 37px;
    --pad-r: 38px;
    --bar-top: 50px;
    --scroll-bottom: 25px;
    /* corner to corner like Figma: 1281.02 × 806.98 in 1280 × 832
       (same stretch limits as above) */
    --e-w: calc(100cqw * 1.000797);
    --e-h: clamp(calc(100cqw * 0.63045 / 1.25), 96.995cqh, calc(100cqw * 0.63045 * 1.15));
    --e-left: 0%;
    --e-top: 0%;
    --tex-pos: 0% 0%;
    --mark-z: 1;            /* on desktop the starship sits under the texture */
  }

  .manifesto {
    --pad-bottom: 69.87px;
    --gap-flag: 21px;
    --gap-rule: 22px;
  }
}

@media (min-width: 600px) {
  .only-wide {
    display: inline;
  }

  /* cowboy sits dead centre under the text column (on phones there's no room) */
  .manifesto__footer {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
  }

  .manifesto__footer .manifesto__tagline {
    justify-self: end;
  }

  .only-narrow {
    display: none;
  }
}

/* ==========================================================================
   Motion — only when JS is running and the visitor hasn't asked for less
   ========================================================================== */
@media (prefers-reduced-motion: no-preference) {
  /* Intro: main.js draws the E, then grows it into place. It stays hidden
     until then (with a failsafe in case the script never runs). */
  .js .hero__e {
    opacity: 0;
    animation: e-failsafe 0.6s ease 4s forwards;
  }

  .js.intro .hero__e {
    animation: none;             /* the loader draws first; the big E stays hidden */
  }

  .js.intro-grow .hero__e,
  .js.is-ready .hero__e {
    opacity: 1;
    animation: none;
  }

  @keyframes e-failsafe {
    to { opacity: 1; }
  }

  /* the light floats over the E continuously once the intro is done */
  .js .hero__e-glint {
    opacity: 0;
    transition: opacity 2.4s ease 0.4s;
  }

  .js.is-ready .hero__e-glint {
    opacity: 1;
  }

  .hero__e-glint::before {
    animation:
      glow-drift 10s cubic-bezier(0.45, 0, 0.55, 1) infinite alternate,
      glow-breathe 7s ease-in-out infinite alternate;
  }

  .hero__e-glint::after {
    animation:
      glow-orbit 15s ease-in-out infinite,
      glow-breathe 10s ease-in-out 2s infinite alternate;
  }

  .hero.is-offscreen .hero__e-glint::before,
  .hero.is-offscreen .hero__e-glint::after,
  .hero.is-offscreen .hero__scroll span {
    animation-play-state: paused;
  }

  @keyframes glow-drift {
    0% { transform: translate(-3.8%, 29.5%); }
    50% { transform: translate(38.5%, 2.3%); }
    100% { transform: translate(84.6%, -18.2%); }
  }

  @keyframes glow-orbit {
    0%, 100% { transform: translate(67.6%, 96.7%); }
    33% { transform: translate(132%, 66.7%); }
    66% { transform: translate(38.2%, 33.3%); }
  }

  @keyframes glow-breathe {
    from { opacity: 0.7; }
    to { opacity: 1; }
  }

  /* Hero entrance */

  .js .hero__mark,
  .js .hero__place,
  .js .hero__contact {
    opacity: 0;
    transform: translateY(-6px);
    transition:
      opacity 1s var(--ease-soft),
      transform 1.2s var(--ease-out);
  }

  .js .hero__mark { transition-delay: 0s; }
  .js .hero__place { transition-delay: 0.12s; }
  .js .hero__contact { transition-delay: 0.2s; }

  .js .hero__scroll {
    opacity: 0;
    transition: opacity 1.2s var(--ease-soft) 0.5s;
  }

  .js.is-ready .hero__mark,
  .js.is-ready .hero__place,
  .js.is-ready .hero__contact {
    opacity: 1;
    transform: none;
  }

  .js.is-ready .hero__scroll {
    opacity: 1;
  }

  /* Scroll cue: slow drift + breathe */
  .js .hero__scroll span {
    animation: scroll-cue 2.6s ease-in-out 2s infinite;
  }

  .hero__scroll:hover span,
  .hero__scroll:focus-visible span {
    animation-play-state: paused;
  }

  @keyframes scroll-cue {
    0%, 100% { transform: translateY(0); opacity: 1; }
    50% { transform: translateY(5px); opacity: 0.55; }
  }

  /* Manifesto reveals as it scrolls into view */
  .js [data-reveal] {
    opacity: 0;
    transform: translateY(18px);
    transition:
      opacity 1.1s var(--ease-soft) var(--reveal-delay, 0ms),
      transform 1.3s var(--ease-out) var(--reveal-delay, 0ms);
  }

  .js .manifesto__rule[data-reveal] {
    transform: scaleX(0);
    transition:
      opacity 0.6s var(--ease-soft) var(--reveal-delay, 0ms),
      transform 1.4s var(--ease-out) var(--reveal-delay, 0ms);
  }

  .js [data-reveal].is-visible {
    opacity: 1;
    transform: none;
  }
}
