/* Cargo Tilt — one stylesheet. No framework, no web fonts, no trackers.
   Visual language: design/ART_DIRECTION_V2.md — glossy toy harbour.

   THE PAGE IS LIGHT, ON PURPOSE, IN EVERY SYSTEM SETTING.
   This site is a poster for a game whose whole world is a sunny harbour at
   midday: saturated sky, warm key light, blue water. A dark variant of that
   poster is not a courtesy, it is a different product — the page spent its
   first round fighting its own app icon in exactly that way. Posters do not
   invert, so `color-scheme: light` is declared once and there is no
   prefers-color-scheme branch anywhere below. Contrast is carried by the
   palette (every pair checked at AA or better), not by darkness.

   Colours are measured off the founder's reference icon
   (art/out/icon/v2/icon_1024.png) and the game palette (art/compose/palette.py).
   The hero is two Cycles-composited bitmaps from art/compose/web_hero.py; the
   heel that ties them together lives at the bottom of this file. */

:root {
  color-scheme: light;

  /* --- the harbour, measured off the icon ------------------------------ */
  --sky-hi:    #EAF7FF;
  --sky-mid:   #CDECFE;
  --sky-low:   #AFE2FC;
  --sea:       #018EDC;
  --sea-deep:  #0B67AF;
  --sea-ink:   #043F72;
  --hull:      #10418B;
  --sun:       #FFD23D;
  --sun-warm:  #FFF3B8;
  --red:       #FE4529;

  /* --- page ------------------------------------------------------------ */
  --page:      #F3FAFF;
  --card:      #FFFFFF;
  --card-2:    #F0F8FE;
  --ink:       #0A2A50;   /* 14.0:1 on white */
  --ink-soft:  #37587A;   /*  7.3:1 on white */
  --line:      #C9E3F6;
  --link:      #0A5A9E;   /*  6.4:1 on white */
  --focus:     #0A4F8C;
  --on-sea:    #FFFFFF;
  --on-sea-soft:#DCEFFC;  /*  4.98:1 on --sea-deep */
  --on-sea-link:#CFEBFF;  /*  4.75:1 on --sea-deep */
  --alert:     #A8231B;   /*  6.6:1 on white */
  --alert-bg:  #FDECEA;

  --radius:    20px;
  --radius-s:  12px;
  --wrap:      68rem;

  /* the glossy-toy elevation: a tight contact shadow plus a soft ambient
     one, never a single flat drop shadow */
  --lift: 0 1px 0 rgba(255,255,255,.9) inset,
          0 1px 2px rgba(10,44,80,.10),
          0 10px 24px -12px rgba(10,44,80,.32);
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--page);
  color: var(--ink);
  font: 1rem/1.62 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
        "Helvetica Neue", Arial, sans-serif;
  overflow-wrap: break-word;
  overflow-x: hidden;   /* belt and braces: nothing here may scroll sideways */
}

.wrap { width: 100%; max-width: var(--wrap); margin-inline: auto; padding-inline: 1.15rem; }
img, svg { max-width: 100%; height: auto; }

a { color: var(--link); text-underline-offset: .18em; }
a:focus-visible, .skip:focus {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
  border-radius: 6px;
}

.skip {
  position: absolute; left: -9999px; top: 0;
  background: var(--card); color: var(--ink);
  padding: .6rem 1rem; z-index: 20; border-radius: 0 0 10px 0;
}
.skip:focus { left: 0; }

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

.site-head {
  background: rgba(255,255,255,.92);
  -webkit-backdrop-filter: saturate(150%) blur(8px);
  backdrop-filter: saturate(150%) blur(8px);
  border-bottom: 1px solid var(--line);
  position: sticky; top: 0; z-index: 10;
}
.head-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; min-height: 3.4rem;
}
.brand {
  display: inline-flex; align-items: center; gap: .6rem;
  font-weight: 800; font-size: 1.08rem; letter-spacing: -.01em;
  color: var(--ink); text-decoration: none; min-width: 0;
}
.brand img { border-radius: 8px; box-shadow: 0 1px 3px rgba(10,44,80,.28); flex: none; }
.lang-switch {
  font-size: .9rem; font-weight: 700; text-decoration: none; white-space: nowrap;
  color: var(--link);
  border: 1px solid var(--line); border-radius: 999px;
  padding: .34rem .9rem; background: var(--card-2);
}
.lang-switch:hover { border-color: var(--focus); }

.site-foot {
  background: var(--card);
  border-top: 1px solid var(--line);
  padding-block: 1.8rem 2.4rem;
  font-size: .92rem; color: var(--ink-soft);
}
.site-foot nav { display: flex; flex-wrap: wrap; gap: 1.3rem; margin-bottom: .85rem; }
.site-foot nav a { font-weight: 700; }
.site-foot p { margin: 0; max-width: 46rem; }

/* =====================================================================
   THE HERO — one composition, not a column of text with a picture under it.
   Copy and key art share a single grid row from 62rem up, so at a desktop
   width the title, the badges and the ship are one thing, above the fold.
   ===================================================================== */

.hero {
  position: relative;
  padding-block: 2.2rem 2.6rem;
  background:
    radial-gradient(46rem 26rem at 92% -16%, rgba(255,238,190,.92) 0%, rgba(255,238,190,0) 64%),
    linear-gradient(172deg, var(--sky-hi) 0%, var(--sky-mid) 58%, var(--sky-low) 100%);
  border-bottom: 1px solid #A9DCF7;
}
.hero-grid { display: grid; gap: 2rem; align-items: center; }
.hero-copy { min-width: 0; text-align: center; }

.hero-icon {
  display: block; margin: 0 auto .85rem;
  width: clamp(68px, 15vw, 88px); height: auto;
  border-radius: 22.37%;             /* the iOS squircle's nearest CSS cousin */
  box-shadow: 0 2px 4px rgba(6,32,62,.18), 0 14px 30px -12px rgba(6,32,62,.55);
}
.hero h1 {
  font-size: clamp(2.5rem, 8.5vw, 4rem);
  line-height: 1.0; letter-spacing: -.03em; font-weight: 800;
  margin: 0 0 .5rem; color: #08244A;
  text-shadow: 0 1px 0 rgba(255,255,255,.7);
}
.hero .tagline {
  font-size: clamp(1.08rem, 3.2vw, 1.35rem); font-weight: 700;
  color: #0B2E56; margin: 0 0 .85rem;
}
.hero .pitch {
  font-size: clamp(1rem, 2.4vw, 1.1rem);
  color: #12365F; margin: 0 auto 1.5rem; max-width: 32rem;
}
.hero-meta {
  margin: 1.1rem 0 0; font-size: .88rem; font-weight: 600;
  color: #1B4674; display: flex; flex-wrap: wrap; gap: .4rem .9rem;
  justify-content: center;
}
.hero-meta span { display: inline-flex; align-items: center; gap: .4rem; }
.hero-meta span::before {
  content: ""; width: .42rem; height: .42rem; border-radius: 50%;
  background: var(--sea-deep); flex: none;
}

/* ---------- store badges ----------
   Both are always drawn in full, at full contrast, whether or not there is
   somewhere to send the visitor. Only the wrapper changes: an <a> when
   site.config.json carries the listing URL, an inert <span> when it does not.
   Every colour and font in the artwork is a presentation attribute on the SVG
   itself (see build.py) — the stylesheet may fail and the badge still reads. */

.badges {
  display: flex; flex-wrap: wrap; gap: .7rem;
  justify-content: center; margin: 0;
}
.badge {
  display: inline-flex; border-radius: 9px; text-decoration: none; max-width: 100%;
  box-shadow: 0 1px 2px rgba(6,32,62,.22), 0 10px 22px -14px rgba(6,32,62,.7);
}
.badge .bg-art { display: block; height: 50px; width: auto; }
a.badge { transition: transform .18s ease, box-shadow .18s ease; }
a.badge:hover { transform: translateY(-2px);
                box-shadow: 0 2px 3px rgba(6,32,62,.26), 0 16px 26px -14px rgba(6,32,62,.8); }
a.badge:focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; }
/* no destination yet: identical artwork, nothing to click, nothing to focus */
.badge.is-idle { cursor: default; -webkit-user-select: none; user-select: none; }

/* ---------- the key art ----------
   Two Cycles-composited layers in one rounded plate: the harbour holds still
   and the loaded ship heels on her own waterline. */

.hero-art { margin: 0; min-width: 0; }
.scene {
  position: relative; aspect-ratio: 8 / 5;
  border-radius: 24px; overflow: hidden;
  background: #56BCFB;
  box-shadow: 0 2px 0 rgba(255,255,255,.5) inset,
              0 6px 14px -6px rgba(5,36,72,.35),
              0 30px 60px -30px rgba(5,36,72,.7);
}
.scene img {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover; display: block;
}
.scene-ship { transform-origin: 50.5% 74.5%; }   /* her waterline, from web_hero.py */

/* ---------- the tilt meter ----------
   The game's one piece of HUD, rebuilt in CSS so it stays crisp and stays in
   step with the heel above it. Decorative: the heading and the copy already
   say what it means, so it is hidden from assistive tech. */

.tilt {
  position: relative; height: 26px; margin: .9rem auto 0; max-width: 27rem;
  border-radius: 999px; padding: 4px;
  background: linear-gradient(180deg, #EAF6FF, #C8E4F6);
  box-shadow: 0 1px 0 rgba(255,255,255,.9) inset,
              0 2px 6px -2px rgba(6,32,62,.35);
}
.tilt-track {
  height: 100%; border-radius: 999px;
  background: linear-gradient(90deg,
    #E33B2C 0 14%, #F2A32A 14% 30%, #2FA85F 30% 70%,
    #F2A32A 70% 86%, #E33B2C 86% 100%);
  box-shadow: 0 1px 2px rgba(6,32,62,.30) inset;
}
.tilt-knob {
  /* A full-width layer, not the dot itself: that way the marker's travel below
     is a PERCENTAGE OF THE TRACK and stays in the same colour band at every
     viewport width. In rem it drifted into the red on a phone. */
  position: absolute; left: 4px; right: 4px; top: 50%; height: 0;
}
.tilt-knob::before {
  content: ""; position: absolute; left: 50%; top: -11px;
  width: 22px; height: 22px; margin-left: -11px;
  border-radius: 50%;
  background: radial-gradient(circle at 34% 30%, #FFFFFF 0 38%, #E7F1F8 70%, #BDD3E2 100%);
  box-shadow: 0 1px 0 rgba(255,255,255,.95) inset,
              0 2px 3px rgba(6,32,62,.45), 0 0 0 2px rgba(255,255,255,.75);
}

@media (min-width: 62rem) {
  .hero { padding-block: 3.2rem 3.6rem; }
  .hero-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr); gap: 3.2rem; }
  .hero-copy { text-align: left; }
  .hero-icon { margin-inline: 0; }
  .hero .pitch { margin-inline: 0; }
  .badges, .hero-meta { justify-content: flex-start; }
  .badge .bg-art { height: 54px; }
}

/* ================= sections ================= */

section { padding-block: 3rem; }
section > .wrap > h2 {
  font-size: clamp(1.45rem, 5vw, 2rem); letter-spacing: -.02em;
  margin: 0 0 .45rem; line-height: 1.15;
}
section > .wrap > .lede { color: var(--ink-soft); margin: 0 0 1.7rem; max-width: 42rem; }

/* the deep-water band: saturated harbour blue, straight out of the key art */
.deep {
  background: linear-gradient(180deg, var(--sea-deep) 0%, var(--sea-ink) 100%);
  color: var(--on-sea);
  padding-block: 2.4rem 3.2rem;
}
.deep > .wrap > h2 { color: var(--on-sea); }
.deep > .wrap > .lede { color: var(--on-sea-soft); }
.deep a { color: var(--on-sea-link); }
.deep .motion-note { color: var(--on-sea-soft); }

/* ---------- cards ---------- */

.anim-grid, .shot-grid {
  display: grid; gap: 1.5rem;
  grid-template-columns: repeat(auto-fit, minmax(13.5rem, 1fr));
}
.anim-grid > *, .shot-grid > *, .hero-copy > * { min-width: 0; }

.anim-card, .shot {
  background: var(--card);
  border-radius: var(--radius); overflow: hidden;
  display: flex; flex-direction: column; margin: 0;
  box-shadow: var(--lift);
}
.anim-card img, .shot img {
  display: block; width: 100%; height: auto;
  background: var(--sky-low);
}
.anim-card figcaption, .shot figcaption {
  padding: .9rem 1.05rem 1.1rem; font-size: .93rem; color: var(--ink-soft);
}
.anim-card figcaption b, .shot figcaption b {
  color: var(--ink); display: block; font-size: 1.02rem; margin-bottom: .15rem;
}

.motion-note { font-size: .88rem; color: var(--ink-soft); margin: 1.4rem 0 0; }

/* ---------- "what's on board" ---------- */

.board { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
         list-style: none; margin: 0; padding: 0; }
.board li {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius-s); padding: .95rem 1.1rem;
  font-size: .95rem; color: var(--ink-soft);
  box-shadow: 0 1px 2px rgba(10,44,80,.06);
}
.board li b { display: block; color: var(--ink); font-size: 1rem; margin-bottom: .1rem; }

/* ---------- honest list ---------- */

.honest { background: var(--card); border-block: 1px solid var(--line); }
.honest ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 1.05rem; }
.honest li { padding-left: 2.3rem; position: relative; max-width: 46rem; }
.honest li::before {
  content: "✕"; position: absolute; left: 0; top: -.02rem;
  color: var(--alert); font-weight: 800; font-size: 1.1rem;
  width: 1.6rem; text-align: center;
}
.honest li b { display: block; }
.honest .ads-note { margin-top: 1.8rem; max-width: 46rem; color: var(--ink-soft); font-size: .95rem; }

/* ---------- prose (legal + support) ---------- */

.prose { max-width: 44rem; margin-inline: auto; padding: 2.2rem 1.15rem 1rem; }
.prose h1 { font-size: clamp(1.7rem, 6vw, 2.3rem); line-height: 1.18; margin: 0 0 1.2rem;
            letter-spacing: -.02em; }
.prose h2 { font-size: 1.28rem; margin: 2.3rem 0 .6rem; padding-top: .7rem;
            border-top: 1px solid var(--line); }
.prose h3 { font-size: 1.06rem; margin: 1.6rem 0 .4rem; }
.prose ul { padding-left: 1.3rem; }
.prose li { margin-bottom: .45rem; }
.prose code {
  background: var(--card-2); border: 1px solid var(--line); color: var(--ink);
  padding: .1em .35em; border-radius: 5px; font-size: .9em;
}
.prose .back { margin-top: 2.6rem; font-weight: 700; }

.table-wrap { overflow-x: auto; margin: 1rem 0; max-width: 100%; }
.prose table { border-collapse: collapse; min-width: 30rem; font-size: .92rem; }
.prose th, .prose td {
  border: 1px solid var(--line); padding: .55rem .7rem;
  text-align: left; vertical-align: top;
}
.prose th { background: var(--card-2); }

/* Unfilled [PLACEHOLDER] from the legal sources — impossible to miss if one
   ever comes back. As of 2026-09-20 the sources carry none. */
mark.ph {
  background: #FFF3C4; color: #5B4500;
  border: 1px dashed #B98900; border-radius: 5px;
  padding: 0 .3em; font-weight: 700; font-size: .95em;
}

/* A `> DRAFT` blockquote, lifted out of the markdown. Also currently unused. */
.draft {
  background: var(--alert-bg);
  border: 1px solid var(--alert); border-left-width: 5px;
  border-radius: 12px; padding: 1rem 1.15rem; margin: 1.5rem 0; font-size: .93rem;
}
.draft > :first-child { margin-top: 0; }
.draft > :last-child { margin-bottom: 0; }
.draft strong { color: var(--alert); }

/* ---------- support ---------- */

.todo {
  display: inline-block;
  background: #FFF3C4; color: #5B4500;
  border: 1px dashed #B98900; border-radius: 6px;
  padding: .15em .5em; font-weight: 700;
}
.callout {
  background: var(--card-2); border: 1px solid var(--line);
  border-left: 5px solid var(--sea);
  border-radius: 12px; padding: 1rem 1.15rem; margin: 1.5rem 0;
}
.callout > :first-child { margin-top: 0; }
.callout > :last-child { margin-bottom: 0; }
.support-shot {
  max-width: 15rem; margin: 1rem auto; display: block;
  border-radius: var(--radius); box-shadow: var(--lift);
}

@media (min-width: 52rem) { section { padding-block: 4rem; } }

/* =====================================================================
   MOTION
   Two kinds only:
   1. the hero's heel — one 13 s loop shared by the ship and the tilt meter's
      marker, so the two can never drift out of step;
   2. a one-shot entrance for each block as it scrolls in.
   Both are switched off wholesale at the bottom of this file, where the ship
   is parked at the one angle that carries the whole idea.
   ===================================================================== */

.js .reveal { opacity: 0; transform: translateY(18px);
              transition: opacity .55s ease, transform .55s cubic-bezier(.22,.72,.3,1); }
.js .reveal.in { opacity: 1; transform: none; }
.js .reveal.d1 { transition-delay: .07s; }
.js .reveal.d2 { transition-delay: .14s; }
.js .reveal.d3 { transition-delay: .21s; }

.scene-ship { animation: heel 13s cubic-bezier(.36,.06,.24,1) infinite; }
.tilt-knob  { animation: meter 13s cubic-bezier(.36,.06,.24,1) infinite; }

/* Load to port, load to starboard, nearly over, then back to level. The two
   keyframe sets below share every timing, to the percent. */
@keyframes heel {
  0%,   12% { transform: rotate(0deg); }
  20%,  32% { transform: rotate(-5.5deg); }
  40%,  50% { transform: rotate(4.5deg); }
  58%       { transform: rotate(9.5deg); }
  61%       { transform: rotate(7.8deg); }
  64%       { transform: rotate(9.8deg); }
  70%,  78% { transform: rotate(5.6deg); }
  86%,  94% { transform: rotate(1deg); }
  100%      { transform: rotate(0deg); }
}
/* Percentages of the track. The marker's far swing lands at 50 % + 33.7 % =
   83.7 %, i.e. inside the amber shoulder (70-86 %) and never in the red. */
@keyframes meter {
  0%,   12% { transform: translateX(0); }
  20%,  32% { transform: translateX(-18.9%); }
  40%,  50% { transform: translateX(15.6%); }
  58%       { transform: translateX(32.6%); }
  61%       { transform: translateX(26.7%); }
  64%       { transform: translateX(33.7%); }
  70%,  78% { transform: translateX(19.3%); }
  86%,  94% { transform: translateX(3.3%); }
  100%      { transform: translateX(0); }
}

/* ---------- reduced motion ----------
   Nothing moves, and the still is the frame that carries the idea: loaded,
   heeled hard over, the marker sitting out in the amber. ---------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation: none !important;
    transition-duration: .001ms !important;
  }
  .js .reveal { opacity: 1 !important; transform: none !important; }
  .scene-ship { transform: rotate(9.2deg) !important; }
  .tilt-knob  { transform: translateX(31.9%) !important; }
}
