/* six7.group — SixSeven Group OÜ. Values from the SixSeven design system (/var/www/67/tokens). */

:root {
  --ink-900: #0E0F12;
  --ink-800: #1A1C21;
  --ink-600: #474B54;
  --ink-300: #C9C6BF;
  --paper: #F4F2EE;
  --white: #FFFFFF;
  --orange-500: #FF4D1A;
  --orange-100: #FFE4DA;
  --border-subtle: #E6E3DD;
  --wespend: #2E8F58; /* product colours: each only inside its own panel */
  --wespend-flood: #26794B; /* WeSpend's own darker green: paper text on it is 4.8:1 (on #2E8F58 it is 3.6:1) */
  --onmeal: #7A3E8F;
  --font-display: "Unbounded", "Geist", system-ui, sans-serif;
  --font-sans: "Geist", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono: "Geist Mono", ui-monospace, "SF Mono", Menlo, monospace;
  --ease-out: cubic-bezier(.2, .8, .2, 1);
  --pad: clamp(24px, 4vw, 56px);
}

/* ---------- Base ---------- */

@font-face {
  font-family: "Unbounded";
  font-style: normal;
  font-weight: 200 900;
  font-display: swap;
  src: url(/assets/fonts/unbounded-latin.woff2) format("woff2");
  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;
}
@font-face {
  font-family: "Geist";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url(/assets/fonts/geist-latin.woff2) format("woff2");
  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;
}
@font-face {
  font-family: "Geist Mono";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url(/assets/fonts/geist-mono-latin.woff2) format("woff2");
  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;
}

@property --r { syntax: "<percentage>"; inherits: false; initial-value: 0%; }

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

html {
  background: var(--ink-900);
  scroll-snap-type: y mandatory;
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--ink-900);
  color: var(--ink-900);
  font: 400 15px/1.55 var(--font-sans);
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
}

h1, h2, p { margin: 0; }
img, svg { display: block; }

a {
  color: inherit;
  text-decoration: underline transparent;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: color 160ms var(--ease-out), text-decoration-color 160ms var(--ease-out);
}
a:focus-visible { outline: 2px solid var(--orange-500); outline-offset: 4px; }

::selection { background: var(--orange-100); color: var(--ink-900); }

.label { font: 500 12px/1.4 var(--font-mono); letter-spacing: .08em; text-transform: uppercase; }

/* The page is two screens: the hero and the products (one screen per panel when they stack). */
.hero,
.product { scroll-snap-align: start; scroll-snap-stop: always; }

/* ---------- Hero ----------
   The page is the logo. .hero__layer is the ink version and stays in flow. main.js clones it into
   .hero__layer--orange (same DOM, same grid, recoloured through --fg/--hi/--muted/--dot) and puts the clone
   in .hero__orange. That wrapper slides right by --seam and clips; the clone inside slides left by the same
   amount, so only the edge moves and every glyph stays on the pixel of its ink twin. Both moves are
   compositor-only transforms (percentages of the hero width). Wherever the edge crosses a letter, the letter
   flips colour exactly there. The copy ignores the pointer, so hover and focus land on the ink links; the
   :has() rules mirror those states onto both copies. */

.hero {
  --seam: 50%;
  position: relative;
  display: grid;
  min-height: 100svh;
  overflow: clip;
  background: var(--ink-900);
}

.hero__layer {
  --fg: var(--paper);
  --hi: var(--orange-500);
  --muted: var(--ink-300);
  --dot: var(--orange-500);
  display: grid;
  grid-template-rows: auto 1fr auto;
  padding: clamp(20px, 4vw, 56px);
  color: var(--fg);
  will-change: transform; /* both copies rasterise as compositor layers, so their glyphs land on the same pixels */
}

.hero__orange {
  position: absolute;
  inset: 0;
  overflow: clip;
  transform: translateX(var(--seam));
  will-change: transform;
  pointer-events: none;
}

.hero__layer--orange {
  --fg: var(--ink-900);
  --hi: var(--ink-900);
  --muted: var(--ink-800);
  --dot: var(--paper);
  position: absolute;
  inset: 0;
  background: var(--orange-500); /* on the copy, not the wrapper: an opaque layer renders text like the ink one */
  transform: translateX(calc(-1 * var(--seam)));
}

.hero__head,
.hero__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.hero__home img { height: 36px; width: auto; }

.hero:has(.hero__down:hover) .hero__down { text-decoration-color: var(--hi); }

.hero:has(.hero__home:focus-visible) .hero__home,
.hero:has(.hero__down:focus-visible) .hero__down { outline: 2px solid var(--hi); outline-offset: 4px; }

.hero__centre { align-self: center; padding-block: clamp(24px, 4svh, 96px); }

.wordmark {
  margin-left: -.035em; /* optical: S and G carry a .035em side bearing */
  font: 800 clamp(48px, min(15.5vw, 24svh), 236px)/.9 var(--font-display); /* the hero fits one screen */
  letter-spacing: -.045em;
}
.wordmark__lines,
.wordmark__line { display: block; }

/* Each line clips its letters vertically for the entrance; the padding (cancelled by margin) keeps the
   i-dot and the p descender inside the clip box without moving anything. */
.wordmark__line { overflow-y: clip; white-space: nowrap; padding-top: .06em; margin-top: -.06em; }
.wordmark__line + .wordmark__line { --o: 8; padding: 0 0 .1em; margin: 0 0 -.1em; color: var(--hi); }

.l {
  display: inline-block;
  animation: rise 700ms var(--ease-out) backwards;
  animation-delay: calc((var(--n, 0) + var(--o, 0)) * 28ms);
}
.l:nth-child(2) { --n: 1; }
.l:nth-child(3) { --n: 2; }
.l:nth-child(4) { --n: 3; }
.l:nth-child(5) { --n: 4; }
.l:nth-child(6) { --n: 5; }
.l:nth-child(7) { --n: 6; }
.l:nth-child(8) { --n: 7; }

.tagline {
  max-width: 42ch;
  margin-top: 32px;
  font: 500 clamp(17px, 1.6vw, 22px)/1.4 var(--font-sans);
}
.tagline span { display: block; color: var(--muted); }

.hero__down { display: inline-flex; align-items: center; gap: 10px; }
.hero__legal { color: var(--muted); }

.split { display: flex; width: 12px; height: 12px; }
.split span { flex: 1; background: var(--fg); }
.split span + span { background: var(--dot); }

.hero__head,
.tagline { animation: lift 600ms var(--ease-out) 300ms backwards; }
.hero__foot { animation: lift 600ms var(--ease-out) 500ms backwards; }

@keyframes rise { from { transform: translateY(110%); } }
@keyframes lift { from { opacity: 0; transform: translateY(12px); } }

/* ---------- Products ----------
   Each panel is one screen and one link. main.js clones .product__layer into .product__layer--flood: the
   same content in the product colour, clipped to a circle of radius --r around --mx/--my, which main.js sets
   on pointer enter (the flood grows from there) and leave (it shrinks there). Hover grows --r, a registered
   property, to 150%. On touch the flood is simply unclipped, so the panels are always in colour. The glyph
   follows the pointer through --px/--py, eased by main.js every frame (a transform, no CSS transition). */

.products { display: flex; flex-direction: column; }

.product {
  --name: clamp(44px, 6.4vw, 104px);
  --tag: clamp(16px, 1.4vw, 20px);
  /* what sits under the name: the tagline (12px gap), the domain line (20px gap, 18.2px) and the store badges
     (24px gap, 40px); the desktop layout below redefines it */
  --below: calc(1.4 * var(--tag) + 114.2px);
  /* what the glyph row may take so the panel stays one screen: 100svh minus padding, the 56px top row, two
     24px row gaps, the name, --below and 4px of slack */
  --room: calc(100svh - 2 * var(--pad) - .95 * var(--name) - var(--below) - 108px);
  position: relative;
  overflow: clip;
}
.product--wespend { --brand: var(--wespend); --flood: var(--wespend-flood); }
.product--onmeal { --brand: var(--onmeal); --flood: var(--onmeal); }
/* The 1px divider between the panels takes no space, so each panel stays exactly one screen. */
.product + .product::after { content: ""; position: absolute; inset: 0 0 auto; height: 1px; background: var(--border-subtle); }
/* The domain link is the panel's link: its ::after covers the whole panel, under the store links (z-index 1 too,
   later in the DOM) but over the flood, so the panel's focus ring it draws shows on the colour as well. */
.product__link::after { content: ""; position: absolute; inset: 0; z-index: 1; }
.product__link:focus-visible { outline: none; }
.product__link:focus-visible::after { outline: 3px solid var(--orange-500); outline-offset: -3px; }

.product__layer {
  --glyph: var(--brand);
  --meta: var(--ink-600);
  display: grid;
  grid-template-rows: auto 1fr auto;
  gap: 24px;
  min-height: 100svh;
  padding: var(--pad);
  background: var(--paper);
  color: var(--ink-900);
}

.product__layer--flood {
  --glyph: var(--paper);
  --meta: var(--paper);
  position: absolute;
  inset: 0;
  background: var(--flood);
  color: var(--paper);
  clip-path: circle(var(--r) at var(--mx, 50%) var(--my, 50%));
  transition: --r 500ms var(--ease-out);
  pointer-events: none;
}

.product__top { display: flex; align-items: center; gap: 16px; }
.product__label,
.product__domain { color: var(--meta); }

.glyph {
  --size: min(40svh, 62vw, var(--room));
  align-self: center;
  justify-self: end;
  width: auto;
  height: var(--size);
  margin-right: calc(var(--pad) * -1 - var(--size) * .08);
  color: var(--glyph);
  transform: translate(var(--px, 0px), var(--py, 0px));
  will-change: transform;
}

/* Both glyphs draw in once (main.js adds .will-draw, then .is-in on scroll): WeSpend's two strokes, light one
   first; OnMeal's progress frame to 70 %, then the leaf sprouts from its stem. */
.will-draw .stroke { stroke-dasharray: 1 2; stroke-dashoffset: 1.01; }
.will-draw.is-in .stroke { stroke-dashoffset: 0; transition: stroke-dashoffset 900ms var(--ease-out); }
.will-draw.is-in .stroke + .stroke { transition-delay: 250ms; }

.track { opacity: .18; } /* onMeal spec: the track is the ink at .18 on light, .24 on plum */
.product__layer--flood .track { opacity: .24; }
.leaf { transform-box: fill-box; transform-origin: 0 100%; }
.will-draw .leaf { transform: scale(0); }
.will-draw.is-in .leaf { transform: none; transition: transform 500ms var(--ease-out) 650ms; }
.product--onmeal .glyph { margin-right: 0; } /* the frame is a progress ring: keep it whole, no bleed */

.product__name {
  font: 800 var(--name)/.95 var(--font-display);
  letter-spacing: -.035em;
  transition: transform 300ms var(--ease-out);
}
.product__tagline { margin-top: 12px; font: 500 var(--tag)/1.4 var(--font-sans); }
.product__domain { margin-top: 20px; font: 400 13px/1.4 var(--font-mono); }
.arrow {
  display: inline-block;
  vertical-align: -1px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform 200ms var(--ease-out);
}

/* The stores' official badges, as issued (never redrawn or recoloured), App Store first as Apple asks, one 40px
   height (Apple's minimum). Each link also holds its listing's QR, shown on desktop only (below). Stacked over the
   panel link's ::after and over the flood, so the focus ring shows; the flood's copy underneath is identical. */
.stores { display: flex; flex-wrap: wrap; gap: 12px 16px; margin-top: 24px; }
.store { position: relative; z-index: 1; }
.store__badge { width: auto; height: 40px; }
.store__qr { display: none; width: 96px; height: 96px; padding: 8px; border-radius: 8px; background: var(--white); }

/* ---------- Media queries ---------- */

@media (min-width: 900px) {
  .products { flex-direction: row; }
  .product { flex: 1 1 0; }
  .product + .product::after { inset: 0 auto 0 0; width: 1px; height: auto; }
  .glyph { --size: min(58svh, 46vw, var(--room)); }
}

/* Desktop: a phone can scan these, so each listing's QR sits over its badge, and the stores take the right of the
   text block — QRs level with the tagline, badges level with the domain line. At >= 1024px the tagline beside
   them wraps to 3 lines at most, still shorter than the stores column. */
@media (min-width: 1024px) and (hover: hover) and (pointer: fine) {
  .product { --below: 160px; } /* the stores column: 12px gap, 96px QR, 12px gap, 40px badge */
  .product__bottom {
    display: grid;
    grid-template: "name name" auto "tag stores" auto "domain stores" 1fr / minmax(0, 1fr) auto;
    column-gap: 32px;
  }
  .product__name { grid-area: name; }
  .product__tagline { grid-area: tag; }
  .product__domain { grid-area: domain; align-self: end; margin-bottom: 11px; } /* centred on the 40px badges */
  .stores { grid-area: stores; flex-wrap: nowrap; margin-top: 12px; }
  .store { display: grid; justify-items: center; gap: 12px; }
  .store__qr { display: block; }
}

@media (hover: hover) and (pointer: fine) {
  .product:hover .product__layer--flood { --r: 150%; transition-duration: 650ms; }
  .product:hover .product__name { transform: translateY(-6px); }
  .product:hover .arrow { transform: translate(4px, -4px); }
}

@media (hover: none) {
  .product__layer--flood { clip-path: none; }
}

/* ---------- Reduced motion ---------- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .l, .hero__head, .tagline, .hero__foot { animation: none; }
  .product__layer--flood { transition: none; }
  .product:hover :is(.product__name, .arrow) { transform: none; }
}
