/* ==========================================================================
   Light Tap — design system and site styles
   --------------------------------------------------------------------------
   One idea organises this file: light is a material, not decoration. The page
   is unlit by default and brightness is spent only where it carries meaning.

   The strictest rule: RED IS ONLY EVER A TRAP. It is never a hover state,
   never an error colour, never an accent. The rule of the game is the rule of
   the design system.

   Layer order is declared once so component styles never have to out-specify
   anything above them.
   ========================================================================== */

@layer reset, tokens, base, layout, components, utilities;

/* --------------------------------------------------------------------------
   Reset
   -------------------------------------------------------------------------- */
@layer reset {
  *,
  *::before,
  *::after {
    box-sizing: border-box;
  }

  * {
    margin: 0;
  }

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

  body {
    min-height: 100svh;
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
  }

  img,
  picture,
  video,
  canvas,
  svg {
    display: block;
    max-width: 100%;
    height: auto;
  }

  input,
  button,
  textarea,
  select {
    font: inherit;
    color: inherit;
  }

  button {
    background: none;
    border: 0;
    padding: 0;
    cursor: pointer;
  }

  p,
  h1,
  h2,
  h3,
  h4 {
    overflow-wrap: break-word;
  }

  ul[role="list"],
  ol[role="list"] {
    list-style: none;
    padding: 0;
  }

  html,
  body {
    overflow-x: clip;
  }
}

/* --------------------------------------------------------------------------
   Tokens
   -------------------------------------------------------------------------- */
@layer tokens {
  :root {
    /* -- Surfaces ------------------------------------------------------- */
    --ink: #08070c;
    --ink-raised: #0e0d14;
    --ink-overlay: #15141c;

    /* -- Hairlines ------------------------------------------------------ */
    --line: rgb(255 255 255 / 0.08);
    --line-strong: rgb(255 255 255 / 0.16);

    /* -- Text ----------------------------------------------------------- */
    --text: #f4f3f7;
    --text-secondary: rgb(244 243 247 / 0.64);
    --text-muted: rgb(244 243 247 / 0.44);

    /* -- Light -----------------------------------------------------------
       Two accents and one warning. `--live` is the light you are meant to
       reach; `--gold` marks progression and figures; `--trap` is red and is
       used for nothing except a trap light. ------------------------------ */
    --live: #63d2ff;
    --live-dim: rgb(99 210 255 / 0.16);
    --gold: #ffc24b;
    --gold-dim: rgb(255 194 75 / 0.14);
    --trap: #ff3b4e;
    --trap-dim: rgb(255 59 78 / 0.18);

    --on-light: #08070c;
    --focus-ring: #f4f3f7;

    /* -- Type ----------------------------------------------------------- */
    --font-sans:
      -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial,
      sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
    --font-mono:
      ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

    /* Fluid scale, 390px → 1440px */
    --step--2: clamp(0.72rem, 0.71rem + 0.06vw, 0.76rem);
    --step--1: clamp(0.83rem, 0.81rem + 0.09vw, 0.88rem);
    --step-0: clamp(1rem, 0.97rem + 0.14vw, 1.06rem);
    --step-1: clamp(1.2rem, 1.14rem + 0.3vw, 1.38rem);
    --step-2: clamp(1.44rem, 1.32rem + 0.55vw, 1.79rem);
    --step-3: clamp(1.73rem, 1.53rem + 0.94vw, 2.33rem);
    --step-4: clamp(2.07rem, 1.75rem + 1.5vw, 3.03rem);
    --step-5: clamp(2.49rem, 1.99rem + 2.31vw, 3.94rem);
    --step-6: clamp(2.99rem, 2.24rem + 3.46vw, 5.12rem);

    /* -- Space ---------------------------------------------------------- */
    --space-3xs: 0.25rem;
    --space-2xs: 0.5rem;
    --space-xs: 0.75rem;
    --space-s: 1rem;
    --space-m: 1.5rem;
    --space-l: 2rem;
    --space-xl: 3rem;
    --space-2xl: 4.5rem;
    --space-3xl: 7rem;
    --space-4xl: 10rem;

    /* -- Layout --------------------------------------------------------- */
    --measure: 62ch;
    --measure-tight: 46ch;
    --width-content: 72rem;
    --width-prose: 44rem;
    --gutter: clamp(1.25rem, 0.85rem + 2vw, 2.75rem);
    --section-space: clamp(4.5rem, 3rem + 7vw, 9rem);

    /* -- Radii ---------------------------------------------------------- */
    --radius-s: 6px;
    --radius-m: 14px;
    --radius-l: 24px;
    --radius-pill: 999px;

    /* -- Glow -----------------------------------------------------------
       Light bleeds; it does not sit inside a border. --------------------- */
    --glow-live: 0 0 24px rgb(99 210 255 / 0.45), 0 0 64px rgb(99 210 255 / 0.18);
    --glow-trap: 0 0 22px rgb(255 59 78 / 0.42), 0 0 58px rgb(255 59 78 / 0.16);
    --glow-gold: 0 0 22px rgb(255 194 75 / 0.34);
    --shadow-raised: 0 24px 60px -32px rgb(0 0 0 / 0.9);

    /* -- Motion --------------------------------------------------------- */
    --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
    --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
    --fast: 180ms;
    --base: 280ms;
    --slow: 450ms;

    /* -- Breakpoints (documentation; media queries cannot read these) ----
       phone  < 640px      tablet 640–1023px      desktop >= 1024px       */
  }

  /* A reader who asks for less movement gets a complete static page, not a
     half-finished one: reveals resolve to their visible state. */
  @media (prefers-reduced-motion: reduce) {
    :root {
      --fast: 1ms;
      --base: 1ms;
      --slow: 1ms;
    }

    *,
    *::before,
    *::after {
      animation-duration: 1ms !important;
      animation-iteration-count: 1 !important;
      transition-duration: 1ms !important;
      scroll-behavior: auto !important;
    }
  }
}

/* --------------------------------------------------------------------------
   Base
   -------------------------------------------------------------------------- */
@layer base {
  html {
    color-scheme: dark;
    scroll-behavior: smooth;
    scroll-padding-top: 5rem;
  }

  html {
    background-color: var(--ink);
  }

  body {
    background-color: transparent;
    color: var(--text-secondary);
    font-family: var(--font-sans);
    font-size: var(--step-0);
  }

  h1,
  h2,
  h3,
  h4 {
    color: var(--text);
    font-weight: 600;
    line-height: 1.05;
    letter-spacing: -0.028em;
    text-wrap: balance;
  }

  h1 {
    font-size: var(--step-6);
  }
  h2 {
    font-size: var(--step-4);
  }
  h3 {
    font-size: var(--step-1);
    line-height: 1.2;
    letter-spacing: -0.018em;
  }
  h4 {
    font-size: var(--step-0);
    line-height: 1.3;
    letter-spacing: -0.01em;
  }

  p {
    text-wrap: pretty;
  }

  a {
    color: var(--text);
    text-underline-offset: 0.22em;
    text-decoration-thickness: from-font;
    transition: color var(--fast) ease;
  }

  a:hover {
    color: var(--live);
  }

  :focus-visible {
    outline: 2px solid var(--focus-ring);
    outline-offset: 3px;
    border-radius: var(--radius-s);
  }

  ::selection {
    background-color: var(--live);
    color: var(--on-light);
  }

  hr {
    border: 0;
    border-top: 1px solid var(--line);
  }
}

/* --------------------------------------------------------------------------
   Layout
   -------------------------------------------------------------------------- */
@layer layout {
  .page {
    display: flex;
    flex-direction: column;
    min-height: 100svh;
  }

  .page > main {
    flex: 1;
  }

  .shell {
    width: 100%;
    max-width: var(--width-content);
    margin-inline: auto;
    padding-inline: var(--gutter);
  }

  .shell--prose {
    max-width: var(--width-prose);
  }

  .section {
    padding-block: var(--section-space);
    border-block-start: 1px solid var(--line);
  }

  .section--flush {
    border-block-start: 0;
  }

  .stack > * + * {
    margin-block-start: var(--flow, var(--space-m));
  }

  .visually-hidden:not(:focus):not(:active) {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  /* Zero-size anchor marking the true document start for #top. */
  #top {
    display: block;
    height: 0;
  }

  .skip-link {
    position: fixed;
    inset-block-start: -5rem;
    inset-inline-start: var(--space-s);
    z-index: 200;
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding-inline: var(--space-m);
    border-radius: var(--radius-pill);
    background-color: var(--text);
    color: var(--ink);
    font-size: var(--step--1);
    font-weight: 600;
    text-decoration: none;
    transition: inset-block-start var(--base) var(--ease-out);
  }

  .skip-link:focus {
    inset-block-start: var(--space-s);
    color: var(--ink);
  }
}

/* --------------------------------------------------------------------------
   Components
   -------------------------------------------------------------------------- */
@layer components {
  /* -- Section furniture ------------------------------------------------ */
  .eyebrow {
    display: flex;
    align-items: center;
    gap: var(--space-xs);
    margin-block-end: var(--space-m);
    color: var(--text-muted);
    font-family: var(--font-mono);
    font-size: var(--step--2);
    font-weight: 500;
    letter-spacing: 0.16em;
    text-transform: uppercase;
  }

  .eyebrow::before {
    content: "";
    flex: none;
    width: 1.5rem;
    height: 1px;
    background-color: var(--line-strong);
  }

  .lede {
    max-width: var(--measure);
    margin-block-start: var(--space-m);
    font-size: var(--step-1);
    line-height: 1.5;
    letter-spacing: -0.012em;
    color: var(--text-secondary);
  }

  .section__head {
    max-width: 46rem;
  }

  /* -- Buttons ----------------------------------------------------------- */
  .btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2xs);
    min-height: 48px;
    padding-inline: var(--space-l);
    border: 1px solid transparent;
    border-radius: var(--radius-pill);
    font-size: var(--step--1);
    font-weight: 600;
    letter-spacing: -0.005em;
    text-decoration: none;
    white-space: nowrap;
    transition:
      background-color var(--fast) ease,
      border-color var(--fast) ease,
      color var(--fast) ease,
      transform var(--fast) var(--ease-out);
  }

  .btn:active {
    transform: translateY(1px);
  }

  .btn--primary {
    background-color: var(--text);
    color: var(--on-light);
  }

  .btn--primary:hover,
  .btn--primary:focus-visible {
    background-color: #fff;
    color: var(--on-light);
  }

  .btn--ghost {
    border-color: var(--line-strong);
    color: var(--text);
  }

  .btn--ghost:hover,
  .btn--ghost:focus-visible {
    border-color: var(--text);
    background-color: rgb(255 255 255 / 0.04);
    color: var(--text);
  }

  /* The store link does not exist yet. This is a real, honest state rather
     than a disabled-looking link that goes nowhere. */
  .btn--soon {
    border-color: var(--line-strong);
    background-color: rgb(255 255 255 / 0.03);
    color: var(--text-secondary);
    cursor: default;
  }

  .btn--soon:active {
    transform: none;
  }

  .btn__dot {
    flex: none;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background-color: var(--gold);
    box-shadow: var(--glow-gold);
  }

  .btn-row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-s);
    margin-block-start: var(--space-xl);
  }

  /* -- Header ------------------------------------------------------------
     Sits in the page rather than floating over it: no pill, no shadow, one
     hairline. It only gains a background once the reader has left the top. */
  .site-header {
    position: sticky;
    inset-block-start: 0;
    z-index: 100;
    border-block-end: 1px solid transparent;
    transition:
      background-color var(--base) ease,
      border-color var(--base) ease,
      backdrop-filter var(--base) ease;
  }

  .site-header[data-lifted="true"] {
    background-color: rgb(8 7 12 / 0.72);
    border-block-end-color: var(--line);
    backdrop-filter: saturate(1.4) blur(16px);
    -webkit-backdrop-filter: saturate(1.4) blur(16px);
  }

  .site-header__inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-m);
    min-height: 4.5rem;
  }

  .wordmark {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2xs);
    color: var(--text);
    font-size: var(--step-0);
    font-weight: 600;
    letter-spacing: -0.02em;
    text-decoration: none;
  }


  .site-header__end {
    display: flex;
    align-items: center;
    gap: var(--space-s);
  }

  /* -- Language switcher --------------------------------------------------
     Two plain links, so it works with JavaScript off and reads correctly to a
     screen reader: the active language is a <span aria-current>, the other is
     an anchor to the equivalent page. No flags, no dropdown. */
  .lang-switch {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-family: var(--font-mono);
    font-size: var(--step--2);
    letter-spacing: 0.1em;
  }

  .lang-switch__item {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 2.25rem;
    min-height: 2.25rem;
    border-radius: var(--radius-s);
    color: var(--text-muted);
    text-decoration: none;
    transition: color var(--fast) ease, background-color var(--fast) ease;
  }

  .lang-switch__item abbr {
    text-decoration: none;
    border: 0;
  }

  .lang-switch__item[aria-current="true"] {
    color: var(--text);
  }

  a.lang-switch__item:hover,
  a.lang-switch__item:focus-visible {
    color: var(--text);
    background-color: rgb(255 255 255 / 0.06);
  }

  .lang-switch__sep {
    color: var(--line-strong);
  }

  .site-nav {
    display: none;
  }

  .site-nav__list {
    display: flex;
    align-items: center;
    gap: var(--space-l);
    margin: 0;
    padding: 0;
    list-style: none;
  }

  .site-nav__list a {
    position: relative;
    color: var(--text-secondary);
    font-size: var(--step--1);
    text-decoration: none;
  }

  .site-nav__list a::after {
    content: "";
    position: absolute;
    inset-inline: 0;
    inset-block-end: -6px;
    height: 1px;
    background-color: currentColor;
    transform: scaleX(0);
    transform-origin: left center;
    transition: transform var(--base) var(--ease-out);
    pointer-events: none;
  }

  .site-nav__list a:hover,
  .site-nav__list a:focus-visible {
    color: var(--text);
  }

  .site-nav__list a:hover::after,
  .site-nav__list a:focus-visible::after {
    transform: scaleX(1);
  }

  /* -- Drawer ------------------------------------------------------------ */
  .nav-toggle {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 5px;
    width: 44px;
    height: 44px;
    margin-inline-end: -0.5rem;
  }

  .nav-toggle__bar {
    width: 20px;
    height: 1.5px;
    border-radius: 2px;
    background-color: var(--text);
    transition: transform var(--base) var(--ease-out), opacity var(--fast) ease;
  }

  .nav-toggle[aria-expanded="true"] .nav-toggle__bar:first-child {
    transform: translateY(3.25px) rotate(45deg);
  }

  .nav-toggle[aria-expanded="true"] .nav-toggle__bar:last-child {
    transform: translateY(-3.25px) rotate(-45deg);
  }

  .drawer {
    position: fixed;
    inset: 0;
    z-index: 150;
    display: grid;
    grid-template-rows: auto 1fr;
    background-color: rgb(8 7 12 / 0.96);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    opacity: 0;
    visibility: hidden;
    transition:
      opacity var(--base) ease,
      visibility var(--base);
  }

  .drawer[data-open="true"] {
    opacity: 1;
    visibility: visible;
  }

  .drawer__top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-m);
    min-height: 4.5rem;
  }

  .drawer__list {
    display: flex;
    flex-direction: column;
    margin: 0;
    padding: 0;
    list-style: none;
  }

  .drawer__list a {
    display: block;
    padding-block: var(--space-m);
    border-block-start: 1px solid var(--line);
    color: var(--text);
    font-size: var(--step-2);
    letter-spacing: -0.02em;
    text-decoration: none;
  }

  .drawer__list li:last-child a {
    border-block-end: 1px solid var(--line);
  }

  .drawer__foot {
    margin-block-start: var(--space-xl);
  }

  /* -- Ambient light ------------------------------------------------------
     One fixed pool of light for the whole document. It eases toward the
     scroll position and leans slightly toward the pointer, so the page feels
     lit from somewhere rather than painted flat.

     Deliberately slow and low in contrast: this is atmosphere, and rapid
     brightness change is exactly what the photosensitivity notice warns
     about. It sits behind everything and takes no pointer events. */
  .ambient {
    position: fixed;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    background: radial-gradient(
      42rem 42rem at var(--amb-x, 50%) var(--amb-y, 28%),
      rgb(99 210 255 / 0.075) 0%,
      rgb(255 122 26 / 0.032) 45%,
      rgb(8 7 12 / 0) 72%
    );
  }

  /* -- Hero -------------------------------------------------------------- */
  .hero {
    position: relative;
    padding-block: clamp(3.5rem, 2rem + 8vw, 7rem) var(--section-space);
    overflow: clip;
  }

  .hero__inner {
    position: relative;
    z-index: 1;
    display: grid;
    gap: var(--space-2xl);
  }

  .hero__title {
    max-width: 16ch;
  }

  .hero__line {
    display: block;
    overflow: hidden;
  }

  .hero__line > span {
    display: block;
    animation: line-rise 900ms var(--ease-out) both;
    animation-delay: calc(var(--line, 0) * 110ms);
  }

  .hero__line:last-child > span {
    color: var(--text-secondary);
  }

  @keyframes line-rise {
    from {
      transform: translateY(100%);
      opacity: 0;
    }
    to {
      transform: translateY(0);
      opacity: 1;
    }
  }

  .hero__note {
    margin-block-start: var(--space-l);
    color: var(--text-muted);
    font-size: var(--step--1);
  }

  /* -- Hero stage --------------------------------------------------------
     Portrait, because Light Tap is a portrait iPhone game. The object is the
     real app icon; everything around it is light, not chrome. No border, no
     card, no invented device frame. */
  .hero-stage {
    position: relative;
    display: grid;
    place-items: center;
    width: min(100%, 24rem);
    margin-inline: auto;
    aspect-ratio: 4 / 5;
    isolation: isolate;
  }

  /* The pool the icon sits in. Slow, wide and low-contrast: atmosphere, not
     a strobe. */
  .hero-stage::before {
    content: "";
    position: absolute;
    z-index: -1;
    inset: -18% -22%;
    background: radial-gradient(
      50% 44% at 50% 50%,
      rgb(99 210 255 / 0.16) 0%,
      rgb(255 122 26 / 0.07) 42%,
      rgb(8 7 12 / 0) 72%
    );
    animation: stage-breathe 14s var(--ease-in-out) infinite;
  }

  @keyframes stage-breathe {
    0%,
    100% {
      opacity: 0.75;
      transform: scale(1);
    }
    50% {
      opacity: 1;
      transform: scale(1.06);
    }
  }

  /* The icon leans a few degrees toward the pointer on fine-pointer devices;
     --tilt-x/--tilt-y are written by the motion module and default to rest. */
  .app-icon {
    width: min(72%, 17rem);
    border-radius: 22.5%;
    box-shadow:
      0 40px 90px -30px rgb(0 0 0 / 0.85),
      0 0 70px -10px rgb(99 210 255 / 0.22);
    transform: perspective(900px) rotateX(var(--tilt-x, 0deg))
      rotateY(var(--tilt-y, 0deg)) translateZ(0);
    transition: transform var(--slow) var(--ease-out);
    will-change: transform;
  }

  /* Suspended in light: a slow drift, barely a degree of rotation and a
     breath of scale. Nine seconds per cycle, so nothing reads as an
     animation — and no brightness change, which keeps it clear of the
     photosensitivity guidance. It sits on the <picture> wrapper so it never
     fights the pointer tilt on the <img>. */
  .hero-stage picture {
    animation: icon-float 9s var(--ease-in-out) infinite;
    will-change: transform;
  }

  @keyframes icon-float {
    0%,
    100% {
      transform: translateY(-4px) rotate(-0.6deg) scale(1);
    }
    50% {
      transform: translateY(4px) rotate(0.6deg) scale(1.015);
    }
  }

  .app-icon--mark {
    width: 1.5rem;
    border-radius: 24%;
    box-shadow: none;
    transform: none;
  }

  @media (prefers-reduced-motion: reduce) {
    .hero-stage::before {
      animation: none;
      opacity: 0.9;
    }
    .hero-stage picture {
      animation: none;
      transform: none;
    }
    .app-icon {
      transform: none;
    }
  }

  /* -- The rule ---------------------------------------------------------- */
  .rules {
    display: grid;
    gap: var(--space-l);
    margin-block-start: var(--space-2xl);
    counter-reset: rule;
  }

  .rule {
    padding-block-start: var(--space-m);
    border-block-start: 1px solid var(--line);
  }

  .rule__index {
    display: block;
    margin-block-end: var(--space-s);
    color: var(--text-muted);
    font-family: var(--font-mono);
    font-size: var(--step--2);
    letter-spacing: 0.14em;
  }

  .rule h3 {
    margin-block-end: var(--space-2xs);
  }

  .rule p {
    max-width: var(--measure-tight);
    color: var(--text-secondary);
    font-size: var(--step--1);
    line-height: 1.65;
  }

  /* A single dot per rule, coloured to match what the rule is about. */
  .rule__dot {
    display: inline-block;
    width: 7px;
    height: 7px;
    margin-inline-end: 0.55rem;
    border-radius: 50%;
    vertical-align: 0.12em;
  }

  .rule__dot--live {
    background-color: var(--live);
    box-shadow: var(--glow-live);
  }
  .rule__dot--trap {
    background-color: var(--trap);
    box-shadow: var(--glow-trap);
  }
  .rule__dot--gold {
    background-color: var(--gold);
    box-shadow: var(--glow-gold);
  }

  /* -- Modes ------------------------------------------------------------- */
  .modes {
    margin-block-start: var(--space-2xl);
  }

  .mode {
    display: grid;
    gap: var(--space-2xs) var(--space-xl);
    padding-block: var(--space-l);
    border-block-start: 1px solid var(--line);
  }

  .modes > .mode:last-child {
    border-block-end: 1px solid var(--line);
  }

  .mode__index {
    color: var(--text-muted);
    font-family: var(--font-mono);
    font-size: var(--step--2);
    letter-spacing: 0.14em;
  }

  .mode__name {
    font-size: var(--step-2);
    letter-spacing: -0.022em;
  }

  .mode__line {
    max-width: var(--measure);
    color: var(--text-secondary);
    font-size: var(--step--1);
    line-height: 1.65;
  }

  /* -- Figures ------------------------------------------------------------
     Numbers support the story; they are not a dashboard. Tabular numerals
     keep the row optically aligned. */
  .figures {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-xl) var(--space-l);
    margin-block-start: var(--space-2xl);
  }

  .figure__value {
    display: block;
    color: var(--text);
    font-family: var(--font-mono);
    font-size: var(--step-3);
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.03em;
    line-height: 1;
  }

  .figure__label {
    display: block;
    margin-block-start: var(--space-2xs);
    color: var(--text-muted);
    font-family: var(--font-mono);
    font-size: var(--step--2);
    letter-spacing: 0.14em;
    text-transform: uppercase;
  }

  /* -- Panels (Challenge, Connected, Fair) --------------------------------
     Columns under a hairline rather than cards. A page of bordered boxes
     reads like a dashboard; the rule plus the whitespace is enough. */
  .panel {
    padding-block-start: var(--space-m);
    border-block-start: 1px solid var(--line);
  }

  .panel h3 {
    margin-block-end: var(--space-xs);
  }

  .panel p {
    max-width: var(--measure);
    color: var(--text-secondary);
    font-size: var(--step--1);
    line-height: 1.65;
  }

  .panel-grid {
    display: grid;
    gap: var(--space-xl);
    margin-block-start: var(--space-2xl);
  }

  .spec-list {
    margin: 0;
    padding: 0;
  }

  .spec-list div {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2xs) var(--space-m);
    justify-content: space-between;
    padding-block: var(--space-xs);
    border-block-start: 1px solid var(--line);
  }

  .spec-list div:first-child {
    border-block-start: 0;
  }

  .spec-list dt {
    color: var(--text-secondary);
    font-size: var(--step--1);
  }

  .spec-list dd {
    margin: 0;
    color: var(--text);
    font-family: var(--font-mono);
    font-size: var(--step--1);
    font-variant-numeric: tabular-nums;
  }

  /* -- Safety notice ------------------------------------------------------
     Understated by design. It is information a reader deserves before they
     play, not a warning banner shouting at them. */
  .notice {
    display: grid;
    gap: var(--space-s);
    padding-inline-start: var(--space-l);
    border-inline-start: 2px solid var(--gold);
  }

  .notice h2 {
    font-size: var(--step-1);
    letter-spacing: -0.018em;
  }

  .notice p {
    max-width: var(--measure);
    font-size: var(--step--1);
    line-height: 1.7;
  }

  .notice p + p {
    margin-block-start: var(--space-s);
  }

  /* -- Contact ------------------------------------------------------------ */
  .contact-grid {
    display: grid;
    gap: var(--space-l);
    margin-block-start: var(--space-2xl);
  }

  .contact-card {
    padding-block-start: var(--space-m);
    border-block-start: 1px solid var(--line);
  }

  .contact-card h3 {
    margin-block-end: var(--space-2xs);
  }

  .contact-card p {
    max-width: var(--measure-tight);
    color: var(--text-secondary);
    font-size: var(--step--1);
    line-height: 1.65;
  }

  .contact-address {
    margin-block-start: var(--space-xl);
    font-style: normal;
  }

  .placeholder {
    color: var(--gold);
    font-family: var(--font-mono);
    font-size: 0.95em;
  }

  /* -- Footer ------------------------------------------------------------- */
  .site-footer {
    border-block-start: 1px solid var(--line);
    padding-block: var(--space-2xl) var(--space-l);
    color: var(--text-muted);
    font-size: var(--step--1);
  }

  .site-footer__top {
    display: grid;
    gap: var(--space-xl);
  }

  .site-footer__blurb {
    max-width: 24rem;
    color: var(--text-muted);
    font-size: var(--step--1);
    line-height: 1.65;
  }

  .footer-nav {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-l);
  }

  .footer-nav h2 {
    margin-block-end: var(--space-s);
    color: var(--text-muted);
    font-family: var(--font-mono);
    font-size: var(--step--2);
    font-weight: 500;
    letter-spacing: 0.14em;
    text-transform: uppercase;
  }

  .footer-nav ul {
    display: grid;
    gap: var(--space-2xs);
    margin: 0;
    padding: 0;
    list-style: none;
  }

  .footer-nav a {
    color: var(--text-secondary);
    text-decoration: none;
  }

  .footer-nav a:hover,
  .footer-nav a:focus-visible {
    color: var(--text);
  }

  /* The footer brand is a link home; give it a state worth the click. */
  .wordmark--footer {
    display: inline-flex;
    padding: var(--space-2xs);
    margin: calc(var(--space-2xs) * -1);
    border-radius: var(--radius-m);
    transition: background-color var(--fast) ease;
  }

  .wordmark--footer:hover,
  .wordmark--footer:focus-visible {
    background-color: rgb(255 255 255 / 0.05);
    color: var(--text);
  }

  .wordmark--footer:hover .app-icon,
  .wordmark--footer:focus-visible .app-icon {
    transform: translateY(-1px);
  }

  /* -- Back to top --------------------------------------------------------
     A same-page anchor, nothing more. Smooth scrolling comes from
     `scroll-behavior` and reduced motion turns it into an instant jump, so
     there is no script and no scroll listener behind it. */
  .to-top {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2xs);
    min-height: 44px;
    padding-inline: var(--space-s);
    margin-inline-end: calc(var(--space-s) * -1);
    border-radius: var(--radius-pill);
    color: var(--text-muted);
    font-size: var(--step--2);
    text-decoration: none;
    transition: color var(--fast) ease, background-color var(--fast) ease;
  }

  .to-top:hover,
  .to-top:focus-visible {
    color: var(--text);
    background-color: rgb(255 255 255 / 0.05);
  }

  .to-top__arrow {
    display: inline-block;
    transition: transform var(--base) var(--ease-out);
  }

  .to-top:hover .to-top__arrow,
  .to-top:focus-visible .to-top__arrow {
    transform: translateY(-2px);
  }

  .site-footer__bottom {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2xs) var(--space-m);
    justify-content: space-between;
    margin-block-start: var(--space-2xl);
    padding-block-start: var(--space-m);
    border-block-start: 1px solid var(--line);
    font-size: var(--step--2);
  }

  .site-footer__disclosure {
    max-width: 46rem;
    margin-block-start: var(--space-m);
    color: var(--text-muted);
    font-size: var(--step--2);
    line-height: 1.7;
  }

  /* -- Legal and support prose -------------------------------------------
     Calmer than the homepage: narrower measure, more air, no accents beyond
     the section rules. */
  .doc-header {
    padding-block: var(--space-2xl) var(--space-xl);
  }

  .doc-header h1 {
    font-size: var(--step-4);
  }

  .doc-meta {
    margin-block-start: var(--space-s);
    color: var(--text-muted);
    font-family: var(--font-mono);
    font-size: var(--step--2);
    letter-spacing: 0.1em;
    text-transform: uppercase;
  }

  .doc {
    padding-block-end: var(--space-4xl);
  }

  /* Any section needs air above it, including the first one after a loose
     intro paragraph — not only sections that follow another section. */
  .doc > * + section {
    margin-block-start: var(--space-2xl);
  }

  .doc h2 {
    margin-block-end: var(--space-s);
    font-size: var(--step-2);
    letter-spacing: -0.02em;
  }

  .doc h3 {
    margin-block: var(--space-l) var(--space-2xs);
    font-size: var(--step-0);
    color: var(--text);
  }

  .doc p,
  .doc li {
    max-width: var(--measure);
    line-height: 1.75;
  }

  .doc p + p,
  .doc ul + p,
  .doc p + ul {
    margin-block-start: var(--space-s);
  }

  .doc ul {
    margin-block-start: var(--space-s);
    padding-inline-start: 1.15rem;
    display: grid;
    gap: var(--space-3xs);
  }

  .doc li::marker {
    color: var(--text-muted);
  }

  .doc a {
    color: var(--text);
    text-decoration: underline;
    text-decoration-color: var(--line-strong);
  }

  .doc a:hover {
    color: var(--live);
    text-decoration-color: currentColor;
  }

  .doc__toc {
    margin-block: var(--space-l) var(--space-2xl);
    padding: var(--space-m) var(--space-l);
    border: 1px solid var(--line);
    border-radius: var(--radius-m);
    background-color: var(--ink-raised);
  }

  .doc__toc h2 {
    margin-block-end: var(--space-s);
    color: var(--text-muted);
    font-family: var(--font-mono);
    font-size: var(--step--2);
    font-weight: 500;
    letter-spacing: 0.14em;
    text-transform: uppercase;
  }

  .doc__toc ol {
    display: grid;
    gap: var(--space-3xs);
    margin: 0;
    padding-inline-start: 1.35rem;
    font-size: var(--step--1);
  }

  .doc__toc a {
    text-decoration: none;
    color: var(--text-secondary);
  }

  .doc__toc a:hover,
  .doc__toc a:focus-visible {
    color: var(--text);
  }
}

/* --------------------------------------------------------------------------
   Utilities
   -------------------------------------------------------------------------- */
@layer utilities {
  .flow-s {
    --flow: var(--space-s);
  }
  .flow-l {
    --flow: var(--space-l);
  }

  .text-muted {
    color: var(--text-muted);
  }

  .no-wrap {
    white-space: nowrap;
  }

  /* Reveal on scroll.
     --------------------------------------------------------------------
     Content visibility must never depend on JavaScript, so the hidden state
     is fenced three ways:

     1. `.js-reveal` is added by an inline head script, so no JavaScript at
        all means nothing is ever hidden.
     2. That same inline script arms a timer which removes `.js-reveal`
        again — if the module fails to load, throws, or never observes
        anything, every element becomes visible on its own.
     3. `:not([data-reveal="shown"])` puts the escape inside the selector
        rather than in a second rule. An earlier version used a separate
        `[data-reveal="shown"]` rule, which lost on specificity (0,1,0
        against 0,2,0) and left the whole page at opacity 0 permanently. */
  .js-reveal [data-reveal]:not([data-reveal="shown"]) {
    opacity: 0;
    translate: 0 16px;
    filter: blur(5px);
  }

  [data-reveal] {
    transition:
      opacity var(--slow) var(--ease-out),
      translate var(--slow) var(--ease-out),
      filter var(--slow) var(--ease-out);
    transition-delay: var(--reveal-delay, 0ms);
  }

  @media (prefers-reduced-motion: reduce) {
    .js-reveal [data-reveal]:not([data-reveal="shown"]) {
      opacity: 1;
      translate: none;
      filter: none;
    }
  }

  /* No JavaScript: the drawer can never open, so the toggle is removed and the
     link row is shown inline instead. Navigation still works at every width. */
  .no-js .nav-toggle,
  .no-js .drawer {
    display: none;
  }

  .no-js .site-nav {
    display: block;
  }

  .no-js .site-nav__list {
    flex-wrap: wrap;
    gap: var(--space-2xs) var(--space-m);
  }

  .no-js .site-header__inner {
    flex-wrap: wrap;
    padding-block: var(--space-s);
  }
}

/* ==========================================================================
   Responsive — three designed layouts, not one scaled three ways
   ========================================================================== */

/* -- Tablet ---------------------------------------------------------------- */
@media (min-width: 40rem) {
  @layer components {
    .rules {
      grid-template-columns: repeat(3, minmax(0, 1fr));
      gap: var(--space-l);
    }

    .mode {
      grid-template-columns: 3rem minmax(0, 12rem) minmax(0, 1fr);
      align-items: baseline;
    }

    .figures {
      grid-template-columns: repeat(4, minmax(0, 1fr));
    }

    .panel-grid {
      grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .contact-grid {
      grid-template-columns: repeat(3, minmax(0, 1fr));
    }

    .notice {
      grid-template-columns: minmax(0, 16rem) minmax(0, 1fr);
      gap: var(--space-xl);
    }

    .site-footer__top {
      grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr);
      gap: var(--space-2xl);
    }

    .footer-nav {
      grid-template-columns: repeat(3, minmax(0, 1fr));
    }
  }
}

/* -- Desktop --------------------------------------------------------------- */
@media (min-width: 64rem) {
  @layer components {
    .nav-toggle,
    .drawer {
      display: none;
    }

    .site-nav {
      display: block;
    }

    /* The hero becomes asymmetric: language on the left, the board on the
       right, weighted so the type still leads. */
    .hero__inner {
      grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
      align-items: center;
      /* Fixed 10rem starved the copy column at 1024 and wrapped the buttons;
         the gap now yields space back as the viewport narrows. */
      gap: clamp(3rem, 6vw, 10rem);
    }

    /* The hero icon is 20% larger on desktop only; the stage grows with it
       so the portrait proportion and the surrounding light stay balanced.
       Tablet and phone keep the smaller icon on purpose — at those widths a
       larger one pushes the copy off the first screen. */
    .hero-stage {
      width: min(100%, 29rem);
      margin-inline: auto 0;
    }

    .app-icon--hero {
      width: min(80%, 20.4rem);
    }

    .section__head {
      max-width: 52rem;
    }

    .mode {
      grid-template-columns: 4rem minmax(0, 14rem) minmax(0, 1fr);
      padding-block: var(--space-xl);
    }

    .panel-grid--three {
      grid-template-columns: repeat(3, minmax(0, 1fr));
    }


    .doc-header {
      padding-block: var(--space-3xl) var(--space-xl);
    }
  }
}

/* -- Wide ------------------------------------------------------------------ */
@media (min-width: 90rem) {
  @layer tokens {
    :root {
      --width-content: 78rem;
    }
  }
}
