/* tonemate.co
 *
 * Ported from the homepage design canvas, which in turn takes its values from
 * the app's own token layer (`constants/theme.ts`) and the rules recorded in
 * `_workflow/05-design-system.md`. Change a value here only after changing it
 * there — the app and the site are meant to look like one product.
 *
 * Single theme, deliberately. `Colors.dark` is an alias of `Colors.light` in
 * the app because the two load-bearing contrast rules below were measured
 * against the blush ground; a dark palette is not a token edit, it is that
 * measurement done again.
 */

:root {
  color-scheme: light;

  --bg: #f9edf1;          /* blush ground */
  --bg-sunk: #f2e0e7;     /* pressed / recessed */
  --surface: #ffffff;     /* tiles */
  --well: #2e1b33;        /* the dark inset */
  --on-well: #efe2f2;
  --ink: #35213a;
  --ink-soft: #7e6274;
  --line: #ebd4dd;
  --ring: #8d7d8c;        /* swatch boundary — never lighten this */
  --accent: #b3306e;      /* primary action, and nothing else */
  --accent-deep: #8c2757;
  --on-accent: #ffffff;

  --r-sm: 10px;
  --r-md: 16px;
  --r-lg: 24px;
  --r-pill: 999px;

  --gutter: clamp(20px, 6vw, 160px);
  --measure: 1120px;

  --sans: Inter, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --display: "Space Grotesk", system-ui, -apple-system, sans-serif;
  /* The store badges are Apple's and Google's artwork; their type is not ours. */
  --badge: -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

/* --- faces -------------------------------------------------------------- *
 * Self-hosted and subset (1089 KB of TTF -> 87 KB of woff2). Google's font
 * CDN is deliberately not used: it discloses the visitor's IP to a third
 * party, which is a strange thing to do on the page hosting our privacy
 * policy.                                                                   */

@font-face { font-family: Inter; src: url("/fonts/Inter-Regular.woff2") format("woff2"); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: Inter; src: url("/fonts/Inter-Medium.woff2") format("woff2"); font-weight: 500; font-style: normal; font-display: swap; }
@font-face { font-family: Inter; src: url("/fonts/Inter-SemiBold.woff2") format("woff2"); font-weight: 600; font-style: normal; font-display: swap; }
@font-face { font-family: "Space Grotesk"; src: url("/fonts/SpaceGrotesk-Medium.woff2") format("woff2"); font-weight: 500; font-style: normal; font-display: swap; }
@font-face { font-family: "Space Grotesk"; src: url("/fonts/SpaceGrotesk-Bold.woff2") format("woff2"); font-weight: 700; font-style: normal; font-display: swap; }

/* --- base --------------------------------------------------------------- */

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

h1, h2, h3 { font-family: var(--display); font-weight: 700; line-height: 1.1; margin: 0; }
p { margin: 0; }
img, svg { max-width: 100%; }

a { color: var(--accent); text-decoration: none; }
a:hover { color: var(--accent-deep); text-decoration: underline; }
a:focus-visible,
.badge:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 4px; }

.eyebrow {
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 1.35px;
  text-transform: uppercase;
  color: var(--ink-soft);
}

/* --- header / footer ---------------------------------------------------- */

.site-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 28px var(--gutter);
  max-width: calc(var(--measure) + var(--gutter) * 2);
  margin: 0 auto;
}

.wordmark {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(18px, 0.29vw + 16.9px, 21px);
  letter-spacing: -0.5px;
  color: var(--ink);
}
.wordmark:hover { color: var(--ink); text-decoration: none; }

.site-header nav { display: flex; gap: clamp(16px, 2.2vw, 32px); }
.site-header nav a {
  font-size: 14px;
  font-weight: 500;
  color: var(--ink-soft);
}
.site-header nav a:hover { color: var(--ink); text-decoration: none; }
.site-header nav a[aria-current="page"] { color: var(--ink); }

.site-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 16px 26px;
  padding: 32px var(--gutter) 44px;
  max-width: calc(var(--measure) + var(--gutter) * 2);
  margin: 0 auto;
  border-top: 1px solid var(--line);
  font-size: 13px;
  color: var(--ink-soft);
}
.site-footer nav { display: flex; flex-wrap: wrap; gap: 12px 26px; }
.site-footer a { color: var(--ink-soft); }
.site-footer a:hover { color: var(--ink); }

/* The contact address is printed, never linked (see build.mjs). It sits in the
   footer's link row, so it has to match that row rather than inherit nothing. */
.site-footer .email { color: var(--ink-soft); }

@media (max-width: 640px) {
  .site-header nav a.wide-only { display: none; }
  .site-footer { flex-direction: column; align-items: flex-start; }
  .site-footer nav { flex-direction: column; gap: 10px; }
  .site-footer .copyright { order: 2; }
}

/* --- store badges ------------------------------------------------------- *
 * PLACEHOLDER ARTWORK. Apple and Google each publish the badge as a fixed
 * asset and both forbid redrawing it, so these are replaced by the official
 * files before the app goes on sale:
 *   developer.apple.com/app-store/marketing/guidelines
 *   partnermarketinghub.withgoogle.com
 * Both guidelines also expect a badge to link to a live listing. Ours link
 * nowhere yet — decided 2026-09-10 to show them plain rather than label them.  */

.badges { display: flex; flex-wrap: wrap; gap: 12px; }
.badges.centered { justify-content: center; }

.badge {
  display: flex;
  align-items: center;
  gap: 10px;
  height: clamp(48px, 4vw, 54px);
  padding: 0 clamp(14px, 1.4vw, 18px);
  border-radius: var(--r-sm);
  background: #000000;
  color: #ffffff;
  font-family: var(--badge);
}
.badge svg { width: clamp(22px, 2vw, 26px); height: clamp(22px, 2vw, 26px); flex-shrink: 0; }
.badge .lines { display: flex; flex-direction: column; }
.badge .small { font-size: clamp(10px, 0.85vw, 11px); font-weight: 400; letter-spacing: 0.2px; line-height: 1.25; }
.badge .large { font-size: clamp(18px, 0.29vw + 16.9px, 21px); font-weight: 500; letter-spacing: -0.3px; line-height: 1.15; }
.badge.play .small { letter-spacing: 1.1px; text-transform: uppercase; }

/* --- phone frames ------------------------------------------------------- *
 * `--phone-w` drives everything inside, so one width sets the whole
 * schematic. The 9/19.5 ratio is the iPhone screenshot ratio: a real capture
 * drops in without reflowing anything around it.                            */

.phone {
  width: var(--phone-w);
  aspect-ratio: 9 / 19.5;
  border-radius: calc(var(--phone-w) * 0.128);
  border: 1px solid var(--line);
  padding: calc(var(--phone-w) * 0.06);
  display: flex;
  flex-direction: column;
  gap: calc(var(--phone-w) * 0.05);
  background: var(--surface);
  overflow: hidden;
}
/* A frame holding a real capture rather than a schematic: no padding, and the
   ratio taken from the capture itself.

   The status bar and the home indicator are painted out in the image rather
   than cropped off. A phone draws its own on top of the app, so ours would read
   as doubled up — but cropping them took the ratio from 0.462 to 0.511 and the
   frame stopped looking like a phone at all. Filling them with the app's ground
   removes the chrome and keeps the shape. */
.phone.capture { padding: 0; aspect-ratio: var(--shot-ratio, 1170 / 2532); }

/* One ratio per capture, measured from the source image. These live here and
   not in a style attribute because `style-src 'self'` carries no
   'unsafe-inline', so the browser would drop the attribute and every phone
   would fall back to the default ratio. Replacing a capture is still one file
   and one number. */
.phone.shot-selfie { --shot-ratio: 704 / 1524; }
.phone.shot-wardrobe { --shot-ratio: 853 / 1844; }
.phone.shot-outfit { --shot-ratio: 704 / 1524; }
.phone > img { width: 100%; height: 100%; object-fit: cover; border-radius: inherit; display: block; }

/* The hero phone is the largest of the four on the page and carries the
   heaviest shadow. In this system hierarchy comes from elevation. */
.phone.hero-phone {
  --phone-w: clamp(250px, 4.76vw + 231px, 300px);
  box-shadow: 0 24px 48px rgba(53, 33, 58, 0.16), 0 4px 10px rgba(53, 33, 58, 0.06);
}
.phone.step-phone {
  --phone-w: clamp(175px, 2.86vw + 164px, 205px);
  box-shadow: 0 10px 22px rgba(53, 33, 58, 0.11), 0 2px 5px rgba(53, 33, 58, 0.05);
}
.phone.dark { background: var(--well); align-items: center; justify-content: center; gap: calc(var(--phone-w) * 0.09); }


/* --- home: hero --------------------------------------------------------- */

.section { padding: clamp(56px, 6vw, 96px) var(--gutter); }
.section > .inner { max-width: var(--measure); margin: 0 auto; }

.hero { padding-top: clamp(16px, 2.2vw, 36px); }
.hero .inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(32px, 4vw, 64px);
  align-items: center;
}
.hero .copy { display: flex; flex-direction: column; gap: clamp(20px, 2vw, 28px); }
.hero .heads { display: flex; flex-direction: column; gap: clamp(12px, 1.2vw, 16px); }

.hero h1 {
  font-size: clamp(34px, 1.9vw + 26.6px, 54px);
  line-height: 1.04;
  letter-spacing: -0.037em;
  text-wrap: balance;
}
/* The kicker is a second heading voice, not a subtitle: Space Grotesk 500,
   which the design system declares as `headingMedium`. It stays ink rather
   than accent — accent means "primary action" everywhere in this system, and
   a promise painted in it reads as a button. */
.hero .kicker {
  font-family: var(--display);
  font-weight: 500;
  font-size: clamp(20px, 0.76vw + 17px, 28px);
  line-height: 1.17;
  letter-spacing: -0.03em;
  text-wrap: balance;
}
.lede {
  font-size: clamp(16px, 0.29vw + 14.9px, 19px);
  line-height: 1.6;
  color: var(--ink-soft);
  max-width: 52ch;
  text-wrap: pretty;
}
.hero .shot { display: flex; justify-content: center; }
/* Two captures share the column, so their width comes from the space rather
   than from a clamp — the aspect-ratio turns that into their height. */
.hero .shot.pair { gap: clamp(8px, 1.3vw, 18px); align-items: flex-start; }
.hero .shot.pair .phone { flex: 1 1 0; min-width: 0; width: auto; max-width: 300px; }

/* --- home: steps -------------------------------------------------------- */

.steps { background: var(--surface); padding-top: clamp(44px, 4.6vw, 68px); }
.steps .inner { display: flex; flex-direction: column; gap: clamp(26px, 2.4vw, 34px); }
.steps h2 { font-size: clamp(30px, 0.95vw + 26.3px, 40px); letter-spacing: -0.035em; text-wrap: balance; }
.steps ol {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(32px, 3vw, 36px);
}
.steps li { display: flex; flex-direction: column; gap: clamp(10px, 1vw, 14px); }
/* Number and title share a row. Stacked they cost 42px of height that the
   phone below needs to stay whole on one screen. */
.steps .head { display: flex; align-items: center; gap: 12px; }
.steps .num {
  width: 40px;
  height: 40px;
  border-radius: var(--r-pill);
  background: var(--accent);
  color: var(--on-accent);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--display);
  font-weight: 700;
  font-size: 17px;
  flex-shrink: 0;
}
.steps h3 { font-size: clamp(20px, 0.19vw + 19.3px, 22px); letter-spacing: -0.027em; }
.steps p { font-size: 15px; line-height: 1.65; color: var(--ink-soft); text-wrap: pretty; }
/* Step paragraphs run to different line counts, so the phones would start at
   different heights. Pushing the shot down aligns all three on their base. */
.steps .shot { display: flex; justify-content: center; margin-top: auto; padding-top: 4px; }

/* --- home: outfit band -------------------------------------------------- */

.outfits { background: var(--well); color: var(--on-well); }
.outfits .inner {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(36px, 5vw, 72px);
  align-items: center;
}
.outfits .copy { display: flex; flex-direction: column; gap: clamp(18px, 2vw, 22px); }
.outfits h2 { font-size: clamp(30px, 0.95vw + 26.3px, 40px); letter-spacing: -0.035em; color: var(--on-well); text-wrap: balance; }
.outfits p { font-size: clamp(16px, 0.1vw + 15.6px, 17px); line-height: 1.7; color: #c4afc9; max-width: 48ch; text-wrap: pretty; }
.outfits .occasions { display: flex; flex-wrap: wrap; gap: 10px; }
.outfits .chip {
  padding: 8px 16px;
  border-radius: var(--r-pill);
  border: 1px solid #6b5470;
  font-size: 12px;
  font-weight: 500;
}
.outfits .chip.on { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.outfits .flatlay { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(14px, 1.6vw, 20px); }
.outfits .tile {
  position: relative;
  aspect-ratio: 1 / 0.95;
  border-radius: var(--r-lg);
  background: #fff;
  overflow: hidden;
}

/* The card carries its own white ground, so it fills the tile edge to edge:
   each file is built at this tile's ratio, which is why nothing is cropped and
   no padding is needed. Design-system rule 2 (a cutout carries its own shadow)
   does not apply here -- the white card is what separates the piece from the
   plum band, exactly as it does in the app's wardrobe grid. */
.outfits .tile img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  animation: outfit-swap 9s calc(var(--i, 0) * 3s + var(--stagger, 0s) - 0.45s) infinite;
}

/* A cascade, not a stagger: the four tiles change within a third of a second
   of each other so the grid does not snap all at once, but they stay on the
   same variant -- and the variant IS the outfit. A wider offset would pair
   variant 2 of one slot with variant 1 of another, which is where the clashing
   combinations came from.

   Negative, not positive: a positive delay leaves the first variant on its
   static opacity: 0 until the animation starts, i.e. an empty tile on load. */
.outfits .tile:nth-child(2) { --stagger: -0.1s; }
.outfits .tile:nth-child(3) { --stagger: -0.2s; }
.outfits .tile:nth-child(4) { --stagger: -0.3s; }

/* Fade order within a tile. Same reason as the capture ratios above: a style
   attribute would be dropped by the policy. */
.outfits .tile img:nth-child(2) { --i: 1; }
.outfits .tile img:nth-child(3) { --i: 2; }

@keyframes outfit-swap {
  0% { opacity: 0; }
  5%, 30% { opacity: 1; }
  35%, 100% { opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .outfits .tile img { animation: none; opacity: 0; }
  .outfits .tile img:first-child { opacity: 1; }
}

/* --- home: closing ------------------------------------------------------ */

.closing .inner { display: flex; flex-direction: column; align-items: center; gap: clamp(20px, 2vw, 26px); }
.closing h2 { font-size: clamp(24px, 0.57vw + 21.8px, 30px); line-height: 1.16; letter-spacing: -0.03em; text-align: center; text-wrap: balance; }

/* --- narrow layouts ----------------------------------------------------- */

@media (max-width: 900px) {
  .hero .inner,
  .outfits .inner { grid-template-columns: 1fr; }
  .hero .shot { margin-top: 18px; }
  .steps ol { grid-template-columns: 1fr; gap: 34px; }
}

/* --- the generated documents -------------------------------------------- */

.doc main { max-width: 46rem; margin: 0 auto; padding: 16px var(--gutter) 64px; }
.doc h1 { font-size: clamp(32px, 1.14vw + 27.5px, 44px); letter-spacing: -0.035em; margin-bottom: 8px; text-wrap: balance; }
.doc h2 { font-size: clamp(21px, 0.38vw + 19.5px, 25px); letter-spacing: -0.03em; margin: 44px 0 12px; text-wrap: balance; }
.doc h3 { font-size: clamp(17px, 0.1vw + 16.6px, 18px); letter-spacing: -0.02em; margin: 28px 0 10px; }
.doc p, .doc li { color: var(--ink); line-height: 1.7; }
.doc p { margin: 12px 0; }
.doc ul, .doc ol { padding-left: 22px; }
.doc li { margin: 6px 0; }
.doc hr { border: 0; height: 1px; background: var(--line); margin: 36px 0; }
.doc .updated { color: var(--ink-soft); font-size: 14px; margin: 0 0 8px; }
.doc code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.9em; background: var(--bg-sunk); padding: 1px 5px; border-radius: 5px; }
.doc blockquote { margin: 16px 0; padding: 2px 0 2px 16px; border-left: 3px solid var(--line); color: var(--ink-soft); }

/* The privacy policy's CCPA table is six columns wide. It scrolls inside
   itself rather than widening the page on a phone. */
.table-scroll { overflow-x: auto; margin: 20px 0; border-radius: var(--r-md); border: 1px solid var(--line); }
.doc table { border-collapse: collapse; width: 100%; font-size: 14px; background: var(--surface); }
.doc th, .doc td { border-bottom: 1px solid var(--line); padding: 10px 14px; text-align: left; vertical-align: top; }
.doc thead th { background: var(--bg-sunk); font-weight: 600; white-space: nowrap; }
.doc tbody tr:last-child td { border-bottom: 0; }
