/* ─────────────────── fonts, served from here ───────────────────
   Self-hosted rather than linked from Google. The stylesheet link sent every
   visitor's IP and user-agent to a third party on every page view — including
   on the privacy page — and nothing on this site disclosed it.

   Cut to the four subsets these two languages actually need; greek and
   vietnamese are dropped. `unicode-range` is kept verbatim from Google's own
   CSS, so a browser still downloads only the subsets a page really uses: an
   English reader never fetches the Cyrillic files at all. Filenames carry a
   content hash, which is what lets them be cached for a year.             */

@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/ibm-plex-mono-cyrillic-ext-c6f09ee0.woff2') format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}

@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/ibm-plex-mono-cyrillic-7b59d6bf.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/ibm-plex-mono-latin-ext-f1050dc5.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/ibm-plex-mono-latin-c36f509c.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: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('fonts/ibm-plex-mono-cyrillic-ext-311098be.woff2') format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}

@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('fonts/ibm-plex-mono-cyrillic-d524dc8f.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('fonts/ibm-plex-mono-latin-ext-77f03e26.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('fonts/ibm-plex-mono-latin-a76f53ca.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: 'Manrope';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url('fonts/manrope-cyrillic-ext-e8c0b399.woff2') format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}

@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url('fonts/manrope-cyrillic-95a49306.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url('fonts/manrope-latin-ext-ce093b34.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url('fonts/manrope-latin-e310b55a.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: 'Manrope';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/manrope-cyrillic-ext-e8c0b399.woff2') format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}

@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/manrope-cyrillic-95a49306.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/manrope-latin-ext-ce093b34.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/manrope-latin-e310b55a.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: 'Manrope';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('fonts/manrope-cyrillic-ext-e8c0b399.woff2') format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}

@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('fonts/manrope-cyrillic-95a49306.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('fonts/manrope-latin-ext-ce093b34.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('fonts/manrope-latin-e310b55a.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: 'Manrope';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('fonts/manrope-cyrillic-ext-e8c0b399.woff2') format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}

@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('fonts/manrope-cyrillic-95a49306.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('fonts/manrope-latin-ext-ce093b34.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('fonts/manrope-latin-e310b55a.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: 'Manrope';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url('fonts/manrope-cyrillic-ext-e8c0b399.woff2') format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}

@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url('fonts/manrope-cyrillic-95a49306.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url('fonts/manrope-latin-ext-ce093b34.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url('fonts/manrope-latin-e310b55a.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: 'Prata';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/prata-cyrillic-ext-4430b5c7.woff2') format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}

@font-face {
  font-family: 'Prata';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/prata-cyrillic-a334ddd4.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

@font-face {
  font-family: 'Prata';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/prata-latin-8585ed0b.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;
}

/* Cantle — site styles.
 *
 * Colours are the game's own (cantle/src/theme/colors.ts) and obey the rule
 * written in that file: the chrome stays quiet so the puzzle colours are the
 * only saturated things on screen. Amber, Sky, Jade and Orchid appear only
 * where they carry meaning; gold is the game's leaderboard highlight and is
 * used here the same way — sparingly, for the things that matter.
 *
 * The game is dark-only (app.json sets userInterfaceStyle "dark"), so the site
 * is too. Every colour is painted, never inherited.
 */

:root {
  color-scheme: dark;

  --void:      #05070c;
  --bg:        #0b0e14;
  --raised:    #111725;
  --card:      #151c2c;
  --hair:      rgba(255, 255, 255, 0.07);
  --hair-2:    rgba(255, 255, 255, 0.13);
  --edge:      #5a6684;

  --text:      #f4f6fa;
  --text-2:    #a3aec1;
  --text-3:    #6b7488;

  --gold:      #f5c451;
  --gold-dim:  rgba(245, 196, 81, 0.55);
  --accent:    #6c8cff;

  --mast:      5.25rem;   /* the masthead's own fixed row height */

  --amber:     #e8a33d;
  --sky:       #5b8fe0;
  --jade:      #3fa06b;
  --orchid:    #e493c2;

  --display: Prata, "Bodoni MT", Didot, Georgia, serif;
  --sans:    Manrope, ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono:    "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  --page:    76rem;
  --reading: 36rem;

  --t: cubic-bezier(0.22, 0.61, 0.36, 1);
}

*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
/* Where an anchored section comes to rest. Without this a jump puts the
   section's own top edge at the top of the window -- underneath a masthead
   that is sticky and, on a phone, two rows tall. The section's padding hid
   how much was being swallowed; the heading survived and the air above it
   did not. --chrome is the measured height of the banner and the masthead
   together, so this follows them rather than guessing at a number. */
[id] { scroll-margin-top: calc(var(--chrome, 5.25rem) + 1.5rem); }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--sans);
  font-size: 1.125rem;
  line-height: 1.72;
  font-weight: 400;
  letter-spacing: 0.004em;
  -webkit-font-smoothing: antialiased;
  -webkit-text-size-adjust: 100%;
  overflow-x: hidden;
}

/* Ambient depth: three very faint colour fields and a fine grain, fixed so the
   page moves over them rather than dragging them along. */
body::before,
body::after { content: ""; position: fixed; inset: 0; pointer-events: none; }
body::before {
  z-index: -2;
  background:
    radial-gradient(58rem 40rem at 78% -6%,  rgba(232, 163, 61, 0.10), transparent 62%),
    radial-gradient(52rem 44rem at 6% 22%,   rgba(91, 143, 224, 0.11), transparent 60%),
    radial-gradient(46rem 40rem at 88% 78%,  rgba(228, 147, 194, 0.07), transparent 62%),
    linear-gradient(180deg, var(--bg) 0%, var(--void) 100%);
}
body::after {
  z-index: -1;
  opacity: 0.035;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
}

.page    { width: min(100% - 2.5rem, var(--page));    margin-inline: auto; }
.reading { width: min(100% - 2.5rem, var(--reading)); margin-inline: auto; }

/* ───────────────────────── type ───────────────────────── */

h1, h2, h3 { font-family: var(--display); font-weight: 500; text-wrap: balance; margin: 0; }
h1 { font-size: clamp(2.75rem, 5.6vw, 5rem); line-height: 0.98; letter-spacing: -0.028em; }
h2 { font-size: clamp(2rem, 4.6vw, 3.35rem);  line-height: 1.04; letter-spacing: -0.022em; }
h3 { font-size: 1.35rem; line-height: 1.25; letter-spacing: -0.012em; }

p { margin: 0 0 1.15rem; }
p:last-child { margin-bottom: 0; }

a { color: var(--text); text-decoration-color: var(--gold-dim); text-underline-offset: 0.22em; transition: color 0.2s var(--t); }
a:hover { color: var(--gold); }

.label {
  font-family: var(--mono); font-size: 0.82rem; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.2em; color: var(--gold);
  display: block; margin: 0 0 1.6rem;
}

.lede { font-size: clamp(1.125rem, 1.45vw, 1.3rem); line-height: 1.62; color: #b6bfd0; font-weight: 300; text-wrap: pretty; }

/* No border-radius override: an outline follows the element's own corners, and
   forcing 3px put a nearly-square box around circular controls. */
:focus-visible { outline: 2px solid var(--gold); outline-offset: 4px; }

/* ───────────────────────── masthead ───────────────────────── */

.masthead {
  position: sticky; top: 0; z-index: 40;
  background: rgba(11, 14, 20, 0.72);
  backdrop-filter: blur(16px) saturate(150%);
  border-bottom: 1px solid var(--hair);
}
.masthead > .page { display: flex; align-items: center; justify-content: space-between; gap: 1rem; height: 5.25rem; }
.masthead-right { display: flex; align-items: center; gap: 1.75rem; }

.wordmark { display: inline-flex; align-items: center; gap: 0.7rem; text-decoration: none; color: var(--text); font-family: var(--display); font-size: 2rem; font-weight: 500; letter-spacing: 0.005em; }
.colophon .wordmark { font-size: 1.65rem; }
.wordmark svg { display: block; }
.wordmark:hover { color: var(--text); }

.nav { display: flex; align-items: center; gap: 2rem; }
.nav a { font-family: var(--mono); font-size: 0.8rem; font-weight: 500; text-transform: uppercase; letter-spacing: 0.13em; color: var(--text-3); text-decoration: none; }
.nav a:hover, .nav a[aria-current="page"] { color: var(--text); }
@media (max-width: 40rem) {
  .nav { gap: 1.1rem; }
  .nav a { font-size: 0.72rem; letter-spacing: 0.1em; }
  /* On a phone the header cannot hold four links, a wordmark and the language
     toggle — the row stops fitting and takes the whole page sideways with it.
     The in-page anchors are the ones to drop: on a screen this narrow they
     point at content you reach by scrolling anyway, while Practice is a page
     of its own and the footer still carries the full set. */
  /* The header gets a second row instead of losing links. Hiding the section
     anchors here did fit the row, but it also cut the only route to Modes,
     Tips and Details on a phone -- the footer carries neither, and from the
     practice page there was no way back to them at all.

     `display: contents` dissolves the right-hand group so the wordmark, the
     language switch and the nav become siblings: the first two share the top
     row, and the nav, at full width, wraps below them. */
  .masthead > .page { height: auto; flex-wrap: wrap; padding-block: 0.7rem; row-gap: 0.5rem; }
  .masthead-right { display: contents; }
  .lang { order: 1; }
  /* wrap, not nowrap: with five items the last one ran off the edge and was
     clipped rather than dropping to a line of its own. */
  .nav { order: 2; width: 100%; justify-content: flex-start;
    flex-wrap: wrap; gap: 0.5rem 1.1rem; }
}

.lang {
  display: inline-flex; align-items: center; flex: none;
  padding: 2px; border-radius: 999px;
  border: 1px solid var(--hair-2); background: rgba(255, 255, 255, 0.035);
}
.lang a {
  font-family: var(--mono); font-size: 0.76rem; font-weight: 500;
  letter-spacing: 0.08em; text-transform: uppercase; line-height: 1;
  padding: 0.38rem 0.72rem; border-radius: 999px;
  color: var(--text-3); text-decoration: none;
  transition: color 0.2s var(--t), background 0.2s var(--t);
}
.lang a:hover { color: var(--text); }
.lang a[aria-current="true"] { background: rgba(255, 255, 255, 0.12); color: var(--text); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08); }
@media (max-width: 40rem) {
  .masthead-right { gap: 0.9rem; }
  .lang a { font-size: 0.68rem; padding: 0.32rem 0.58rem; letter-spacing: 0.05em; }
}

/* ───────────────────────── hero ───────────────────────── */

.hero {
  position: relative;
  padding-block: clamp(3rem, 6.5vw, 5.5rem) clamp(3rem, 7vw, 6rem);
  /* The hero owns the first screen. Left to its content it stopped short of
     the fold, and whatever came next was sliced across the bottom at whatever
     height the window happened to be -- a cut that reads as a mistake rather
     than as an invitation. `min-height`, not `height`: on a short window the
     content still wins and the section grows instead of overflowing. */
  min-height: calc(100vh - var(--chrome, 5.25rem));
  min-height: calc(100svh - var(--chrome, 5.25rem));
  display: flex; flex-direction: column; justify-content: center;
  /* The bloom behind the board is deliberately larger than the board, and on a
     narrow screen that surplus was widening the document — the whole page could
     be dragged sideways to look at a gradient. Clipped here rather than on the
     body, because the masthead is sticky and `clip` on an ancestor would strand
     it; and `clip` rather than `hidden`, which would make this a scroll box. */
  overflow-x: clip;
}
.hero-grid { display: grid; gap: clamp(2.5rem, 6vw, 5rem); align-items: center; }
/* The board gets the wider half. It was sharing evenly and losing — the
   canvas is square, so its width is its height, and the column was the
   binding limit long before max-width ever was. */
@media (min-width: 60rem) { .hero-grid { grid-template-columns: 0.88fr 1.12fr; } }

/* The display size follows the width of the window, which on a short laptop is
   the wrong axis: at 1440x760 the Ukrainian headline runs to four lines and
   pushes the store buttons past the fold. `vh` in the middle of the clamp lets
   the height have a say too, so the first screen keeps its call to action. */
.hero h1 { font-size: clamp(2.4rem, min(5.6vw, 9.5vh), 5rem); }
.hero h1 em { font-style: normal; color: var(--gold); }
.hero .lede { max-width: 30rem; margin-top: 1.75rem; }

/* The board is the hero image. It gets a soft bloom behind it so it reads as
   lit rather than drawn. */
.board-frame { position: relative; width: 100%; max-width: 44rem; margin-inline: auto; }
.board-frame::before {
  content: ""; position: absolute; inset: -14%;
  background: radial-gradient(closest-side, rgba(108, 140, 255, 0.16), transparent 72%);
  filter: blur(8px); pointer-events: none;
}
.board { position: relative; aspect-ratio: 1 / 1; }
.board canvas { width: 100%; height: 100%; display: block; }


.board-meta {
  display: flex; justify-content: center; gap: 1.6rem; margin-top: 1.4rem;
  font-family: var(--mono); font-size: 0.82rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: #8b95aa;
}
.board-meta b { color: var(--text-2); font-weight: 500; }

/* The fold is now clean, which leaves nothing peeking to say there is more.
   This says it instead: quiet, and the only moving thing on the screen. */
/* Pinned to the bottom edge of the first screen, not floated after the content.
   Centred with the content it landed a couple of hundred pixels above the fold,
   which reads as an element that lost its place rather than as the end of the
   screen. Absolute, so the hero's own content stays vertically centred. */
.scroll-cue {
  position: absolute; left: 50%; transform: translateX(-50%);
  bottom: clamp(1.25rem, 3.5vh, 2.5rem);
  display: inline-flex; flex-direction: column; align-items: center; gap: 0.5rem;
  text-decoration: none; color: var(--text-3);
  font-family: var(--mono); font-size: 0.68rem; letter-spacing: 0.16em; text-transform: uppercase;
  transition: color 0.3s var(--t);
}
.scroll-cue:hover { color: var(--text-2); }
.scroll-cue svg { display: block; animation: cue-bob 2.4s ease-in-out infinite; }
@keyframes cue-bob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(4px); } }
@media (prefers-reduced-motion: reduce) { .scroll-cue svg { animation: none; } }

/* A short laptop is short of about 160px, and the hero's own vertical padding
   alone is 184 -- so the fix is air, not type. Measured at 1440x760, where the
   Ukrainian headline runs to four lines and pushed the store buttons out of
   the first screen entirely. */
@media (max-height: 52rem) and (min-width: 60rem) {
  .hero { padding-block: clamp(1.25rem, 3vh, 2.75rem); }
  .hero .lede { margin-top: 1rem; }
  .stores { margin-top: 1.5rem; }
  .scroll-cue { bottom: clamp(0.75rem, 2vh, 1.25rem); }
}

/* ───────────────────────── ways to play ───────────────────────── */

.modes { display: grid; gap: 1.35rem; margin-top: clamp(2.5rem, 5vw, 3.5rem); }
@media (min-width: 46rem) { .modes { grid-template-columns: repeat(2, 1fr); } }
.mode {
  position: relative; padding: 2rem 1.9rem 1.8rem; border-radius: 14px;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.045), rgba(255, 255, 255, 0.012));
  border: 1px solid var(--hair);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);
  transition: border-color 0.3s var(--t), transform 0.3s var(--t);
}
.mode:hover { border-color: rgba(245, 196, 81, 0.3); transform: translateY(-3px); }
.mode h3 { margin: 0 0 0.55rem; }
.mode p { color: var(--text-2); font-weight: 300; margin-bottom: 0; }
.mode-tag { font-family: var(--mono); font-size: 0.72rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--gold-dim); display: block; margin-bottom: 1rem; }

.tiers { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 1.15rem; }
.tier {
  display: inline-flex; align-items: center; gap: 0.5rem;
  font-family: var(--mono); font-size: 0.76rem; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--text-2); border: 1px solid var(--hair); border-radius: 999px; padding: 0.35rem 0.75rem;
}
.tier i { width: 0.65rem; height: 0.65rem; border-radius: 50%; background: var(--c); }

/* ───────────────────────── tips ───────────────────────── */

.tips { counter-reset: tip; display: grid; gap: 0; margin-top: clamp(2.5rem, 5vw, 3.5rem); border-top: 1px solid var(--hair); }
.tip { counter-increment: tip; display: grid; gap: 0.3rem 1.75rem; padding: 1.65rem 0; border-bottom: 1px solid var(--hair); }
@media (min-width: 44rem) { .tip { grid-template-columns: 3.5rem 1fr; } }
.tip::before { content: counter(tip, decimal-leading-zero); font-family: var(--mono); font-size: 0.86rem; letter-spacing: 0.1em; color: var(--gold-dim); padding-top: 0.3rem; }
.tip h3 { margin: 0 0 0.35rem; font-family: var(--sans); font-size: 1.12rem; font-weight: 700; letter-spacing: -0.01em; }
.tip p { color: var(--text-2); font-weight: 300; margin: 0; }

/* ───────────────────────── the details ───────────────────────── */

.spec { display: grid; gap: 0; margin-top: clamp(2.5rem, 5vw, 3.5rem); border-top: 1px solid var(--hair); }
.spec > div { display: grid; gap: 0.3rem 1.75rem; padding: 1.15rem 0; border-bottom: 1px solid var(--hair); align-items: baseline; }
@media (min-width: 44rem) { .spec > div { grid-template-columns: 14rem 1fr; } }
.spec dt { font-family: var(--mono); font-size: 0.8rem; letter-spacing: 0.11em; text-transform: uppercase; color: var(--text-3); }
.spec dd { margin: 0; color: var(--text-2); font-weight: 300; }
.spec dd b { color: var(--text); font-weight: 600; font-variant-numeric: tabular-nums; }

/* ───────────────────────── practice ───────────────────────── */

/* This page is a control surface, not a document. Everything needed to solve
   a board — tiers, clock, board, palette — is sized to the viewport and fits
   between the masthead and the bottom of the screen at any height, so nothing
   has to be scrolled to mid-solve. What explains the page sits below it, where
   scrolling is the right gesture.

   svh, not vh: on a phone `vh` is the height with the browser chrome RETRACTED,
   so a layout built on it is taller than the screen actually is until you
   scroll — which is the one thing this page exists to avoid. */
.play { display: flex; flex-direction: column; min-height: 28rem; }
/* A definite height, not a minimum: the board below sizes itself from the
   height left over, and `min-height` leaves that height indefinite — the
   container query resolves to zero and the board vanishes. min-height stays
   only as a floor for absurdly short windows, where scrolling is the honest
   answer; set too high it becomes the overflow it was meant to prevent.

   --chrome is measured and published by site.js, because the banner above the
   masthead is a sentence that wraps — no constant here can be right at every
   width and in both languages. The fallback is the masthead alone. */
.play { height: calc(100vh - var(--chrome, var(--mast))); }
.play { height: calc(100svh - var(--chrome, var(--mast))); }

.play-page {
  flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column;
  gap: clamp(0.5rem, 1.6vh, 1.05rem);
  padding-block: clamp(0.6rem, 2vh, 1.4rem);
}

.play-head { display: flex; align-items: baseline; justify-content: space-between; flex-wrap: wrap; gap: 0.75rem 1.25rem; }
.play-head h1 { font-size: clamp(1.15rem, 0.85rem + 1.3vw, 1.75rem); margin: 0; line-height: 1.15; }

.tier-bar { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.tier-btn {
  display: inline-flex; align-items: baseline; gap: 0.4rem;
  padding: 0.42rem 0.85rem; border-radius: 999px;
  border: 1px solid var(--hair); background: rgba(255, 255, 255, 0.02);
  font-size: 0.85rem; color: var(--text-2); cursor: pointer;
  transition: color 0.2s var(--t), border-color 0.2s var(--t), background 0.2s var(--t);
}
.tier-btn i { font-family: var(--mono); font-style: normal; font-size: 0.72rem; color: var(--text-3); }
.tier-btn:hover { color: var(--text); border-color: var(--hair-2); }
.tier-btn[aria-selected="true"] {
  background: var(--gold); border-color: var(--gold); color: #1c1400; font-weight: 500;
}
.tier-btn[aria-selected="true"] i { color: rgba(28, 20, 0, 0.55); }

/* The clock is centred by giving it a column of its own between two equal
   sides, so it does not shift when the buttons beside it change width. */
.hud { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 1rem; }
.hud-clock { grid-column: 2; text-align: center; }
.hud-clock > b {
  display: block; line-height: 1;
  font-size: clamp(1.6rem, 1.15rem + 1.8vw, 1.95rem); font-weight: 800;
  color: #ffffff; letter-spacing: -0.02em; font-variant-numeric: tabular-nums;
}
.hud-moves {
  display: block; margin-top: 5px;
  font-family: var(--mono); font-size: 0.72rem; letter-spacing: 0.08em;
  text-transform: uppercase; color: #8a8a94;
}
.hud-moves b { color: var(--text-2); font-weight: 500; font-variant-numeric: tabular-nums; }

.hud-tools { grid-column: 3; display: flex; justify-content: flex-end; gap: 0.6rem; }
/* 36px gold-rimmed disc — the app's own header button, same size and border. */
.disc {
  width: 36px; height: 36px; flex: none; border-radius: 50%;
  display: grid; place-items: center; cursor: pointer;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(201, 162, 74, 0.42);
  transition: border-color 0.2s var(--t), background 0.2s var(--t), opacity 0.2s var(--t);
}
.disc:hover { border-color: rgba(201, 162, 74, 0.78); background: rgba(201, 162, 74, 0.09); }
.disc svg { display: block; }

/* The board takes whatever height is left, and is square. `100cqh` is the
   height of this box, so the square is capped by the SHORTER of the two axes
   — the plain min() above it is the fallback for engines without container
   units, which get the old width-driven behaviour rather than nothing. */
/* The board is the only row here that flexes, which means it is the only one
   that pays when the window is short — and `flex: 1 1 0` will pay it all the
   way down to nothing. Seen for real: at a viewport too short for the fixed
   rows the canvas measured 0x0 and the board simply was not there. A floor on
   both the row and the square makes the page scroll instead, which is the
   honest failure. */
/* Centred in the space it is given, not pinned to the top of it: the square
   rarely fills that box exactly, and the leftover belongs on both sides. */
.play-board { flex: 1 1 0; min-height: 9rem; container-type: size;
  display: grid; place-items: center; }
.board-fit { position: relative; margin-inline: auto; aspect-ratio: 1; }
.board-fit { width: min(100%, 34rem); }
.board-fit { width: clamp(9rem, min(100%, 100cqh, 34rem), 34rem); }
/* Mobile browsers paint a translucent box over whatever they judge tappable.
   On the board that box is the size of the board -- most of a phone screen --
   and it flashes on every move. The feedback it provides is already there and
   better: the node settles, a ripple leaves it, the colour changes. */
* { -webkit-tap-highlight-color: transparent; }

#practice-board {
  display: block; width: 100%; height: 100%;
  cursor: pointer; touch-action: manipulation;
  /* Clearing a node is a long press, and a long press on a canvas is also how
     iOS opens its save-image menu. Both fired at once: the board cleared and
     the system sheet came up over it. */
  -webkit-touch-callout: none;
  user-select: none; -webkit-user-select: none;
}

.board-veil {
  position: absolute; inset: 0; z-index: 2;
  display: none; flex-direction: column; align-items: center; justify-content: center;
  gap: 1rem; text-align: center; padding: 1.5rem;
}
/* Opaque, not translucent. The board behind it is not drawn at all before the
   clock starts (see board.js), and this matches that: a cover, not a haze.
   A translucent one would also have to be trusted, and it should not be. */
.board-veil[data-veil-start] {
  border-radius: 18px; border: 1px solid var(--hair);
  background: linear-gradient(180deg, #131a2a, #0c1119);
}

[data-phase="idle"] .board-veil[data-veil-start] { display: flex; }

.start-btn {
  border: 0; border-radius: 999px; cursor: pointer;
  padding: 0.7rem 1.7rem; background: var(--gold); color: #1c1400;
  font-family: var(--sans); font-size: 1rem; font-weight: 600;
  transition: transform 0.28s var(--t);
}
.start-btn:hover { transform: translateY(-2px); }
.veil-note { max-width: 20rem; font-size: 0.88rem; line-height: 1.5; color: var(--text-2); font-weight: 300; margin: 0; }
.done-flawless { font-family: var(--mono); font-size: 0.78rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--gold); margin: 0; display: none; }
[data-flawless="true"] .done-flawless { display: block; }

/* Reserved height, so the board above never jumps as the line changes. */
.play-hint {
  min-height: 1.2rem; margin: 0; text-align: center;
  font-size: 0.79rem; color: #8a8a94; font-variant-numeric: tabular-nums;
}
.play-hint[data-state="clash"]    { color: #ff8f8f; }
.play-hint[data-state="solved"]   { color: var(--text); }
.play-hint[data-state="flawless"] { color: var(--gold); }

/* 54px swatches with a fixed 1-4 label beneath, as the app's tray has them.
   The digits name the palette order so a colour can be called by number —
   they are labels, never counts. */
.palette { display: flex; justify-content: center; gap: clamp(0.7rem, 3vw, 1.125rem); }
.chip-btn {
  display: grid; justify-items: center; gap: 0.55rem;
  background: none; border: 0; padding: 0; cursor: pointer;
  --sw: clamp(2.3rem, 1.2rem + 4.4vw, 3.375rem);
}
.chip-sw {
  position: relative; width: var(--sw); height: var(--sw); border-radius: 50%;
  background: var(--c); display: grid; place-items: center;
  font-size: calc(var(--sw) * 0.44); line-height: 1; color: #ffffff;
  transition: transform 0.2s var(--t);
}
.chip-btn:hover .chip-sw { transform: translateY(-2px); }
/* Gold marks the player's own current choice, and only that — never a board
   state, which is what the red conflict ring and the white focus ring are. */
.chip-btn[aria-pressed="true"] .chip-sw::after {
  content: ""; position: absolute; inset: -5px; border-radius: 50%;
  border: 2.5px solid #e8c86a;
}
/* The palette chip is a swatch with a digit beneath it, and the default focus
   box drew around BOTH — a gold rectangle enclosing the whole control, which
   reads as a second, larger selection ring. The indicator belongs on the
   swatch. White, not gold: gold means the colour you have chosen, and a focus
   ring is not a choice yet. Suppressed on the chosen chip, which already wears
   its own ring — one ring per swatch, the same rule the board follows. */
.chip-btn:focus-visible { outline: none; }
.chip-btn:not([aria-pressed="true"]):focus-visible .chip-sw::before {
  content: ""; position: absolute; inset: -5px; border-radius: 50%;
  border: 2px solid #ffffff;
}

.chip-n { font-family: var(--mono); font-size: 0.78rem; font-weight: 700; color: #9a9aa4; font-variant-numeric: tabular-nums; }
.chip-btn[aria-pressed="true"] .chip-n { color: #e8c86a; font-weight: 800; }

/* On a phone the head is competing with the board for the same pixels, and
   the board is the thing being used. Tighter chips keep the four tiers on one
   row instead of two, and the page title steps back to a size that no longer
   claims a row of its own — together worth about eighty pixels of board. */
@media (max-width: 30rem) {
  .play-head { gap: 0.5rem 0.75rem; }
  .play-head h1 { font-size: 1.05rem; }
  .tier-bar { gap: 0.3rem; }
  .tier-btn { padding: 0.3rem 0.55rem; font-size: 0.76rem; gap: 0.28rem; }
  .tier-btn i { font-size: 0.66rem; }
  .hud-clock > b { font-size: 1.5rem; }
  .chip-btn { gap: 0.35rem; }
}
/* The result block is taller than the palette it replaces, and on a phone it
   cleared the bottom of the screen by single digits. Tightened here rather
   than shrinking the time, which is the one thing the screen is for. */
@media (max-width: 30rem), (max-height: 50rem) {
  .result-rule { margin-bottom: 0.55rem; }
  .result-note { margin-top: 0.35rem; }
  .result-time { margin-top: 0.35rem; font-size: clamp(2rem, 1.2rem + 3vw, 2.6rem); }
  .result-stats { margin-top: 0.6rem; }
  .result-go { margin-top: 0.8rem; padding: 0.6rem 1.4rem; }
}

/* A short window is a different squeeze from a narrow one: here the fixed
   rows above and below the board are what has to give. */
@media (max-height: 44rem) {
  .play-page { gap: 0.45rem; padding-block: 0.5rem; }
  .play-head h1 { font-size: 1.05rem; }
  .hud-clock > b { font-size: 1.45rem; }
  .chip-btn { --sw: clamp(2.1rem, 1rem + 4vw, 2.6rem); gap: 0.3rem; }
}

/* The finished board is the reward, so nothing covers it: the result takes
   the row the palette was using, exactly as the app keeps the board on screen
   and puts its banner beneath. Anatomy and type are the app's SolvedResultPanel
   — a gold hairline that fades at both ends, a small wide-tracked gold title,
   then the time as the largest thing on the screen. */
.result { display: none; flex-direction: column; align-items: center; text-align: center; }
[data-phase="done"] .result { display: flex; animation: result-in 0.22s cubic-bezier(0.2, 0.8, 0.2, 1) both; }
[data-phase="done"] .play-hint,
[data-phase="done"] .palette { display: none; }

@keyframes result-in { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }

.result-rule {
  width: 104px; height: 1px; margin-bottom: 0.9rem;
  background: linear-gradient(90deg, transparent, rgba(201, 162, 74, 0.85), transparent);
}
.result-title {
  margin: 0; color: var(--gold);
  font-family: var(--sans); font-size: 0.94rem; font-weight: 800;
  letter-spacing: 0.16em; text-transform: uppercase;
}
/* One quiet footnote, never a second celebration competing with the title. */
.result-note { margin: 0.5rem 0 0; color: #a8a8b2; font-size: 0.8rem; font-weight: 600; display: none; }
[data-flawless="true"] .result-note { display: block; }
.result-time {
  margin: 0.5rem 0 0; color: #ffffff; font-weight: 800; letter-spacing: -0.02em;
  font-size: clamp(2.2rem, 1.4rem + 3vw, 3.25rem); line-height: 1;
  font-variant-numeric: tabular-nums;
}
.result-stats { display: flex; align-items: center; gap: 1.375rem; margin-top: 0.9rem; }
.result-stat { display: flex; flex-direction: column; align-items: center; }
.result-stat span {
  color: #8a8a94; font-family: var(--mono); font-size: 0.68rem;
  letter-spacing: 0.05em; text-transform: uppercase; margin-bottom: 3px;
}
.result-stat b { color: #e9e9ed; font-size: 0.94rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.result-div { width: 1px; height: 28px; background: rgba(255, 255, 255, 0.12); }
.result-go {
  margin-top: 1.1rem; cursor: pointer;
  padding: 0.7rem 1.6rem; border-radius: 16px;
  background: var(--gold); color: #0c0304; border: 1.5px solid #c9a24a;
  font-family: var(--sans); font-size: 1rem; font-weight: 700;
  transition: transform 0.28s var(--t);
}
.result-go:hover { transform: translateY(-2px); }

.play-notes { padding-block: clamp(2.5rem, 5vw, 3.5rem); border-top: 1px solid var(--hair); }
.play-notes p { color: var(--text-2); font-weight: 300; margin: 0 0 1rem; }
.play-notes p:last-child { margin-bottom: 0; }

/* ───────────────────────── the note ───────────────────────── */

.note { max-width: 40rem; margin-inline: auto; }
/* Centred, like every other section's kicker. The body below it stays ranged
   left, because this is the one block of long prose on the page and centring
   it would cost more in readability than the symmetry is worth -- but the
   label had no reason to break the rhythm. */
.note .label { text-align: center; }
.note-body p {
  font-size: clamp(1.125rem, 1.5vw, 1.3rem); line-height: 1.68;
  color: #c3cbd9; font-weight: 300; margin-bottom: 1.4rem;
}
.note-body strong { color: var(--text); font-weight: 600; }
.note-body p:first-child { font-size: clamp(1.25rem, 1.9vw, 1.55rem); line-height: 1.5; color: var(--text); }
.note-sign {
  margin: 2.25rem 0 0; padding-top: 1.6rem; border-top: 1px solid var(--hair);
  font-family: var(--display); font-size: 1.4rem; color: var(--text-2);
}

/* ───────────────────────── store buttons ───────────────────────── */

/* Drawn here rather than using Apple's and Google's own artwork, for one
   reason that decides it: Apple ships no Ukrainian badge — its endpoint
   returns the English file byte-for-byte for uk-ua while serving real
   translations for de, fr, ja, pl and ru — so the official set cannot give
   the Ukrainian page a matching pair. Drawing both also lets the two read
   the same way, which the official wording ("Download on the" against "Get
   it on") does not.
   To go back: the official files are one curl away, see README. */

.stores { display: flex; flex-wrap: wrap; gap: 1rem; margin-top: 3.25rem; }

.store {
  position: relative; isolation: isolate;
  display: inline-flex; align-items: center; gap: 1.05rem;
  /* Never wider than it wants to be, and never so wide that the pair stops
     fitting on one line — two stacked store buttons read as a list of
     choices to weigh rather than as one obvious next step. */
  min-width: min(16.25rem, calc(50% - 0.5rem)); padding: 0.9rem 1.6rem;
  border-radius: 14px; text-decoration: none; color: var(--text);
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.075), rgba(255, 255, 255, 0.022));
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.09), 0 12px 28px -20px rgba(0, 0, 0, 0.9);
  transition: transform 0.28s var(--t), border-color 0.28s var(--t), box-shadow 0.28s var(--t);
}

/* A single soft highlight raked across the top edge, so the surface reads as
   lit rather than filled. */
.store::before {
  content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit;
  background: radial-gradient(120% 80% at 30% -30%, rgba(255, 255, 255, 0.14), transparent 60%);
  opacity: 0; transition: opacity 0.28s var(--t);
}
.store:hover { transform: translateY(-2px); border-color: rgba(255, 255, 255, 0.26); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.12), 0 18px 34px -22px rgba(0, 0, 0, 1); color: var(--text); }
.store:hover::before { opacity: 1; }

.store-mark { flex: none; display: grid; place-items: center; width: 2.15rem; }
.store-mark svg { display: block; }

/* Two lines, weighted hard toward the second. "Download on" reads identically
   on both buttons and so carries nothing between them; the store's name is the
   only part anyone scans for. Four levers pull the same way — the label is
   smaller, lighter, dimmer and tracked wide, which makes it read as a caption
   rather than a sentence; the name is larger, at the family's heaviest weight,
   and tracked tight, which adds mass without adding size.
   The label was dimmed too far at first — #7d8799 measures 4.9:1 against the
   button's surface, past the 4.5:1 floor for small text, while the name still
   runs at 2.2x its size and twice its weight. Quiet is not the same as faint. */
.store-text   { display: grid; gap: 0.14rem; text-align: left; }
.store-kicker { font-family: var(--mono); font-size: 0.68rem; font-weight: 500; letter-spacing: 0.17em; text-transform: uppercase; color: #7d8799; }
.store-name   { font-size: 1.5rem; font-weight: 800; letter-spacing: -0.03em; line-height: 1.02; }

/* The visitor's own platform, set by assets/site.js. Gold is the game's own
   leaderboard highlight — the one place the page spends it on a control. */
.store[data-primary="true"] {
  background: linear-gradient(180deg, #ffdc86 0%, var(--gold) 55%, #e8b23e 100%);
  border-color: rgba(255, 226, 150, 0.75);
  color: #1c1400;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.5), 0 16px 34px -18px rgba(245, 196, 81, 0.5);
}
.store[data-primary="true"]:hover { transform: translateY(-2px); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.6), 0 22px 42px -20px rgba(245, 196, 81, 0.6); color: #1c1400; }
.store[data-primary="true"] .store-kicker { color: rgba(28, 20, 0, 0.58); }
.store[data-primary="true"] .store-mark .apple-mark { fill: #1c1400; }

.finale .stores { justify-content: center; }

.store-note { font-family: var(--mono); font-size: 0.82rem; letter-spacing: 0.07em; text-transform: uppercase; color: #8b95aa; margin: 1.6rem 0 0; }

/* ───────────────────────── bands ───────────────────────── */

.band { padding-block: clamp(5rem, 10vw, 9rem); border-top: 1px solid var(--hair); position: relative; }
.band--quiet { background: linear-gradient(180deg, rgba(255, 255, 255, 0.016), transparent 60%); }

.statement { text-align: center; max-width: 40rem; margin-inline: auto; }
.statement .label { justify-content: center; }
.statement .lede { margin: 1.75rem auto 0; max-width: 34rem; }

/* The four colours, stated once and compactly rather than as a chart. */
.chips { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.55rem 1.6rem; margin-top: 2.25rem; }
.chip { display: inline-flex; align-items: center; gap: 0.6rem; font-family: var(--mono); font-size: 0.82rem; letter-spacing: 0.09em; text-transform: uppercase; color: #8b95aa; }
.chip i { width: 1.4rem; height: 1.4rem; border-radius: 50%; display: grid; place-items: center; font-style: normal; font-size: 0.72rem; color: #0b0e14; }

/* Feature cards */
.cards { display: grid; gap: 1.35rem; margin-top: clamp(2.5rem, 5vw, 3.5rem); }
@media (min-width: 46rem) { .cards { grid-template-columns: repeat(2, 1fr); } }
.card {
  position: relative; padding: 2.3rem 2.15rem 2.1rem; border-radius: 14px;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.045), rgba(255, 255, 255, 0.012));
  border: 1px solid var(--hair);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);
  transition: border-color 0.3s var(--t), transform 0.3s var(--t);
}
.card:hover { border-color: rgba(245, 196, 81, 0.3); transform: translateY(-3px); }
.card h3 { margin-bottom: 0.6rem; }
.card p { color: var(--text-2); font-weight: 300; margin-bottom: 0; }
.card-index { font-family: var(--mono); font-size: 0.8rem; letter-spacing: 0.16em; color: var(--gold-dim); display: block; margin-bottom: 1.1rem; }

/* Closing call to action */
.finale { text-align: center; }
.finale .store-note { text-align: center; }

/* ───────────────────────── documents ───────────────────────── */

.doc { padding-block: clamp(3rem, 7vw, 5rem) clamp(4rem, 9vw, 7rem); }
.doc h1 { font-size: clamp(2.2rem, 5.5vw, 3.6rem); line-height: 1.02; }
.doc h2 { font-size: clamp(1.35rem, 2.6vw, 1.7rem); line-height: 1.2; margin: 3.25rem 0 0.9rem; }
.doc h3 { font-size: 1.08rem; font-family: var(--sans); font-weight: 700; letter-spacing: -0.005em; margin: 2rem 0 0.5rem; }
.doc p, .doc li { color: var(--text-2); font-weight: 300; }
.doc strong { color: var(--text); font-weight: 600; }
.doc ul, .doc ol { padding-left: 1.2rem; }
.doc li { margin-bottom: 0.5rem; }
.doc a { color: var(--gold); text-decoration-color: var(--gold-dim); }

.dateline { font-family: var(--mono); font-size: 0.82rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-3); margin: 1.25rem 0 3rem; }

.doc main { counter-reset: clause; }
.clause { counter-increment: clause; }
.clause > h2::before {
  content: counter(clause, decimal-leading-zero);
  font-family: var(--mono); font-size: 0.62em; font-weight: 500;
  color: var(--gold-dim); margin-right: 0.9em; vertical-align: 0.22em;
}

.panel {
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.04), rgba(255, 255, 255, 0.01));
  border: 1px solid var(--hair); border-radius: 14px;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);
  padding: 1.6rem 1.75rem; margin: 2rem 0;
}
.panel > :last-child { margin-bottom: 0; }
.panel h2, .panel h3 { margin-top: 0; }

.jurisdiction { border-left: 1px solid var(--gold-dim); padding: 0.15rem 0 0.15rem 1.4rem; margin: 1.75rem 0; }
.jurisdiction > :last-child { margin-bottom: 0; }
.jurisdiction h3 { margin-top: 0; font-family: var(--mono); font-size: 0.82rem; font-weight: 500; text-transform: uppercase; letter-spacing: 0.12em; color: var(--gold); }

dl.facts { margin: 0; display: grid; gap: 1.15rem; }
dl.facts > div { display: grid; gap: 0.2rem; }
dl.facts dt { font-family: var(--mono); font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.11em; color: var(--text-3); }
dl.facts dd { margin: 0; color: var(--text-2); }

.table-scroll { overflow-x: auto; margin: 1.6rem 0; border-radius: 10px; }
table { width: 100%; border-collapse: collapse; font-size: 0.94rem; min-width: 32rem; }
th, td { text-align: left; padding: 0.75rem 0.9rem 0.75rem 0; border-bottom: 1px solid var(--hair); vertical-align: top; }
th { font-family: var(--mono); font-size: 0.76rem; font-weight: 500; text-transform: uppercase; letter-spacing: 0.1em; color: var(--text-3); border-bottom-color: var(--hair-2); }
td { color: var(--text-2); font-weight: 300; }
td:first-child { color: var(--text); font-weight: 400; }
th:last-child, td:last-child { padding-right: 0; }

/* A fact only the owner can supply. Must reach zero before launch. */
.fill { display: inline; background: rgba(245, 196, 81, 0.09); color: var(--gold); border-bottom: 1px dashed var(--gold-dim); padding: 0.05em 0.35em; font-family: var(--mono); font-size: 0.88em; letter-spacing: 0.01em; }

.draft { border-bottom: 1px solid var(--hair); background: rgba(245, 196, 81, 0.04); color: #8b95aa; font-family: var(--mono); font-size: 0.78rem; letter-spacing: 0.09em; text-transform: uppercase; text-align: center; padding: 0.6rem 1rem; }
.draft b { color: var(--gold); font-weight: 500; }

/* ───────────────────────── colophon ───────────────────────── */

.colophon { border-top: 1px solid var(--hair); padding-block: clamp(3.5rem, 6vw, 5rem) 3.25rem; font-size: 0.95rem; color: #7b8598; }
.colophon-top { display: grid; gap: 2.5rem; margin-bottom: 3rem; }
@media (min-width: 44rem) { .colophon-top { grid-template-columns: 1fr auto auto; gap: 3rem; align-items: start; } }
.colophon-col { display: grid; gap: 0.7rem; align-content: start; }
.colophon-head { font-family: var(--mono); font-size: 0.72rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--text-3); margin: 0 0 0.2rem; }
.colophon-col a { color: var(--text-2); text-decoration: none; }
.colophon-col a:hover { color: var(--gold); }
.colophon-brand { display: grid; gap: 0.9rem; align-content: start; max-width: 22rem; }
.colophon-brand p { margin: 0; color: var(--text-3); }
.colophon-mail { font-family: var(--mono); font-size: 0.86rem; letter-spacing: 0.05em; color: var(--text-2); text-decoration-color: var(--hair-2); }
.colophon-mail:hover { color: var(--gold); }
.colophon a { color: var(--text-3); }
.colophon a:hover { color: var(--gold); }
.colophon-base { display: flex; flex-wrap: wrap; gap: 0.4rem 1.5rem; justify-content: space-between; border-top: 1px solid var(--hair); padding-top: 1.6rem; font-family: var(--mono); font-size: 0.78rem; letter-spacing: 0.07em; text-transform: uppercase; }
.colophon-base p { margin: 0; }

.skip { position: absolute; left: -9999px; }
.skip:focus { left: 0.9rem; top: 0.9rem; z-index: 60; background: var(--gold); color: #1a1200; padding: 0.6rem 1rem; border-radius: 8px; }

/* ───────────────────────── motion ───────────────────────── */

/* Hidden only once the reveal script has announced itself on <html>. Without
   JavaScript — or if it fails to load — every .rise element is simply visible,
   which is the state that matters. Content must never depend on a script to
   exist. */
.js .rise { opacity: 0; transform: translateY(22px); transition: opacity 0.9s var(--t), transform 0.9s var(--t); }
.js .rise.is-in { opacity: 1; transform: none; }
.rise[data-delay="1"] { transition-delay: 0.09s; }
.rise[data-delay="2"] { transition-delay: 0.18s; }
.rise[data-delay="3"] { transition-delay: 0.27s; }
.rise[data-delay="4"] { transition-delay: 0.36s; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .rise { opacity: 1; transform: none; transition: none; }
  *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; }
}

.gone { padding-block: clamp(4rem, 10vw, 8rem); }
.gone h1 { margin: 0 0 1.25rem; }
.gone-list { list-style: none; padding: 0; margin: 2rem 0 0; display: flex; flex-wrap: wrap; gap: 0.6rem; }
.gone-list a {
  display: inline-block; padding: 0.5rem 1rem; border-radius: 999px;
  border: 1px solid var(--hair); color: var(--text-2); text-decoration: none;
  transition: color 0.2s var(--t), border-color 0.2s var(--t);
}
.gone-list a:hover { color: var(--text); border-color: var(--hair-2); }
