/* landing-static · one product, one page.
   Colors: layer 1 palette (--palette-*) and layer 2 semantic (--color-*) live only in :root;
   component rules below use var(--color-*) only. --accent is the product's own #rrggbb.
   Contrast: no readable text sits on the accent. The accent is only a fill (hero block, arrow cell, button body);
   every word is ink on the page color or on-plate on a plate, and every accent edge carries an ink border plus
   a page-color ring, so any accent (black, white, yellow...) stays readable. 404.html repeats these tokens. */
:root {
  --accent: #0D3B44;
  --palette-paper: #ffffff;
  --palette-concrete: #e3e6ea;
  --palette-carbon: #000000;
  --palette-graphite: #15171b;
  --palette-chalk: #f2f3f5;
  --palette-ash: #6b7480;
  --palette-grain-shade: rgb(0 0 0 / 0.16);
  --palette-grain-light: rgb(255 255 255 / 0.12);

  --color-bg: var(--palette-concrete);
  --color-ink: var(--palette-carbon);
  --color-plate: var(--palette-carbon);
  --color-on-plate: var(--palette-paper);
  --color-edge: var(--palette-carbon);
  --color-shadow: var(--palette-carbon);
  --color-grain-shade: var(--palette-grain-shade);
  --color-grain-light: var(--palette-grain-light);
  --color-accent: var(--accent);

  --shadow-step: clamp(0.625rem, 1.4vw, 1.25rem);
  --border: 0.25rem;
  --gutter: clamp(1.25rem, 4vw, 3.5rem);
  color-scheme: light dark;
}
@media (prefers-color-scheme: dark) {
  :root {
    --color-bg: var(--palette-graphite);
    --color-ink: var(--palette-chalk);
    --color-plate: var(--palette-chalk);
    --color-on-plate: var(--palette-carbon);
    --color-edge: var(--palette-chalk);
    --color-shadow: var(--palette-ash);
  }
}

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

html { background: var(--color-bg); }
body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--color-bg);
  color: var(--color-ink);
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  line-height: 1.5;
  -webkit-text-size-adjust: 100%;
}

/* ---- stage: wordmark across the top; left column = description over the numbered features; right column = the accent block ---- */
.stage {
  --wordmark: clamp(4rem, 14vw, 14rem); /* the wordmark's font size: one variable, read by the h1 and by the block's top padding */
  flex: 1;
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  grid-template-rows: auto 1fr;
  column-gap: var(--gutter);
  padding: var(--gutter) var(--gutter) 0;
  overflow-x: clip; /* the wordmark's negative side bearing never adds a horizontal scrollbar */
}

/* the wordmark spans both columns, so a short name crosses over the accent block and a long one wraps above it */
.stage > h1 {
  grid-column: 1 / -1;
  grid-row: 1;
  position: relative;
  z-index: 2;
  margin: 0 8% 0 -0.05em; /* -0.05em pulls the first letter's side bearing onto the page edge */
  font-size: var(--wordmark);
  font-weight: 900;
  line-height: 0.86;
  letter-spacing: -0.055em;
  overflow-wrap: break-word;
  hyphens: auto;
  /* a hard halo in the page color keeps the letters readable where they cross the accent */
  text-shadow:
    0.03em 0 0 var(--color-bg), -0.03em 0 0 var(--color-bg),
    0 0.03em 0 var(--color-bg), 0 -0.03em 0 var(--color-bg),
    0.022em 0.022em 0 var(--color-bg), -0.022em 0.022em 0 var(--color-bg),
    0.022em -0.022em 0 var(--color-bg), -0.022em -0.022em 0 var(--color-bg);
}

/* name length buckets (set by the renderer on <main> and the h1): a long name is scaled to fit instead of being cut mid-word */
.stage.name-m { --wordmark: clamp(2.5rem, 10.5vw, 11rem); }
.stage.name-l { --wordmark: clamp(2rem, 7vw, 8rem); }
.stage > h1.name-m, .stage > h1.name-l { font-size: var(--wordmark); }

/* the left column: the description sits right under the wordmark, the features close the column level with the block's foot,
   so no void opens between them; a page without features centres the description in the column instead */
.copy {
  grid-column: 1;
  grid-row: 2;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: clamp(1.5rem, 3vw, 2.5rem);
  /* the top margin clears the descenders of the wordmark (y, g, p) that hang below its line box */
  margin: clamp(2.5rem, 5.5vw, 6rem) 0 calc(var(--gutter) + var(--shadow-step));
}

.description {
  max-width: 34ch;
  margin: 0;
  font-size: clamp(1.125rem, 1.6vw, 1.5rem);
  font-weight: 500;
  line-height: 1.45;
  overflow-wrap: break-word;
}

/* CJK has no spaces: break at punctuation, not inside words (overflow-wrap above still guards a long unbroken run) */
:lang(zh), :lang(ja), :lang(ko) { word-break: keep-all; }

/* ---- features: ruled, numbered, ink on the page color; the number sits on a plate ---- */
.features {
  counter-reset: feature;
  max-width: 34rem;
  margin: 0;
  padding: 0;
  list-style: none;
  border-top: var(--border) solid var(--color-edge);
}
.features li {
  counter-increment: feature;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: 1rem;
  align-items: start;
  padding: 0.9rem 0;
  border-bottom: 0.125rem solid var(--color-edge);
}
.features li::before {
  content: counter(feature, decimal-leading-zero);
  grid-row: 1 / span 2;
  min-width: 2.75rem;
  padding: 0.2rem 0.4rem;
  background: var(--color-plate);
  color: var(--color-on-plate);
  font-size: 1.125rem;
  font-weight: 900;
  line-height: 1.3;
  text-align: center;
  letter-spacing: -0.02em;
}
/* title and text are two blocks, title first: on their own lines at every width (the source also has a space between them, so
   copied or read-aloud text is "title text", not "titletext") */
.features b { display: block; grid-column: 2; font-size: clamp(1.0625rem, 1.5vw, 1.375rem); font-weight: 900; line-height: 1.25; overflow-wrap: break-word; }
.features span { display: block; grid-column: 2; margin-top: 0.15rem; font-size: clamp(1rem, 1.2vw, 1.125rem); font-weight: 500; line-height: 1.4; overflow-wrap: break-word; }

/* ---- the accent block: flat product color, CSS grain, hard offset shadow; it holds the product's screenshot (or a big glyph),
   the tagline plate overlapping it, and the buttons ---- */
.hero {
  grid-column: 2;
  grid-row: 1 / span 2;
  position: relative;
  min-height: min(82vh, 50rem);
  margin: 0 var(--shadow-step) calc(var(--gutter) + var(--shadow-step)) 0;
  padding: clamp(1.5rem, 3vw, 2.75rem);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: flex-start;
  gap: 1.5rem;
  background-color: var(--color-accent);
  background-image:
    radial-gradient(var(--color-grain-shade) 0.6px, transparent 1.2px),
    radial-gradient(var(--color-grain-light) 0.6px, transparent 1.2px),
    repeating-linear-gradient(115deg, var(--color-grain-shade) 0 1px, transparent 1px 7px);
  background-size: 5px 5px, 7px 7px, auto;
  background-position: 0 0, 2px 3px, 0 0;
  border: var(--border) solid var(--color-edge);
  box-shadow: var(--shadow-step) var(--shadow-step) 0 var(--color-shadow);
  animation: slam 520ms cubic-bezier(0.2, 0.9, 0.25, 1.2) both;
}

/* a name wide enough to cross into the block (the renderer sets .crosses) hangs its descenders (y, g, p) 1.0 wordmark below the
   block's top edge: the block's content starts 1.15 wordmarks down, so the wordmark overlaps only the coloured area, never the screenshot */
.stage.crosses .hero { padding-top: calc(var(--wordmark) * 1.15); }

/* the screenshot or icon: framed like a device, tilted a little, with its own hard shadow; the product owns the file.
   Shrink-to-fit, never wider than the block, centred on both axes in the room above the tagline and buttons. */
.shot {
  align-self: center;
  width: fit-content;
  max-width: 100%;
  min-width: 0;
  margin: auto;
  background: var(--color-bg);
  border: var(--border) solid var(--color-edge);
  box-shadow: 0.75rem 0.75rem 0 var(--color-shadow);
  transform: rotate(1.5deg);
}
/* heroWidth/heroHeight only give the aspect ratio (no layout shift); the displayed size comes from the block, never from them */
.shot img {
  display: block;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: clamp(15rem, 44vh, 28rem);
  object-fit: contain;
}

/* no image: the first letter of the name, outlined, large enough to be a graphic */
.mark {
  align-self: center;
  margin: auto 0; /* centred in the room above the tagline and buttons, like the screenshot */
  color: transparent;
  -webkit-text-stroke: 0.045em var(--color-edge);
  font-size: clamp(10rem, 24vw, 24rem);
  font-weight: 900;
  line-height: 0.9;
  letter-spacing: -0.04em;
  user-select: none;
}

/* tagline: a plate that steps out of the block's left edge, tilted, and climbs over the screenshot's foot */
.tagline {
  position: relative;
  z-index: 3;
  margin: -2.75rem 0 0 calc(-1 * clamp(2.25rem, 5vw, 4.5rem));
  max-width: calc(100% + clamp(2.25rem, 5vw, 4.5rem));
  transform: rotate(-3deg);
  transform-origin: left bottom;
}
.tagline span {
  display: inline;
  padding: 0.12em 0.4em;
  background: var(--color-plate);
  color: var(--color-on-plate);
  font-size: clamp(1.375rem, 2.6vw, 2.25rem);
  font-weight: 800;
  line-height: 1.5;
  letter-spacing: -0.01em;
  overflow-wrap: break-word;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}

/* the app button (when the product has a web app) and the Play button stack, the app one first */
.actions { display: flex; flex-flow: row wrap; align-items: flex-start; gap: 1.25rem 1.5rem; max-width: 100%; }

/* ---- soon label: an inert stamp for a product that is not live yet; deliberately not button-shaped
   (dashed edge, no arrow cell, no shadow, no hover) so nobody reads it as something to press ---- */
.soon { margin: 0; max-width: 100%; }
.soon span {
  display: inline-block;
  max-width: 100%;
  padding: 0.75rem 1.4rem;
  border: var(--border) dashed var(--color-edge);
  background: var(--color-bg); /* page color on the accent block: the dashed ink edge stays visible, unlike a black plate on black */
  color: var(--color-ink);
  font-size: clamp(1.375rem, 3vw, 2rem);
  font-weight: 900;
  letter-spacing: 0.08em;
  line-height: 1.3;
  text-transform: uppercase;
  overflow-wrap: break-word;
  transform: rotate(-2deg);
}

/* ---- Play button: plate label cell + accent arrow cell, ink border, page-color ring, hard shadow ---- */
.play {
  display: inline-flex;
  align-items: stretch;
  min-height: 4rem;
  max-width: 100%;
  border: var(--border) solid var(--color-edge);
  outline: 0.1875rem solid var(--color-bg); /* the ring keeps the button's edge visible on an accent equal to the ink */
  background: var(--color-accent);
  color: var(--color-on-plate);
  text-decoration: none;
  box-shadow: 0.5rem 0.5rem 0 var(--color-shadow);
  transition: transform 90ms ease-out, box-shadow 90ms ease-out;
}
.play__label {
  display: flex;
  align-items: center;
  padding: 0.75rem 1.25rem;
  background: var(--color-plate);
  color: var(--color-on-plate);
  font-size: clamp(1.0625rem, 1.4vw, 1.25rem);
  font-weight: 800;
  line-height: 1.2;
}
.play__arrow {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 4rem;
  padding: 0 0.625rem;
  border-left: var(--border) solid var(--color-edge);
  background: var(--color-accent);
}
/* the glyph sits on its own plate, so it reads on any accent */
.play__arrow span {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  background: var(--color-plate);
  color: var(--color-on-plate);
  font-size: 1.5rem;
  font-weight: 900;
  line-height: 1;
}
.play:hover { transform: translate(0.25rem, 0.25rem); box-shadow: 0.25rem 0.25rem 0 var(--color-shadow); }
.play:active { transform: translate(0.5rem, 0.5rem); box-shadow: 0 0 0 var(--color-shadow); }
/* two rings (page color, then ink): one of them clears 3:1 against any accent; the transparent outline shows in forced colors */
.play:focus-visible {
  outline: 0.25rem solid transparent;
  outline-offset: 0.25rem;
  box-shadow: 0 0 0 0.25rem var(--color-bg), 0 0 0 0.5rem var(--color-ink);
}
/* the label inverts on focus, so focus reads even where the ink ring meets an ink-colored accent */
.play:focus-visible .play__label { background: var(--color-bg); color: var(--color-ink); }

/* ---- footer: privacy, optional contact, and the runupbiz attribution pushed to the far end ---- */
footer {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem 1.5rem;
  padding: 1rem var(--gutter) 1.5rem;
  font-size: 0.875rem;
}
footer a { color: var(--color-ink); text-decoration: underline; text-underline-offset: 0.2em; text-decoration-thickness: 1px; }
footer a:hover { text-decoration-thickness: 2px; }
footer a:focus-visible { outline: 0.1875rem solid var(--color-ink); outline-offset: 0.25rem; }
footer .brand { margin-left: auto; font-weight: 800; letter-spacing: 0.02em; text-decoration: none; }
footer .brand:hover { text-decoration: underline; }

@keyframes slam {
  from { transform: translate(var(--shadow-step), var(--shadow-step)); box-shadow: 0 0 0 var(--color-shadow); }
  to { transform: none; box-shadow: var(--shadow-step) var(--shadow-step) 0 var(--color-shadow); }
}

/* a page without features: the description floats in the middle of its column instead of hugging the wordmark */
@media (min-width: 641px) {
  .copy > .description:only-child { margin-block: auto; }
}

/* ---- mobile: one column in reading order (wordmark, description, the block with the screenshot and button, features, footer) ---- */
@media (max-width: 640px) {
  .stage {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: none;
    align-content: start;
    padding-top: 1.5rem;
  }
  .stage { --wordmark: clamp(3rem, 18vw, 10rem); }
  .stage.name-m { --wordmark: clamp(2.25rem, 10.5vw, 10rem); }
  .stage.name-l { --wordmark: clamp(1.75rem, 7vw, 8rem); }
  .stage > h1 { grid-column: 1; grid-row: 1; margin: 0 0 0 -0.04em; }
  .stage > h1.name-m, .stage > h1.name-l { font-size: var(--wordmark); }
  .copy { display: contents; } /* description and features become rows of the stage grid, with the block between them */
  .description { grid-column: 1; grid-row: 2; margin: 1.25rem 0 2rem; }
  .hero,
  .stage.crosses .hero { /* stacked under the description: the wordmark crosses nothing */
    grid-column: 1;
    grid-row: 3;
    min-height: 0;
    margin-bottom: calc(var(--shadow-step) + 0.5rem);
    padding: 1.75rem 1.25rem 1.25rem;
    align-items: stretch;
    gap: 1.5rem;
  }
  .shot img { max-height: clamp(14rem, 55vh, 30rem); }
  .mark { font-size: clamp(7rem, 40vw, 11rem); }
  .tagline { margin-left: -0.5rem; max-width: 100%; transform: rotate(-2deg); }
  .actions { flex-direction: column; align-items: stretch; }
  .play { display: flex; width: 100%; min-height: 3.5rem; }
  .play__label { flex: 1; }
  .features { grid-column: 1; grid-row: 4; max-width: none; margin: 1.5rem 0 2rem; }
}

/* ---- forced colors (Windows high contrast): no tilt or overlap, every box keeps a system-color border ---- */
@media (forced-colors: active) {
  .stage > h1 { margin-right: 0; }
  .hero { border-color: CanvasText; }
  .tagline { margin: 0; max-width: 100%; transform: none; }
  .tagline span { border: 0.125rem solid CanvasText; }
  .shot { border-color: CanvasText; transform: none; }
  .mark { -webkit-text-stroke-color: CanvasText; }
  .features, .features li { border-color: CanvasText; }
  .features li::before { border: 0.125rem solid CanvasText; }
  .play, .play__arrow { border-color: ButtonText; }
  .soon span { border-color: CanvasText; transform: none; }
  .play__arrow span { border: 0.125rem solid ButtonText; }
}
@media (forced-colors: active) and (min-width: 641px) {
  /* below the wordmark, clear of its text backplate: no text over a box whose fill is gone */
  .stage > h1 { margin-bottom: 0.25em; }
  .hero, .stage.crosses .hero { grid-row: 2; padding-top: clamp(1.5rem, 3vw, 2.75rem); }
}

@media (prefers-reduced-motion: reduce) {
  .hero { animation: none; }
  .play { transition: none; }
}
