/* The landing page, built by homepage.js: the hero, the timeline, the level select and the finale. story.css
   has the scenes of the story. site.css sets the fonts of the headings and the motion of the buttons.
   Only transform, opacity and the light of the dark area move, and only while the system allows
   motion. Without motion the light of the dark area is in the middle. */

/* A stage for Shelly and Jack, lit by the light inside it. */
.stage {
  position: relative;
  border: var(--border-2) solid var(--stage-outline);
  border-radius: var(--radius);
  background: var(--stage);
}
.light { position: absolute; inset: 0; }
/* Jack and Shelly stand at rest in the dark area, which dark-area.js hides while the light hunts. */
.dark-search.hunting .rest-pair { display: none; }
.light-red { background: radial-gradient(circle at 50% 75%, color-mix(in oklab, var(--jack) var(--light-strength), transparent), transparent 65%); }
.light-green { background: radial-gradient(circle at 50% 75%, color-mix(in oklab, var(--shelly) var(--light-strength), transparent), transparent 65%); }

/* --- Hero --- */

.hero { padding: var(--hero-pad); }
.hero-text { --layout-gap: var(--space-20); justify-items: start; }
.lead { font: var(--font-lead); color: var(--text-2); }
.hero .trust { font: var(--font-small); color: var(--muted); }

/* --- Dark area --- */

/* @property lets the sweep keyframes move the light after a touch. The light shows only while a
   mouse is in the area, while the sweep runs or with reduced motion, and its lit part shows the
   striped floor of the stage. */
@property --light-x { syntax: "<length-percentage>"; inherits: false; initial-value: 50%; }
@property --light-y { syntax: "<length-percentage>"; inherits: false; initial-value: 50%; }
.dark-search {
  --area-height: var(--height-dark-area);
  --light-radius: calc(var(--area-height) * 0.32);
  --light-core: calc(var(--area-height) * 0.2);
  --lit-background:
    radial-gradient(circle var(--light-radius) at var(--light-x) var(--light-y), transparent 0 var(--light-core), var(--darkness) var(--light-radius)),
    var(--stage-pattern);
  height: var(--area-height);
  background: var(--darkness);
}
.dark-search.lit,
.dark-search.sweeping { background: var(--lit-background); }

/* While dark-area.js sets cursor-hidden, the cursor is hidden inside the area only, and comes back
   when the pointer leaves it. The way out is the bottom right corner of the area. The corner is
   blank and looks like the area around it. */
.dark-way-out {
  display: none;
  position: absolute;
  right: 0;
  bottom: 0;
  width: var(--size-way-out);
  height: var(--size-way-out);
}
/* gotchas/jack/visit.js watches this line along the bottom edge of the area, where Jack stands. */
.dark-bottom-edge { position: absolute; inset: auto 0 0; }
.dark-search.cursor-hidden {
  &, * { cursor: none; }
  .dark-way-out { display: block; }
}

/* Jack beside the bottom right corner of the dark area, where the way out is. Each pose stands with
   the bottom edge of its own figure on the bottom edge of the area, and with the left edge of its
   figure --gap to the right of the area. Where the gutter of the page is narrower than the figure
   that shows his laugh pose, that figure ends --gap before the right edge of the window. He walks
   in from beyond the right edge of the window, facing left, for --walk-rounds rounds of his walk
   frames, laughs for --laugh-rounds rounds at the timing of the art, and walks back out to the
   right. parts/jack-visit.js sets the number of frames and the figure of each pose. The visit itself
   runs one animation for the whole time, whose end gotchas/jack/visit.js waits for. It spans the area and the
   gutter of the page beside it, up to the right edge of the window, and clips Jack where he is
   beyond that edge. */
.jack-visit {
  --width: var(--sprite-size);
  --gap: var(--space-8);
  --walk-rounds: 2;
  --laugh-rounds: 1;
  --walk-in-time: calc(var(--walk-rounds) * var(--walk-in-frames) * var(--sprite-frame-time));
  --laugh-time: calc(var(--laugh-rounds) * var(--laugh-frames) * var(--art-frame-time));
  --walk-out-time: calc(var(--walk-rounds) * var(--walk-out-frames) * var(--sprite-frame-time));
  --walked-in-and-laughed: calc(var(--walk-in-time) + var(--laugh-time));
  --off-screen: calc(var(--page-gutter) + var(--width));
  position: absolute;
  inset: 0 auto 0 0;
  width: calc(100% + var(--page-gutter));
  overflow-x: clip;
  z-index: var(--layer-jack-beside-area);
  pointer-events: none;
}
.visit-poses {
  position: absolute;
  bottom: 0;
  left: calc(100% - var(--page-gutter) + min(var(--gap), var(--page-gutter) - var(--figure-width) - var(--gap)));
  display: grid;
  place-items: end start;
}
.visit-poses > * { grid-area: 1 / 1; position: relative; opacity: 0; }
.visit-walk-in .character { --strip-rounds: var(--walk-rounds); }
.visit-walk-out .character { --strip-delay: var(--walked-in-and-laughed); --strip-rounds: var(--walk-rounds); }
.visit-laugh .character {
  --sprite-frame-time: var(--art-frame-time);
  --strip-delay: var(--walk-in-time);
  --strip-rounds: var(--laugh-rounds);
}
/* What Jack says is a sentence, so it shows in the sans font: the pixel font is only for short
   labels. */
.jack-hint {
  position: absolute;
  top: 8%;
  right: 75%;
  inline-size: max-content;
  max-inline-size: var(--measure-hint);
  padding: var(--space-6) var(--space-10);
  border: var(--border-2) solid var(--jack);
  background: var(--surface);
  color: var(--text);
  font: 600 var(--font-14)/var(--leading-140) var(--sans);
}

/* Jack at the right edge of the dark area, in front of it and facing left, with the hint to his left.
   The clipping box keeps him inside the area. He moves in until the half of him nearer the area
   shows, waits and moves out again, for --peek-time, which parts/jack-peek.js sets and after which
   gotchas/jack/peek.js hides the peek. */
.jack-peek-lane {
  position: absolute;
  inset: 0;
  overflow: clip;
  border-radius: inherit;
  pointer-events: none;
}
.jack-peek {
  position: absolute;
  right: 0;
  top: 40%;
  width: calc(var(--sprite-size) / 2);
  translate: 100% 0;
}
/* The rounds of the laugh end before the peek does. */
.jack-peek .character { width: 100%; scale: -1 1; --strip-rounds: 6; }

/* The visit and the peek move only while the system allows motion. */
@media (prefers-reduced-motion: no-preference) {
  .dark-search.lit { --light-x: var(--pointer-x); --light-y: var(--pointer-y); }
  .jack-visit { animation: visit calc(var(--walked-in-and-laughed) + var(--walk-out-time)); }
  .dark-search.sweeping { animation: sweep var(--duration-sweep) var(--ease-in-out); }
  .visit-walk-in { animation: visit-walk-in var(--walk-in-time) var(--ease-linear); }
  .visit-laugh { animation: shown var(--laugh-time) var(--walk-in-time); }
  .visit-walk-out { animation: visit-walk-out var(--walk-out-time) var(--ease-linear) var(--walked-in-and-laughed); }
  .jack-peek { animation: peek var(--peek-time) var(--ease-in-out); }
}
@media (prefers-reduced-motion: reduce) {
  .dark-search { background: var(--lit-background); }
}
:root[data-motion="reduce"] .dark-search { background: var(--lit-background); }
@keyframes sweep {
  0% { --light-x: 15%; --light-y: 20%; }
  35% { --light-x: 80%; --light-y: 35%; }
  70% { --light-x: 30%; --light-y: 80%; }
  100% { --light-x: 70%; --light-y: 50%; }
}
@keyframes visit { from, to { visibility: visible; } }
@keyframes peek { 15%, 85% { translate: 50% 0; } }
@keyframes shown { from, to { opacity: 1; } }
@keyframes visit-walk-in { from { transform: translateX(var(--off-screen)); opacity: 1; } to { opacity: 1; } }
@keyframes visit-walk-out { from { opacity: 1; } to { transform: translateX(var(--off-screen)); opacity: 1; } }

/* --- Sections of text --- */

/* The trick tag is styled by level-select.css, as on the start screen and in the outcome of the demo. The
   :where() keeps the specificity of this rule, which the rules of the finale below rely on. */
.text-section p:not(:where(.trick-tag)) { max-width: var(--measure-text); font: var(--font-lead); color: var(--text-2); }
/* A list that clips its items, marked as dom.js describes for CLIPS_ATTRIBUTE, makes room above and
   below itself for --overhang without moving what is around it. */
.text-items {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-16);
  margin: calc(var(--space-8) - var(--overhang, var(--space-0))) 0 calc(-1 * var(--overhang, var(--space-0)));
  padding: var(--overhang, 0) 0;
  list-style: none;
}
.text-items li {
  padding: var(--space-16) var(--space-20);
  border: var(--border-1) solid var(--line);
  border-left: var(--border-3) solid var(--jack);
  border-radius: var(--radius);
  background: var(--surface);
}

/* --- Timeline --- */

/* On a wide screen the title stands beside the cards and stays below the header while its section is on
   screen. */
@media (width > 760px) {
  .timeline { grid-template-columns: minmax(0, 1fr) minmax(0, 3fr); column-gap: var(--space-32); align-items: start; }
  .timeline-title { grid-row: 1 / span 2; position: var(--rail-title-position); top: var(--header-height, var(--space-72)); font: var(--font-timeline-title); }
}

/* swipe-cards.js marks the dot for the card in view, and gives the row the class "scrolls" while the
   system allows motion. The dots show only then. */
.swipe-dots { display: none; gap: var(--space-6); justify-content: center; }
.swipe-dots span { width: var(--size-dot); height: var(--size-dot); border-radius: 50%; background: var(--line-strong); }
.swipe-dots .current { background: var(--text); }

/* The scrolling row scrolls sideways natively and snaps card by card. The next card shows at the edge,
   so the row reads as one that scrolls, and its scrollbar shows for a mouse. */
.swipe-cards.scrolls {
  display: flex;
  flex-wrap: var(--rail-wrap);
  overflow-x: var(--rail-overflow);
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scrollbar-width: thin;
}
.swipe-cards.scrolls li { flex: 0 0 var(--rail-basis); scroll-snap-align: start; }

/* On a wide screen three cards show side by side, and the fourth shows at the edge. */
@media (width > 760px) {
  .swipe-cards.scrolls li { flex-basis: var(--rail-basis-wide); }
}
.swipe-cards.scrolls + .swipe-dots { display: var(--rail-dots); }

/* Each card of the timeline has its year, then its side in its color, the red of Jack for an attack
   and the green of Shelly for a defense, what happened and the link to its source. */
.timeline-attack { --side: var(--jack); }
.timeline-defense { --side: var(--shelly); }
.text-items .timeline-card { display: grid; gap: var(--space-4); align-content: start; border-left-color: var(--side); }
.timeline-card a { justify-self: start; margin-top: var(--space-4); }
.timeline-year { font-size: var(--font-22); font-weight: 700; }
.timeline-side { font: var(--font-side); color: var(--side); text-transform: var(--case-slogan); }

/* --- Level select --- */

.levels .level-select { margin-top: var(--space-8); }

/* --- Finale --- */

.finale { --layout-gap: var(--space-20); }
.trust-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(var(--width-trust-fact), 100%), 1fr));
  gap: var(--space-16);
  margin: 0;
  padding: 0;
  list-style: none;
}
.trust-fact {
  display: grid;
  gap: var(--space-8);
  align-content: start;
  justify-items: start;
  padding: var(--space-16);
  border: var(--border-1) solid var(--line);
  border-left: var(--border-3) solid var(--shelly);
  border-radius: var(--radius);
  background: var(--surface);
}
.trust-fact p { font: var(--font-body); }
/* The switch of Jack's tricks shows its state beside its label, as the settings do. */
.tricks-row {
  max-width: var(--measure-teaser);
  padding: var(--space-12) var(--space-16);
  border: var(--border-1) solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
}

.text-section .tricks-note { font: var(--font-small); color: var(--muted); max-width: var(--measure-teaser); }

/* --- Phone --- */

@media (width <= 760px) {
  .hero { grid-template-columns: 1fr; --layout-gap: var(--space-32); padding-top: var(--space-40); }
  .dark-search { --area-height: var(--height-dark-area-phone); }
  .jack-visit { --width: calc(var(--sprite-size) / 2); }
  .text-items { grid-template-columns: minmax(0, 1fr); }
}

@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    :root:not([data-motion="reduce"]) .levels .level-card {
      animation: rise-in var(--ease-linear) both;
      animation-timeline: view();
      animation-range: entry 0% entry 60%;
    }
  }
}
@keyframes rise-in { from { opacity: 0; transform: translateY(var(--space-24)); } }
