/* gamuli.com: one stylesheet for all three pages.
 *
 * ONE FILE, so the pages cannot drift apart. Same argument as the obstacles
 * copy having one source: three stylesheets is three chances for the privacy
 * page to stop looking like the site it belongs to.
 *
 * NO EXTERNAL REQUESTS ANYWHERE ON THIS SITE. No webfont, no CDN, no
 * analytics, no embeds. Partly because it is fast and cannot break, and partly
 * because it lets the privacy page say "this website makes no third-party
 * requests" and have that be true. A Google Fonts link would have made it a
 * lie, and on that page of all pages.
 *
 * The palette is lifted from the game's own, tools/art/tikit.py, so the site
 * and the store listing are the same cold blue rather than two guesses at it.
 */

:root {
  --deep:   #071926;   /* the well behind everything */
  --ground: #0a2338;   /* the field, UiKit.Ground */
  --card:   #17324b;   /* a raised surface */
  --line:   #23486a;   /* hairlines */
  --edge:   #5e8cad;   /* tikit EDGE, secondary type */
  --accent: #46a7d3;   /* tikit ACCENT, the one action colour */
  --snow:   #e8f4fb;   /* tikit SNOW, type */
  --dim:    #9fb8cc;

  /* The game's headings are letter-spaced to the point of being a device:
     "S E T T I N G S", "H O W  T O  P L A Y". The site borrows the habit
     rather than importing a personality from a webfont it would have to
     fetch. */
  --face: ui-sans-serif, system-ui, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, "Cascadia Mono", "SF Mono", Consolas, monospace;

  --measure: 34rem;    /* about 66 characters */
  --pad: clamp(1.25rem, 4vw, 2.5rem);

  color-scheme: dark;
}

/* A SINGLE VISUAL WORLD, deliberately: this is a game about polar night and
   there is no daylight version of it. So no prefers-color-scheme block.
   The colours below are the whole design, not the dark half of one. */

* { box-sizing: border-box; }

/* HIDDEN MUST WIN, and this is not housekeeping.
 *
 * The browser's own rule is `[hidden] { display: none }`, a bare attribute
 * selector, which ANY class that sets display beats. `.button` sets
 * `display: inline-block`, so the pre-launch link on the home page, marked
 * `hidden` precisely so it would not be live, rendered as a button. The one
 * element on the site that had to stay dark was the one shining. */
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100vh;
  /* So the footer sits at the bottom of the window on a short page. The home
     page is three elements tall and its footer would otherwise hang one
     scroll below the fold, which reads as a page that has not finished. */
  display: flex;
  flex-direction: column;
  font-family: var(--face);
  font-size: clamp(1rem, .95rem + .3vw, 1.125rem);
  line-height: 1.65;
  color: var(--snow);
  background: var(--deep);
  /* the ground's own cyan lift, as a gradient rather than a texture */
  background-image:
    radial-gradient(120% 70% at 50% 0%, #14507050 0%, transparent 62%),
    linear-gradient(180deg, var(--ground) 0%, var(--deep) 100%);
  background-attachment: fixed;
}

/* ---- rhythm ------------------------------------------------------------ */

.wrap {
  width: 100%;
  max-width: 60rem;
  margin: 0 auto;
  /* PADDING-INLINE, NOT THE SHORTHAND. `padding: 0 var(--pad)` also sets the
     block padding to zero, and .wrap beats a bare `main` on specificity, so
     `main { padding-top: 3rem }` lost silently and every page's first heading
     sat against the header rule. Caught in a screenshot, not in the source. */
  padding-inline: var(--pad);
}

/* Centred, not left-aligned in a wide box. A reading measure pinned to the
   left of a 60rem page leaves a void down the right that reads as a column
   that failed to load rather than as air. */
.narrow { max-width: var(--measure); margin-inline: auto; }

/* Space siblings apart with the layout, never with per-element margins that
   collapse into each other. */
.stack { display: flex; flex-direction: column; }
/* MARGIN-BLOCK, not the lot. The point of this line is to stop a child's own
   vertical margins fighting the gap; zeroing the horizontal ones too also
   killed `.narrow`'s `margin-inline: auto`, so every centred reading column
   silently went back to hugging the left edge. Second time the same shorthand
   has done this. See .wrap above. */
.stack > * {
  margin-block: 0;
  /* AND min-width:0, which is what keeps a phone from scrolling sideways.
     A flex item defaults to `min-width: auto`, refusing to be narrower than
     its content, so the screenshot rail, whose content is five phone-shaped
     images in a row, made itself 1300px wide inside a 430px column and dragged
     the whole page out with it. The rail's own overflow-x never got a chance
     to do its job. */
  min-width: 0;
}
.stack-s { gap: .6rem; }
.stack-m { gap: 1.15rem; }
.stack-l { gap: 2.5rem; }
/* A gap big enough to be a separation rather than a rhythm. The home page's
   mark, rule and line are one object and the link is a different one; at an
   even 2.5rem the link read as a third line of the identity. */
.stack-far { gap: clamp(3.5rem, 11vh, 6.5rem); }

/* ---- type -------------------------------------------------------------- */

h1, h2, h3 { font-weight: 800; line-height: 1.2; text-wrap: balance; }

h1 { font-size: clamp(1.9rem, 1.4rem + 2.2vw, 3rem); letter-spacing: -.01em; }
h2 {
  font-size: 1rem;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--accent);
}
h3 { font-size: 1.15rem; letter-spacing: .01em; }

p { margin: 0; }
a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: .18em; }
a:hover { color: var(--snow); }
a:focus-visible,
.button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 4px;
}

.lede { font-size: 1.15em; color: var(--snow); }
.quiet { color: var(--dim); }
.small { font-size: .875rem; color: var(--dim); }

ul { margin: 0; padding-left: 1.1rem; }
li::marker { color: var(--edge); }
li + li { margin-top: .5rem; }

hr {
  border: 0;
  height: 1px;
  background: var(--line);
  margin: 0;
}

/* ---- the mark ---------------------------------------------------------- */

/* GAMULI, set rather than drawn. Swap this one element for an <img> when the
   commissioned mark arrives; nothing else references it. */
.mark {
  font-weight: 800;
  font-size: clamp(2.4rem, 1.6rem + 4vw, 4.5rem);
  letter-spacing: .34em;
  text-indent: .34em;          /* tracking pads the right side only; recentre */
  text-transform: uppercase;
  color: var(--snow);
  line-height: 1;
}

.rule-under {
  width: 4rem;
  height: 2px;
  background: var(--accent);
  border-radius: 2px;
}

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

.site-head {
  padding: 1.6rem 0;
  border-bottom: 1px solid var(--line);
}
.site-head .wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}
.site-head .home {
  font-weight: 800;
  letter-spacing: .22em;
  text-transform: uppercase;
  font-size: .95rem;
  color: var(--snow);
  text-decoration: none;
}
.site-head .home:hover { color: var(--accent); }
.site-head nav { display: flex; gap: 1.4rem; font-size: .9rem; }

.site-foot {
  margin-top: 5rem;
  padding: 2rem 0 3rem;
  border-top: 1px solid var(--line);
  font-size: .875rem;
  color: var(--dim);
}
.site-foot a { color: var(--edge); }
.site-foot .wrap { display: flex; flex-wrap: wrap; gap: .6rem 1.6rem; }

/* ---- home -------------------------------------------------------------- */

.hold {
  flex: 1;
  display: grid;
  place-items: center;
  text-align: center;
  padding-block: 4rem;
}
.hold .stack { align-items: center; }

.button {
  /* INLINE-FLEX AND A MIN-HEIGHT, not just smaller padding. The type and the
     padding came down to make the button quieter beside a wordmark, which on a
     phone would have taken the tap target under the 44px everyone's guidelines
     ask for. The height is held; only the weight of it drops. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: .45rem 1.4rem;
  font-size: .875rem;
  border-radius: 9px;
  border: 1px solid #7fd0ef;
  background: linear-gradient(180deg, #63c0e6 0%, var(--accent) 100%);
  color: #06202e;
  font-weight: 800;
  letter-spacing: .06em;
  text-transform: uppercase;
  text-decoration: none;
  box-shadow: 0 2px 0 #1d6c92, 0 8px 22px #0000004d;
}
.button:hover { filter: brightness(1.08); color: #06202e; }
.button:active { transform: translateY(1px); box-shadow: 0 1px 0 #1d6c92; }

/* ---- the game page ----------------------------------------------------- */

main { flex: 1 0 auto; padding-top: 3rem; }

.hero { display: grid; gap: 2rem; align-items: center; }
@media (min-width: 46rem) {
  .hero { grid-template-columns: auto 1fr; gap: 2.5rem; }
}
.hero .icon {
  width: 108px; height: 108px;
  border-radius: 24px;
  display: block;
  box-shadow: 0 10px 30px #00000066;
}
.hero .wordmark {
  display: block;
  width: min(100%, 21rem);
  height: auto;
}

/* The page's real <h1> is the wordmark IMAGE, so the heading text is here for
   a screen reader and for anything that reads structure rather than pixels. */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Phone-shaped shots want a rail, not a grid: five portrait images side by
   side in a column layout would each be the width of a postage stamp. The
   rail scrolls itself so the page body never does. */
.rail {
  display: flex;
  gap: 1rem;
  overflow-x: auto;
  padding-bottom: 1rem;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
}
.rail img {
  flex: 0 0 auto;
  width: clamp(190px, 42vw, 250px);
  height: auto;
  border-radius: 14px;
  border: 1px solid var(--line);
  scroll-snap-align: start;
  background: var(--ground);
}

/* Two square-ish board close-ups side by side. They are NOT in the rail above:
   that rail is phone-shaped shots at one aspect, and dropping a wide crop into
   it would make one card half the height of its neighbours. */
.pair { display: grid; gap: 1.25rem; }
@media (min-width: 40rem) {
  .pair { grid-template-columns: 1fr 1fr; gap: 1.5rem; }
}
.shot { margin: 0; display: flex; flex-direction: column; gap: .6rem; }
.shot img {
  width: 100%;
  height: auto;
  /* Both crops are cut to 4:3 AT SOURCE so the pair sits level. Doing it here
     with object-fit instead zoomed each one until the thing it was a picture
     of had gone: the doorway off one, the shards off the other. Frame the
     photograph, do not crop it in the page. */
  border-radius: 12px;
  border: 1px solid var(--line);
  background: var(--ground);
}

.panel {
  background: #12293f99;
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 1.4rem 1.5rem;
}

.feature-grid { display: grid; gap: 1.25rem; }
@media (min-width: 40rem) {
  .feature-grid { grid-template-columns: 1fr 1fr; gap: 1.5rem; }
}
.feature h3 { color: var(--snow); margin-bottom: .3rem; }

/* ---- the policy -------------------------------------------------------- */

.doc h2 { margin-top: 2.2rem; }
.doc h2:first-of-type { margin-top: 0; }

.doc table {
  width: 100%;
  border-collapse: collapse;
  font-size: .9rem;
  font-variant-numeric: tabular-nums;
}
.doc th, .doc td {
  text-align: left;
  padding: .6rem .8rem;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
}
.doc th { color: var(--edge); font-weight: 600; letter-spacing: .04em; }
.doc code { font-family: var(--mono); font-size: .9em; color: var(--edge); }

/* A table is the wrong shape on a phone; let it scroll in its own box rather
   than let the page scroll sideways. */
.scroll-x { overflow-x: auto; }

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

/* THERE ISN'T ANY, and that is a decision rather than an omission.
 *
 * The home page had a staggered fade-up on its three elements. It was the
 * default flourish, the one every generated page reaches for, and on a page
 * whose entire content IS those three elements it hid all of them behind an
 * animation-delay. A screenshot taken mid-run showed one grey word on an empty
 * field and nothing else, which is also what a reader gets if the animation
 * never starts. Three elements do not need choreography.
 *
 * If motion is ever added here, it belongs on something that survives without
 * it: a hover, a scroll reveal on content already painted. Never on the thing
 * the page is for. */
