/*
 * Two faces and three inks per scheme, taken from the app's measured screen style guide.
 *
 * **This file is checked against that guide, not merely descended from it.** It is still a
 * copy -- a Pages project serving static files cannot import a Kotlin colour scheme -- but
 * `docs/design/build_screen_specimen.py` parses the custom properties below, asserts each
 * one against the constant the app uses, and carries every pair as a row in the contrast
 * table it computes. So the copy cannot go stale in silence, which is the thing a copy
 * usually does: the app's own splash HTML (`app/webApp/src/webMain/resources/index.html`)
 * carries its own small palette and still runs a ground value a later measurement
 * corrected, and nobody noticed because nothing could.
 *
 * That guard is why the landing page lives in this repo at all. If you change a value here,
 * change the app's and the generator's with it, or the specimen build fails.
 *
 * Every ratio quoted below is computed by that generator, not measured by hand.
 */

/* Arvo 400 and Poppins 400, subset to Latin. **Build products**, emitted by
 * `tools/fonts/build_fonts.py` alongside the ttf the app uses -- same source, same subset
 * range, different container -- so this page inherits that script's `--verify-served`
 * provenance check rather than carrying hand-converted binaries nothing regenerates.
 * `check.py` asserts every character this page uses survives in both subsets, because
 * pyftsubset drops a glyph the source lacks without saying so (Arvo has no arrow, and the
 * app hit exactly that). OFL text ships beside the files, as the licence requires. */
@font-face {
  font-family: "Arvo";
  src: url("fonts/arvo_regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Poppins";
  src: url("fonts/poppins_regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

:root {
  color-scheme: light dark;
  /* Light ground and dark ink: 15.43:1. */
  --ground: #F6F6F6;
  --ink: #1E1E1E;
  /* The annotation ink, which is the app's link colour on the About page. 6.87:1 -- below
   * the app's 7:1 small-text bar by the same deliberate margin recorded there, and clear of
   * AA at 4.5. Held to the scheme rule that makes it coherent rather than arbitrary: the
   * annotation ink is always the family the ground is not. */
  --accent: #1A5793;
  /* Structure, never meaning. The frame ink on all 121 pages of the rulebook. Non-text, so
   * the 3:1 bar applies: 4.82:1. */
  --rule: #8A6636;
}

@media (prefers-color-scheme: dark) {
  :root {
    /* Warm, with a yellow bias -- the measured ground, not a neutral charcoal. Bone ink on
     * it is 12.61:1. */
    --ground: #1E1E12;
    --ink: #EADEC6;
    /* Amber, because the ground is now the other family. 9.94:1. */
    --accent: #FFBA5A;
    --rule: #A28A5A;
  }
}

body {
  margin: 0;
  /* The top pad scales with the viewport rather than being a constant. At a constant 2rem a
   * five-paragraph page sits in the top fifth of a desktop window and reads as a page that
   * failed to finish loading; centring it vertically instead would risk clipping the top on
   * a short window, which is the failure the app's own about-bar hit on a phone. Scaling the
   * pad gets the desktop result without the overflow case existing at all. */
  padding: clamp(2rem, 12vh, 7rem) 1.25rem 4rem;
  background: var(--ground);
  color: var(--ink);
  /* Poppins is the body role. The fallback is a system stack rather than a named family,
   * so a blocked or failed font request degrades to something legible rather than to a
   * default serif. */
  font-family: "Poppins", system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: 1.0625rem;
  line-height: 1.6;
}

main {
  /* 616px is the app's prose measure -- 70 characters of the body face -- and the app scopes
   * it to paragraphs for the same reason it matters more here than anywhere: this page is
   * nothing but paragraphs, so an uncapped line on a wide window is the whole page. */
  max-width: 616px;
  margin: 0 auto;
}

h1 {
  /* Arvo is the name role. It has no 500 or 600 -- four static styles, Regular and Bold --
   * so asking for anything between gets a synthesised weight. 400, and the lever if it
   * looms is the size, not the weight: its cap height is 106% of Poppins'. */
  font-family: "Arvo", Georgia, serif;
  font-weight: 400;
  font-size: 2rem;
  line-height: 1.2;
  margin: 0 0 1.5rem;
  padding-bottom: 1rem;
  border-bottom: 1px solid var(--rule);
}

p {
  margin: 0 0 1.25rem;
}

.lede {
  font-size: 1.1875rem;
}

.action {
  margin-top: 2rem;
  font-size: 1.1875rem;
}

.note {
  /* The one paragraph that knows about the gate. Quieter than the action above it without
   * dropping below the body size, because an instruction a visitor needs in order to get in
   * is not fine print. Opacity rather than a fourth ink: it composites against whichever
   * ground is live, so it cannot be the one value that fails on a scheme nobody checked.
   *
   * It is still a pair nothing else draws, so it is two rows in the specimen's contrast
   * table: the blend is #C1B8A2 at 8.52:1 on dark and #494949 at 8.33:1 on light, both
   * clear of the 7:1 bar. An earlier version of this comment said "0.8 of 12.61:1 and
   * 15.43:1", which is not how opacity works -- the generator recomputes the blend from
   * the alpha below, so changing it fails the build rather than the comment. */
  opacity: 0.8;
}

a {
  color: var(--accent);
  /* Underlined, always. The app's guide is explicit that hover may never be the sole carrier
   * of information, and a link that announces itself only on hover is that rule broken on
   * the one page whose entire job is to be clicked through. */
  text-decoration: underline;
  text-underline-offset: 0.15em;
}

/* The one thing this page exists to get clicked, so it should not be typographically
 * identical to the inline link three lines above it. A frame rather than a filled button:
 * the rulebook's structural copper is exactly this -- a line that is always there and means
 * nothing on its own -- and a framed label is a component the app's register already has.
 *
 * It drops the underline, which is the one place this file departs from the rule above.
 * That is allowed because the rule is really "the affordance may not depend on hover", and
 * the frame carries it at rest. The hover change is reinforcement on top, never the signal.
 */
.action a {
  display: inline-flex;
  align-items: center;
  padding: 0.55rem 1.15rem;
  border: 1px solid var(--rule);
  text-decoration: none;
  /* 48px is the app's minimum touch target and it clears the 44px its device spike set as
   * the layout contract. Padding alone gets close; this makes it exact rather than nearly. */
  min-height: 48px;
  box-sizing: border-box;
}

.action a:hover {
  border-color: var(--accent);
}

a:focus-visible {
  /* Focus is visibly different from hover rather than sharing its treatment, because a
   * keyboard user gets one and not the other. */
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}
