/*
  Ryokōya — ryokoya.app
  ---------------------------------------------------------------------------
  The site is a page torn out of the thing it is selling: a night sky, a route
  drawn across it, and a small creature keeping notes. Every color below is
  lifted from DesignSystem.swift so the web and the app are the same object.

  TYPOGRAPHY, and why there is not a single webfont.
  `ui-rounded` resolves to SF Rounded on Apple platforms — literally the app's
  typeface — and `ui-serif` resolves to New York, Apple's editorial serif, which
  is exactly the guidebook voice this wants. Both cost zero requests. That is
  not only a performance nicety: the privacy page claims the site loads nothing
  from anyone else, and pulling fonts from a CDN would quietly make that untrue.
  The audience is iPhone owners, so the good case is also the common case.
*/

:root {
  /* Straight from DesignSystem.swift */
  --teal:    #26adb8;
  --coral:   #ff6b6b;
  --gold:    #ffc247;
  --purple:  #8c5ccc;
  --success: #33c78c;

  /* The share card's night canvas */
  --night-0: #0b1028;
  --night-1: #161340;
  --night-2: #241a4e;

  --ink:       #f4f2ff;
  --ink-soft:  rgba(244, 242, 255, 0.72);
  --ink-faint: rgba(244, 242, 255, 0.45);
  --rule:      rgba(244, 242, 255, 0.12);

  --display: ui-serif, "New York", Georgia, "Times New Roman", serif;
  --ui: ui-rounded, "SF Pro Rounded", -apple-system, "Segoe UI", system-ui, sans-serif;

  --measure: 68ch;
  --page: 1120px;
}

*, *::before, *::after { box-sizing: border-box; }

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  font-family: var(--ui);
  color: var(--ink);
  background: var(--night-0);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* ---------------------------------------------------------------- atmosphere
   Three layers, none of them an image request: a vertical night gradient, two
   color blooms borrowed from the share card, and a grain overlay generated by
   an inline SVG turbulence filter. Grain is what stops a large flat gradient
   reading as a cheap CSS backdrop. */

.sky {
  position: fixed;
  inset: 0;
  z-index: -2;
  background:
    radial-gradient(900px 620px at 12% 4%, rgba(38, 173, 184, 0.20), transparent 62%),
    radial-gradient(760px 560px at 88% 26%, rgba(140, 92, 204, 0.22), transparent 60%),
    radial-gradient(820px 620px at 42% 82%, rgba(255, 107, 107, 0.13), transparent 62%),
    linear-gradient(178deg, var(--night-0) 0%, var(--night-1) 46%, var(--night-2) 100%);
}

.grain {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: 0.4;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
}

/* A fixed starfield, deterministic rather than random, so the sky is the same
   sky on every visit. */
.stars { position: fixed; inset: 0; z-index: -1; pointer-events: none; }
.stars i {
  position: absolute;
  border-radius: 50%;
  background: #fff;
  animation: twinkle 6s ease-in-out infinite;
}
@keyframes twinkle { 0%, 100% { opacity: 0.28; } 50% { opacity: 0.85; } }
@media (prefers-reduced-motion: reduce) { .stars i { animation: none; } }

/* ------------------------------------------------------------------- shell */

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

header.masthead {
  position: sticky;
  top: 0;
  z-index: 20;
  padding: 0.9rem 0;
  backdrop-filter: blur(14px);
  background: rgba(11, 16, 40, 0.62);
  border-bottom: 1px solid transparent;
  transition: border-color 0.3s ease, background 0.3s ease;
}
header.masthead.stuck { border-bottom-color: var(--rule); background: rgba(11, 16, 40, 0.86); }

.masthead .wrap { display: flex; align-items: center; gap: 1.25rem; }
.masthead img { height: 30px; width: auto; display: block; }
.masthead nav { margin-left: auto; display: flex; gap: 1.5rem; align-items: center; }
.masthead nav a {
  color: var(--ink-soft);
  text-decoration: none;
  font-size: 0.9rem;
  font-weight: 600;
  transition: color 0.2s ease;
}
.masthead nav a:hover { color: var(--gold); }
@media (max-width: 640px) { .masthead nav a.hide-sm { display: none; } }

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

h1, h2, h3 { font-family: var(--display); font-weight: 700; letter-spacing: -0.02em; margin: 0; }
h1 { font-size: clamp(2.7rem, 7.5vw, 5.1rem); line-height: 1.02; }
h2 { font-size: clamp(1.9rem, 4vw, 2.9rem); line-height: 1.1; }
h3 { font-size: 1.16rem; font-family: var(--ui); font-weight: 700; letter-spacing: -0.01em; }

p { line-height: 1.65; margin: 0 0 1.1rem; max-width: var(--measure); }
a { color: var(--gold); }

.eyebrow {
  font-family: var(--ui);
  font-size: 0.76rem;
  font-weight: 800;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--gold);
  margin: 0 0 1rem;
}
.lede { font-size: clamp(1.06rem, 2vw, 1.24rem); color: var(--ink-soft); }
.jp { font-family: var(--ui); color: var(--teal); letter-spacing: 0.3em; font-size: 0.8rem; }

/* -------------------------------------------------------------------- hero */

.hero { padding: clamp(3.5rem, 9vw, 7rem) 0 clamp(3rem, 7vw, 5.5rem); }
.hero .wrap { display: grid; grid-template-columns: 1.15fr 0.85fr; gap: clamp(2rem, 5vw, 4.5rem); align-items: center; }
@media (max-width: 860px) { .hero .wrap { grid-template-columns: 1fr; } }

.hero h1 em {
  font-style: italic;
  color: var(--gold);
  /* The one place the display face is allowed to show off. */
}

.hero-actions { display: flex; flex-wrap: wrap; gap: 0.9rem; margin-top: 2rem; align-items: center; }

.btn {
  font-family: var(--ui);
  font-weight: 700;
  font-size: 1rem;
  text-decoration: none;
  padding: 0.95rem 1.6rem;
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  transition: transform 0.18s ease, box-shadow 0.18s ease;
}
.btn-primary {
  background: linear-gradient(120deg, var(--gold), #ffb01f);
  color: #2b1a00;
  box-shadow: 0 10px 30px rgba(255, 194, 71, 0.28);
}
.btn-primary:hover { transform: translateY(-2px); box-shadow: 0 16px 40px rgba(255, 194, 71, 0.38); }
.btn-ghost { color: var(--ink); border: 1px solid var(--rule); }
.btn-ghost:hover { border-color: var(--gold); color: var(--gold); }

.hero-note { font-size: 0.86rem; color: var(--ink-faint); margin-top: 1.4rem; }

/* Phone: tilted, not flat-on — a diary lying on a table rather than a spec sheet. */
.phone {
  position: relative;
  border-radius: 30px;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow: 0 40px 90px rgba(0, 0, 0, 0.55), 0 0 0 8px rgba(255, 255, 255, 0.03);
  transform: rotate(-3deg);
  transition: transform 0.5s cubic-bezier(0.2, 0.8, 0.2, 1);
  max-width: 300px;
  margin-inline: auto;
}
.phone:hover { transform: rotate(-1deg) translateY(-6px); }
.phone img { display: block; width: 100%; height: auto; }

/* -------------------------------------------------------- collection pair
   The two shared favorites cards beside the "what you bring home" story.
   Fanned rather than stacked: they are the same object from two trips, and a
   pair leaning against each other reads as a collection where a neat grid of
   two reads as a comparison. The rotations are opposed so the pair has a
   center, and they straighten on hover — the same gesture .phone makes, so the
   page has one idea about how its images behave. */

.collection-pair {
  margin: 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(0.6rem, 1.6vw, 1.1rem);
  align-items: center;
}

/* The media column of THIS split carries two 9:16 cards rather than one phone,
   so it needs more than the 0.75fr a single phone gets. At the default ratio
   each card landed around 150px wide and the maps inside them stopped being
   readable, which defeats showing them at all. */
#favorites .split { grid-template-columns: 1fr 0.92fr; }
@media (max-width: 860px) {
  #favorites .split { grid-template-columns: 1fr; }
  .collection-pair { max-width: 520px; margin-inline: auto; }
}
.collection-card {
  border-radius: 18px;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow: 0 26px 60px rgba(0, 0, 0, 0.5), 0 0 0 6px rgba(255, 255, 255, 0.03);
  transition: transform 0.5s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.collection-card:first-child { transform: rotate(-3.5deg); }
.collection-card:last-child  { transform: rotate(3deg) translateY(1.4rem); }
.collection-pair:hover .collection-card:first-child { transform: rotate(-1deg) translateY(-6px); }
.collection-pair:hover .collection-card:last-child  { transform: rotate(1deg) translateY(0.6rem); }
.collection-card img { display: block; width: 100%; height: auto; }

.collection-note {
  margin: 2.4rem 0 0;
  text-align: center;
  font-size: 0.84rem;
  color: var(--ink-faint);
}

/* Tilted cards need room to lean into; the last one also rides 1.4rem low. */
@media (min-width: 861px) { .collection-pair { padding: 0.6rem 0.2rem 1.4rem; } }

@media (prefers-reduced-motion: reduce) {
  .collection-card,
  .collection-pair:hover .collection-card:first-child,
  .collection-pair:hover .collection-card:last-child { transform: none; transition: none; }
}

/* ------------------------------------------------------------- phone pair
   Two screenshots where one used to sit, in the hero and the packs section.
   One phone shows a feature; two show it lives in an app with a second screen
   behind it, which is the difference between a mock-up and a product.

   SIDE BY SIDE, not overlapped. The first cut leaned the second phone behind
   the first, which reads fine on a narrow viewport and poorly on a desktop one
   — the back screenshot becomes a sliver of texture rather than a thing you can
   read. The favorites section had already solved this: two cards at equal
   width, opposing tilts, one riding slightly low. Same treatment here, so the
   page holds ONE idea about how it presents a pair of screens.

   The cost is width, which is why both containing columns widen below. */

.phone-pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(0.6rem, 1.6vw, 1.05rem);
  align-items: center;
  margin-inline: auto;
}
.phone-pair .phone { margin-inline: 0; max-width: none; }
.phone-pair .phone:first-child { transform: rotate(-3.5deg); }
.phone-pair .phone:last-child  { transform: rotate(3deg) translateY(1.2rem); }
.phone-pair:hover .phone:first-child { transform: rotate(-1deg) translateY(-6px); }
.phone-pair:hover .phone:last-child  { transform: rotate(1deg) translateY(0.5rem); }

/* The packs pair sits on the left of its split, so it leans the other way. */
.phone-pair-flip .phone:first-child { transform: rotate(3deg); }
.phone-pair-flip .phone:last-child  { transform: rotate(-3.5deg) translateY(1.2rem); }
.phone-pair-flip:hover .phone:first-child { transform: rotate(1deg) translateY(-6px); }
.phone-pair-flip:hover .phone:last-child  { transform: rotate(-1deg) translateY(0.5rem); }

/* The one-line caption the favorites pair already carried, extended to these
   two. It does real work: without it a reader has to guess whether two screens
   mean two features or one feature photographed twice. Matched to
   .collection-note exactly — the page should have one voice for captions —
   but with less room above, since the low-riding phone leans 1.2rem rather
   than the collection card's 1.4rem. */
.pair-note {
  margin: 1.9rem 0 0;
  text-align: center;
  font-size: 0.84rem;
  color: var(--ink-faint);
}

/* A pair needs more room than the single phone these columns were sized for.
   At the old ratios each screenshot came out near 140px and the UI inside
   stopped being legible, which is the whole reason to show a screenshot. */
.hero .wrap { grid-template-columns: 1.12fr 0.88fr; }
#packs .split.flip { grid-template-columns: 0.95fr 1fr; }
@media (max-width: 860px) {
  .hero .wrap { grid-template-columns: 1fr; }
  #packs .split.flip { grid-template-columns: 1fr; }
  .phone-pair { max-width: 520px; }
}

@media (prefers-reduced-motion: reduce) {
  .phone-pair .phone,
  .phone-pair:hover .phone:first-child, .phone-pair:hover .phone:last-child,
  .phone-pair-flip:hover .phone:first-child, .phone-pair-flip:hover .phone:last-child {
    transform: none; transition: none;
  }
}

/* ------------------------------------------------------- tracking profiles
   The battery table. Four rows, and the fourth is the point — it is styled as
   the cheap one so the eye lands there, because "we made the common case
   coarse" is the whole answer to the battery question. */

.profiles { margin: 0; padding: 1.4rem 1.3rem 1.5rem; border-radius: 22px;
  background: rgba(255, 255, 255, 0.04); border: 1px solid var(--rule); }
.profiles figcaption { font-size: 0.7rem; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--ink-faint); margin-bottom: 1.1rem; }
.profiles ol { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.9rem; }
.profiles li { padding: 0.85rem 0.95rem; border-radius: 14px; background: rgba(255, 255, 255, 0.035);
  border-left: 3px solid rgba(255, 194, 71, 0.55); }
.profiles li.pf-cheap { border-left-color: var(--success); background: rgba(51, 199, 140, 0.09); }
.pf-name { display: block; font-weight: 700; font-size: 0.98rem; }
.pf-detail { display: block; font-size: 0.86rem; color: var(--ink-soft); margin-top: 0.15rem; }
.pf-why { display: block; font-size: 0.8rem; color: var(--ink-faint); margin-top: 0.3rem; font-style: italic; }

/* ------------------------------------------------------------------ tiers
   Free first, because the free tier IS the product and the paid one is a set
   of conveniences on top. A pricing table that leads with the paid column
   tells the opposite story.

   The two cards are the same width and the same height, even though Free
   carries ten bullets to Pro's seven. Sizing each card to its own content is
   the honest default, but on screen it reads as Pro being the lesser thing —
   a shorter box next to a taller one looks unfinished rather than cheaper.
   Matched frames, and the leftover room inside the Pro card is spent below. */

.tiers { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(1rem, 2.5vw, 1.6rem); align-items: stretch; }
@media (max-width: 860px) { .tiers { grid-template-columns: 1fr; } }

.tier { padding: clamp(1.6rem, 3vw, 2.2rem); border-radius: 24px; border: 1px solid var(--rule);
  background: rgba(255, 255, 255, 0.04); display: flex; flex-direction: column; }
.tier-free { background: linear-gradient(150deg, rgba(51, 199, 140, 0.13), rgba(38, 173, 184, 0.09));
  border-color: rgba(51, 199, 140, 0.32); }
.tier-label { margin: 0; font-size: 0.72rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--ink-faint); }
.tier-price { margin: 0.5rem 0 1.3rem; font-family: var(--display); font-size: clamp(2rem, 4vw, 2.7rem);
  font-weight: 700; letter-spacing: -0.02em; line-height: 1; }
.tier-price span { display: block; margin-top: 0.5rem; font-family: var(--ui); font-size: 0.86rem;
  font-weight: 500; letter-spacing: 0; color: var(--ink-soft); }
/* `margin-bottom: auto` is what spends the leftover height in the shorter card:
   it eats the free space, which pushes .tier-note down to sit on the card's
   bottom edge like a footer instead of leaving a void underneath it. When
   there is no free space (the Free card, which sets the row height) auto
   resolves to 0 and .tier-note keeps its own 1.4rem — so the taller card is
   untouched and this cannot collapse the gap. */
.tier ul { list-style: none; margin: 0 0 auto; padding: 0; display: grid; gap: 0.75rem; }
.tier li { position: relative; padding-left: 1.65rem; font-size: 0.94rem; color: var(--ink-soft); line-height: 1.5; }
.tier li b { color: var(--ink); font-weight: 700; }
.tier li::before { content: "✓"; position: absolute; left: 0; top: 0; font-weight: 800; color: var(--success); }
.tier-pro li::before { color: var(--gold); }
.tier-note { margin: 1.4rem 0 0; padding-top: 1.2rem; border-top: 1px solid var(--rule);
  font-size: 0.9rem; color: var(--ink-soft); line-height: 1.55; }
.tier-note b { color: var(--ink); }
.tier-foot { margin: 1.6rem 0 0; text-align: center; font-size: 0.92rem; color: var(--ink-soft); }
.tier-foot b { color: var(--ink); }

/* ----------------------------------------------------------------- strips
   Trip Pass and City Packs, under the two tiers.
 
   Both were footnotes before — Trip Pass buried at the bottom of the Pro card,
   City Packs as one gray line under the grid — and a footnote is where a reader
   decides something is unimportant. They are neither: Trip Pass is the answer
   for somebody who travels twice a year and correctly refuses a subscription,
   and packs are the whole collecting game.
 
   Wide and short rather than a third and fourth column. They are not tiers and
   should not look like tiers being compared: a full-width strip reads as "also
   available" instead of "option C". The price sits in its own left-hand block
   so the eye gets the number before the argument, which is the same order the
   tiers above use. */

.strips { margin-top: clamp(1rem, 2.5vw, 1.6rem); display: grid; gap: clamp(0.8rem, 1.8vw, 1.1rem); }

.strip {
  display: grid;
  grid-template-columns: minmax(140px, 0.2fr) 1fr;
  gap: clamp(1rem, 3vw, 2.2rem);
  align-items: center;
  padding: clamp(1.3rem, 2.6vw, 1.9rem) clamp(1.4rem, 3vw, 2.2rem);
  border-radius: 24px;
  border: 1px solid var(--rule);
  background: rgba(255, 255, 255, 0.04);
}
.strip-pass  { background: linear-gradient(120deg, rgba(255, 194, 71, 0.12), rgba(255, 194, 71, 0.03));
               border-color: rgba(255, 194, 71, 0.30); }
.strip-packs { background: linear-gradient(120deg, rgba(255, 107, 107, 0.12), rgba(140, 92, 204, 0.06));
               border-color: rgba(255, 107, 107, 0.28); }

.strip-mark {
  width: 46px; height: 46px; border-radius: 14px;
  display: grid; place-items: center;
  margin: 0 auto 0.9rem;
}
.strip-mark svg { width: 23px; height: 23px; display: block; }
.strip-pass .strip-mark  { background: rgba(255, 194, 71, 0.16); color: var(--gold); }
.strip-packs .strip-mark { background: rgba(255, 107, 107, 0.16); color: var(--coral); }

.strip-price { text-align: center; }
.strip-amount { display: block; font-family: var(--display); font-weight: 700; letter-spacing: -0.02em;
  line-height: 1; font-size: clamp(1.8rem, 3.4vw, 2.4rem); }
.strip-cadence { display: block; margin-top: 0.45rem; font-size: 0.76rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--ink-faint); }
.strip-pass .strip-amount  { color: var(--gold); }
.strip-packs .strip-amount { color: var(--coral); }

.strip-body h3 { margin: 0 0 0.5rem; }
.strip-body p { margin: 0; font-size: 0.94rem; color: var(--ink-soft); line-height: 1.6; }
.strip-body p b { color: var(--ink); font-weight: 700; }

/* Stacked, with the price above the argument rather than beside it. A 140px
   price column on a 375px screen leaves the paragraph in a gutter. */
@media (max-width: 640px) {
  .strip { grid-template-columns: 1fr; gap: 0.9rem; }
  .strip-price { text-align: left; display: flex; align-items: baseline; gap: 0.6rem; }
  .strip-mark { margin: 0 0 0.75rem; }
  .strip-cadence { margin-top: 0; }
}

/* ------------------------------------------------------------------- route
   The spine of the page: a dashed line drawn as you scroll, the same motif the
   app stamps on its books and share cards. */

.route { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 0; }
.route path {
  fill: none;
  stroke: rgba(244, 242, 255, 0.30);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-dasharray: 1 10;
}

/* ---------------------------------------------------------------- sections */

section { position: relative; padding: clamp(3.5rem, 8vw, 6.5rem) 0; }
.section-head { max-width: 62ch; margin-bottom: clamp(2rem, 4vw, 3.2rem); }

/* Three beats, offset so the eye walks rather than scans. */
.beats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.6rem; }
@media (max-width: 820px) { .beats { grid-template-columns: 1fr; } }
.beat {
  position: relative;
  padding: 1.9rem 1.6rem 1.7rem;
  border-radius: 22px;
  background: rgba(255, 255, 255, 0.045);
  border: 1px solid var(--rule);
}
.beats .beat:nth-child(2) { transform: translateY(1.8rem); }
.beats .beat:nth-child(3) { transform: translateY(3.6rem); }
@media (max-width: 820px) { .beats .beat { transform: none !important; } }
.beat .num {
  font-family: var(--display);
  font-size: 2.6rem;
  line-height: 1;
  color: var(--gold);
  opacity: 0.5;
  display: block;
  margin-bottom: 0.7rem;
}
.beat p { font-size: 0.96rem; color: var(--ink-soft); margin-bottom: 0; }
.beat h3 { margin-bottom: 0.5rem; }

/* Feature grid */
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(255px, 1fr)); gap: 1.4rem; }
.card {
  padding: 1.7rem 1.5rem;
  border-radius: 20px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--rule);
  transition: border-color 0.25s ease, transform 0.25s ease, background 0.25s ease;
}
.card:hover { border-color: rgba(255, 194, 71, 0.4); transform: translateY(-3px); background: rgba(255, 255, 255, 0.06); }
.card p { font-size: 0.94rem; color: var(--ink-soft); margin-bottom: 0; }
.card h3 { margin-bottom: 0.5rem; }
.card .mark {
  width: 38px; height: 38px; border-radius: 12px;
  display: grid; place-items: center;
  margin-bottom: 1rem;
}
.card .mark svg { width: 21px; height: 21px; display: block; }

/* Split: text beside a phone */
.split { display: grid; grid-template-columns: 1fr 0.75fr; gap: clamp(2rem, 5vw, 4rem); align-items: center; }
.split.flip { grid-template-columns: 0.75fr 1fr; }
@media (max-width: 860px) { .split, .split.flip { grid-template-columns: 1fr; } }

/* The promise block — the app's actual differentiator, so it gets the weight */
.promise {
  border-radius: 26px;
  padding: clamp(2rem, 4.5vw, 3.2rem);
  background: linear-gradient(150deg, rgba(38, 173, 184, 0.13), rgba(140, 92, 204, 0.10));
  border: 1px solid rgba(38, 173, 184, 0.28);
}
.promise ul { list-style: none; padding: 0; margin: 1.6rem 0 0; display: grid; gap: 0.9rem; }
/* NOT display:flex. A flex li makes every child its own flex item, so a <b>
   followed by plain text becomes two columns — which fragmented these lines into
   "Your trips live on your device" | ", and" | "your" | "in". The check is
   positioned instead, and the content stays ordinary flowing text. */
.promise li {
  position: relative;
  padding-left: 1.75rem;
  color: var(--ink-soft);
  line-height: 1.55;
}
.promise li b { color: var(--ink); font-weight: 700; }
.promise li::before {
  content: "✓";
  position: absolute;
  left: 0;
  top: 0;
  color: var(--success);
  font-weight: 800;
}

/* Numbers */
/* ------------------------------------------------------------- the recall
   The "example day handed back" panel beside the nine-o'clock story. Built
   from type and rules rather than a screenshot, so the page keeps its promise
   of loading nothing from anywhere. */
.recall {
  margin: 0;
  padding: 1.5rem 1.4rem 1.6rem;
  border-radius: 22px;
  border: 1px solid var(--rule);
  background: linear-gradient(160deg, rgba(255,255,255,0.06), rgba(255,255,255,0.02));
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.35);
  position: relative;
}
.recall figcaption { margin-bottom: 1.1rem; }
.recall-kicker {
  font-family: var(--ui);
  font-size: 0.68rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 0 0 0.5rem;
}
.recall-title {
  font-family: var(--display);
  font-size: 1.5rem;
  line-height: 1.1;
  color: var(--ink);
  margin: 0 0 0.35rem;
}
.recall-stats { font-size: 0.82rem; color: var(--ink-faint); margin: 0; }

.recall-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.15rem; }
.recall-list li {
  display: grid;
  grid-template-columns: 3.7rem 1fr auto;
  align-items: baseline;
  gap: 0.7rem;
  padding: 0.55rem 0.6rem;
  border-radius: 11px;
  font-size: 0.92rem;
}
.recall-list .t { font-family: var(--ui); font-size: 0.78rem; color: var(--teal); letter-spacing: 0.04em; }
.recall-list .p { color: var(--ink-soft); }
.recall-list .d { font-family: var(--ui); font-size: 0.76rem; color: var(--ink-faint); }

/* The payoff row: the line the whole story above is about. */
.recall-list li.hit {
  background: rgba(255, 194, 71, 0.11);
  border: 1px solid rgba(255, 194, 71, 0.34);
  padding-block: 0.6rem;
}
.recall-list li.hit .p { color: var(--ink); font-weight: 600; }
.recall-list li.hit .t,
.recall-list li.hit .d { color: var(--gold); }

.recall-note {
  margin: 0.9rem 0 0;
  font-size: 0.84rem;
  color: var(--ink-faint);
  font-style: italic;
}

/* A stamp, pressed into the corner the way the app presses them. */
.recall-seal {
  position: absolute;
  right: 1.1rem;
  bottom: 1.1rem;
  width: 82px;
  height: 82px;
  border-radius: 50%;
  border: 2px solid rgba(255, 194, 71, 0.55);
  display: grid;
  place-content: center;
  text-align: center;
  transform: rotate(-9deg);
  color: var(--gold);
}
.recall-seal::before {
  content: "";
  position: absolute;
  inset: 5px;
  border-radius: 50%;
  border: 1px dashed rgba(255, 194, 71, 0.4);
}
.recall-seal b { display: block; font-family: var(--ui); font-size: 0.6rem; letter-spacing: 0.1em; font-weight: 800; }
.recall-seal span { display: block; font-family: var(--ui); font-size: 0.55rem; letter-spacing: 0.14em; opacity: 0.8; margin-top: 2px; }

/* Under the seal the last row would collide with it. */
@media (min-width: 861px) { .recall { padding-bottom: 5.6rem; } }
@media (max-width: 860px) { .recall-seal { display: none; } }

.tally { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1rem; margin-top: 2.5rem; }
@media (max-width: 700px) { .tally { grid-template-columns: repeat(2, 1fr); } }
.tally div { text-align: center; padding: 1.2rem 0.5rem; border-radius: 16px; background: rgba(255,255,255,0.035); border: 1px solid var(--rule); }
.tally b { display: block; font-family: var(--display); font-size: 2rem; line-height: 1; color: var(--gold); }
.tally span { display: block; margin-top: 0.4rem; font-size: 0.72rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-faint); }

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

footer {
  border-top: 1px solid var(--rule);
  padding: 3rem 0 3.5rem;
  margin-top: 2rem;
}
footer .wrap { display: flex; flex-wrap: wrap; gap: 1.6rem 2.5rem; align-items: center; }
footer img { height: 26px; opacity: 0.85; }
footer nav { display: flex; gap: 1.5rem; flex-wrap: wrap; }
footer a { color: var(--ink-soft); text-decoration: none; font-size: 0.9rem; }
footer a:hover { color: var(--gold); }
footer .legal { width: 100%; color: var(--ink-faint); font-size: 0.8rem; margin: 0; }

/* ------------------------------------------------------- document pages
   Legal pages are for reading, not for looking at. Same sky, quieter fittings,
   a comfortable measure and real hierarchy. */

.doc { padding: clamp(2.5rem, 6vw, 4.5rem) 0 5rem; }
.doc .wrap { max-width: 800px; }
.doc h1 { font-size: clamp(2.1rem, 5vw, 3.1rem); margin-bottom: 0.6rem; }
.doc .updated { color: var(--ink-faint); font-size: 0.86rem; margin-bottom: 2.5rem; }
.doc h2 { font-size: 1.42rem; margin: 2.6rem 0 0.85rem; }
.doc h3 { margin: 1.8rem 0 0.5rem; color: var(--gold); }
.doc p, .doc li { color: var(--ink-soft); }
.doc ul { padding-left: 1.15rem; margin: 0 0 1.2rem; }
.doc li { margin-bottom: 0.55rem; line-height: 1.6; }
.doc strong { color: var(--ink); }
.doc table { width: 100%; border-collapse: collapse; margin: 1.2rem 0 1.8rem; font-size: 0.92rem; }
.doc th, .doc td { text-align: left; padding: 0.7rem 0.6rem; border-bottom: 1px solid var(--rule); vertical-align: top; }
.doc th { color: var(--ink); font-family: var(--ui); font-weight: 700; font-size: 0.8rem; letter-spacing: 0.08em; text-transform: uppercase; }
.doc td:first-child { color: var(--ink); font-weight: 600; white-space: nowrap; }
.doc .callout {
  border-left: 3px solid var(--teal);
  background: rgba(38, 173, 184, 0.08);
  padding: 1.1rem 1.3rem;
  border-radius: 0 14px 14px 0;
  margin: 1.6rem 0;
}
.doc .callout p:last-child { margin-bottom: 0; }

/* ---------------------------------------------------------------- reveals */

.js .reveal { opacity: 0; transform: translateY(22px); transition: opacity 0.7s ease, transform 0.7s cubic-bezier(0.2, 0.8, 0.2, 1); }
.js .reveal.in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .js .reveal { opacity: 1; transform: none; transition: none; }
}

/* Hero load-in: one orchestrated cascade rather than scattered fidgeting. */
.js .rise { opacity: 0; animation: rise 0.9s cubic-bezier(0.2, 0.8, 0.2, 1) forwards; }
.rise:nth-child(1) { animation-delay: 0.05s; }
.rise:nth-child(2) { animation-delay: 0.15s; }
.rise:nth-child(3) { animation-delay: 0.25s; }
.rise:nth-child(4) { animation-delay: 0.35s; }
.rise:nth-child(5) { animation-delay: 0.45s; }
@keyframes rise { to { opacity: 1; transform: none; } }
.js .rise { transform: translateY(20px); }
@media (prefers-reduced-motion: reduce) {
  .js .rise { opacity: 1; transform: none; animation: none; }
}

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

/* ------------------------------------------------------------- brandmark
   A 30px mark in the masthead is navigation; it does not tell a first-time
   visitor where they have landed. The hero opens with the wordmark at real
   size, the kanji, and a plain gloss of what the word means — most of the
   audience will never have seen it before. */

.brandmark { margin-bottom: 1.6rem; }
.brandmark img {
  display: block;
  width: min(340px, 74vw);
  height: auto;
}
.brandmark-gloss {
  margin: 0.85rem 0 0;
  font-size: 0.92rem;
  color: var(--ink-faint);
  letter-spacing: 0.01em;
}
.brandmark-gloss i { color: var(--teal); font-style: italic; }

/* Honest labelling for anything that does not ship on day one. */
.soon {
  display: inline-block;
  margin-top: 0.5rem;
  font-size: 0.84rem;
  color: var(--gold);
  opacity: 0.85;
}

/* ------------------------------------------------------------ the flock
   Overlapping portraits, because a character lineup is the hook and a list of
   names is not. Each sits slightly higher than the last so the row reads as a
   crowd leaning in rather than a row of buttons. */

.flock {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  padding-left: 26px;      /* balances the negative margin below */
  margin-top: 2.5rem;
}
.flock img {
  width: clamp(74px, 11vw, 116px);
  height: clamp(74px, 11vw, 116px);
  border-radius: 50%;
  margin-left: -26px;
  border: 3px solid rgba(11, 16, 40, 0.9);
  box-shadow: 0 14px 34px rgba(0, 0, 0, 0.45);
  background: var(--night-1);
  position: relative;
  /* Stagger: alternating lift, so the row has a pulse instead of a flat edge. */
  transform: translateY(calc(var(--i) % 2 * -14px));
  z-index: calc(10 - var(--i));
  transition: transform 0.35s cubic-bezier(0.2, 0.8, 0.2, 1), z-index 0s;
}
.flock img:hover {
  transform: translateY(calc(var(--i) % 2 * -14px)) translateY(-12px) scale(1.07);
  z-index: 20;
}
@media (prefers-reduced-motion: reduce) { .flock img { transition: none; } }
