/* ==========================================================================
   ACT 3 · KURALLAR.  Beat: netlik, settling into sakinlik.
   Four states, not six. Six statements crossing through one frame is six
   beats for one idea, so each state now carries a whole step and is anchored
   by an object from the game rather than by typography alone:

     a  kim, ne kadar     two opening hands, two cards each
     b  el                the card front with its real QR, hanging over the
                          gap in the timeline that its year belongs to
     c  iki özel kart     the two printed special cards, set down at angles
     d  kapanış           nothing. The act ends in authored silence.

   Every object is printed on the same stock as the deck (--tt-paper) with the
   same ink, so the pictures belong to the printer that made the cards. One
   accent, already on the paper. No icon set: the two marks are drawn by hand
   in the markup.

   THE FIELD RULE. The states share one frame, so the crossings have to stay
   readable. Every state is anchored either to the top of the field or to its
   bottom, and the act alternates: a top, b bottom, c top, d bottom. Two
   consecutive states therefore never share a vertical anchor at ANY width,
   which is what keeps them apart once the columns collapse at 860px. (The
   six-state cut had a and b both centred, which printed one statement over
   the other on a phone for the whole crossover.) What is left to keep true is
   a height budget: a top state plus the bottom state it crosses with must fit
   the field. The tight pair is c with b, so the pictures are sized off the
   viewport HEIGHT, which is the dimension that binds, and both states are
   trimmed again at 860px and at 620px.

   THE CUE ARITHMETIC. Neighbouring windows are built so their ramps coincide
   exactly: while one state is on its plateau the next is at zero, and the
   whole overlap is a single complementary dissolve. smoothstep is symmetric,
   s(t) + s(1 - t) = 1, so the two opacities sum to 1 across the crossing and
   the stage never dips towards an empty frame.

     a  0    0.28  0    0.43     full 0    .. 0.16    dissolve 0.16 .. 0.28
     b  0.16 0.60  0.27 0.27     full 0.28 .. 0.48    dissolve 0.48 .. 0.60
     c  0.48 0.86  0.32 0.32     full 0.60 .. 0.74    dissolve 0.74 .. 0.86
     d  0.74 1     0.46 0        full 0.86 .. 1

   a is the greet form (third value 0), because a pinned act whose first cue
   ramps in shows an empty stage for a full viewport before its own progress
   leaves 0. d ends at 1 and therefore MUST pass an explicit rampOut of 0: the
   default 0.3 fades the closing line to nothing exactly at p = 1 and the act
   ends on an empty screen.

   Everything continuous is driven off --sc-p, which the engine publishes on
   the section. The local default below is the pre-mount fallback: the
   engine's inline value always wins over it.
   ========================================================================== */

.rules {
  --sc-p: 0;
  /* The ground is the drifted page canvas (#1C1511). The stage stays
     transparent so the drift crossfade from the previous act reads. */
  background: transparent;
}

/* .sc-stage (engine) already gives this element sticky + 100svh + overflow
   clip. All this adds is the stacking context for the veil and the frame. */
.rules-stage {
  display: grid;
  grid-template-columns: 100%;
  isolation: isolate;
}

/* --- the settling ground ------------------------------------------------
   The act ends darker than it began. Opacity only, driven by act progress,
   so the closing line sits on the quietest surface on the page. It reaches
   its floor at p = 0.90, just after the closing line comes to full, and
   holds there to the end. */
.rules-veil {
  grid-area: 1 / 1;
  background: #0A0705;
  pointer-events: none;
  opacity: clamp(0, calc((var(--sc-p, 0) - 0.6) * 2.067), 0.62);
}

.rules-frame {
  grid-area: 1 / 1;
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  row-gap: clamp(1.4rem, 3.4vh, 2.6rem);
  padding-block: clamp(4.6rem, 11vh, 8rem) clamp(2.2rem, 5vh, 3.4rem);
  min-height: 0;
}

/* --- the states ---------------------------------------------------------
   One 12 column field, one row. Each state claims its columns and its
   anchor, and align-self start / end is the top and the bottom of the
   field. */
.rules-states {
  grid-row: 1;
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: clamp(0.9rem, 1.8vw, 1.5rem);
  min-height: 0;
}

.rules-state {
  grid-row: 1;
  display: grid;
  align-items: center;
  gap: clamp(1.3rem, 3vh, 2.4rem);
  /* The engine writes opacity + transform here. Never add a transform of
     your own to a cue node. */
  will-change: opacity, transform;
}

/* Text and picture share a line on the wide field: the text takes what is
   left, the picture stays at its printed size. */
.rules-state--a,
.rules-state--b { grid-template-columns: minmax(0, 1fr) auto; }
/* c is the one that flips, so the two cards are the first thing you meet and
   the line beside them names them. Source order stays text first, which is
   also the order the stacked layout wants. */
.rules-state--c { grid-template-columns: auto minmax(0, 1fr); }
.rules-state--c > .rules-said { grid-column: 2; grid-row: 1; }
.rules-state--c > .rules-pic  { grid-column: 1; grid-row: 1; }

/* Upper field. */
.rules-state--a { grid-column: 1 / span 12; align-self: start; }
.rules-state--c { grid-column: 1 / span 12; align-self: start; }
/* Lower field. Both stop short of the right edge: the page's corner disc is
   fixed down there and sits on top of anything that reaches it. */
.rules-state--b { grid-column: 1 / span 9; align-self: end; }
.rules-state--d { grid-column: 1 / span 7; align-self: end; }

.rules-said {
  display: grid;
  gap: clamp(0.85rem, 1.9vh, 1.35rem);
  align-content: center;
}

/* --- the spoken line ----------------------------------------------------
   #F3EADC on #1C1511 is 15.12:1, and the veil only darkens the ground
   further. Each state keeps its own width and weight on the variable axes so
   the three statements do not read as three renderings of one template. */
.rules-head {
  color: var(--sc-ink);
  max-width: 17ch;
}
.rules-head--a { font-variation-settings: "wght" 780, "wdth" 120; max-width: 13ch; }
.rules-head--b { font-variation-settings: "wght" 820, "wdth" 104; max-width: 14ch; }
.rules-head--c { font-variation-settings: "wght" 800, "wdth" 96;  max-width: 15ch; }

/* The supporting line. #A28E77 on #1C1511 is 5.73:1, and the veil only
   darkens the ground further, so it never drops below that. */
.rules-note {
  font-family: var(--sc-font-text);
  font-size: clamp(0.98rem, 1.1vw, 1.1rem);
  line-height: 1.6;
  letter-spacing: 0.005em;
  color: var(--sc-ink-soft);
  max-width: 46ch;
  text-wrap: pretty;
  margin: 0;
}

/* ======================================================= printed objects ==
   All three pictures are made of one part: a piece of card stock with ink on
   it. .tt-card carries the paper, the raking light and the drop shadow; the
   print sits above the sheen, which otherwise takes small type down to
   2.6:1 in the bright corner.

   The stock is sized off viewport height (with a vw ceiling for narrow
   windows) because the act's constraint is vertical: two states have to fit
   the field together. Width follows from the deck's own 5:7 proportion. */
.rules-yc > *,
.rules-face > *,
.rules-pc > * { position: relative; z-index: 1; }

/* A card seen the way it lies in a timeline: the year, and nothing else.
   #191108 on #EDE2CE is 14.55:1. */
.rules-yc,
.rules-slot {
  flex: 0 0 auto;
  block-size: min(clamp(3.9rem, 9.5vh, 6.2rem), 17vw);
  inline-size: auto;
  aspect-ratio: 5 / 7;
  border-radius: 3px;
}
.rules-yc {
  display: grid;
  align-content: end;
  padding: 0.36rem 0.42rem 0.4rem;
}
.rules-yc__y {
  display: block;
  font-variation-settings: "wght" 820, "wdth" 76;
  font-size: clamp(0.8rem, 1vw, 1rem);
  line-height: 0.9;
  color: var(--tt-paper-ink);
}

/* --- a · two opening hands ---------------------------------------------
   Two players, two cards each, set down facing one another. The pairs are
   fanned and tilted rather than laid out in a row, so they read as two hands
   on a table and not as a second timeline. The angles are variables so a
   breakpoint, or reduced motion, can flatten them without restating this. */
.rules-pic--hands {
  display: flex;
  align-items: center;
  gap: clamp(1.1rem, 2.4vw, 2.2rem);
}
.rules-hand { display: flex; }
.rules-hand > .rules-yc + .rules-yc {
  margin-inline-start: clamp(-1.5rem, -1.1vw, -0.7rem);
  transform: rotate(var(--rules-fan, 7deg));
  transform-origin: 0 100%;
}
.rules-hand--one { transform: rotate(var(--rules-h1-rot, -3.4deg)) translateY(0.35rem); }
.rules-hand--two { transform: rotate(var(--rules-h2-rot, 2.6deg)) translateY(-0.45rem); }

/* --- b · the round ------------------------------------------------------
   The card front, and the opening it belongs in. The face is centred over
   the row and the empty slot is the middle item of that row at every width,
   so the card always hangs over its own place among the years. */
.rules-pic--round {
  --rules-drop: clamp(0.85rem, 2.2vh, 1.5rem);
  display: grid;
  justify-items: center;
  row-gap: var(--rules-drop);
}

.rules-face {
  position: relative;
  block-size: min(clamp(5.6rem, 15vh, 10.6rem), 26vw);
  inline-size: auto;
  aspect-ratio: 5 / 7;
  border-radius: 3px;
  padding: clamp(0.4rem, 0.6vw, 0.6rem);
  display: grid;
  place-items: center;
  transform: rotate(var(--rules-face-rot, -2.6deg));
}
/* The drop into the slot: a hairline across the gap and nothing else. The
   card is already over the opening; this only says so out loud. */
.rules-face::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 100%;
  inline-size: 0;
  block-size: var(--rules-drop);
  border-left: 1px dashed color-mix(in oklab, var(--sc-ink) 26%, transparent);
}
.rules-face__qr {
  inline-size: 100%;
  block-size: auto;
  color: var(--tt-paper-ink);
  shape-rendering: crispEdges;
}

/* The timeline itself: years ascending, all of them sitting on one line. */
.rules-tl {
  display: flex;
  align-items: flex-end;
  gap: clamp(0.3rem, 0.6vw, 0.55rem);
  padding: 0 clamp(0.4rem, 0.8vw, 0.7rem) clamp(0.42rem, 0.9vh, 0.7rem);
  border-bottom: 1px solid var(--tt-line);
}

/* The opening. Dashed, empty, exactly a card wide: the one thing on the
   stage made of absence. The question mark is #A28E77, 5.73:1 on the
   ground. */
.rules-slot {
  border: 1px dashed color-mix(in oklab, var(--sc-ink) 30%, transparent);
  display: grid;
  place-items: center;
}
.rules-slot__q {
  font-variation-settings: "wght" 820, "wdth" 76;
  font-size: clamp(0.95rem, 1.2vw, 1.2rem);
  line-height: 1;
  color: var(--sc-ink-soft);
}

/* --- c · the two special cards -----------------------------------------
   Playing-card proportion, printed rule, and the two of them set down at
   different angles and heights: two objects on a table, not two tiles in a
   row. These carry running text, so they stay width-driven (the rule has to
   have room to wrap) with a viewport-height ceiling. */
.rules-pic--deck {
  display: flex;
  align-items: flex-start;
  gap: clamp(0.7rem, 1.4vw, 1.1rem);
}
.rules-pc {
  flex: 0 0 auto;
  inline-size: min(clamp(8.4rem, 10.6vw, 10.6rem), 22vh);
  aspect-ratio: 5 / 7;
  padding: clamp(0.75rem, 1.1vw, 1.05rem);
  display: grid;
  grid-template-rows: auto 1fr auto;
  gap: 0.45rem;
}
.rules-pc--ch { transform: rotate(var(--rules-ch-rot, -3.2deg)); }
.rules-pc--jk { transform: rotate(var(--rules-jk-rot, 2.4deg)) translateY(var(--rules-jk-drop, 1.2rem)); }

.rules-pc__mark {
  color: var(--tt-accent-deep);   /* 5.39:1 on the stock */
  inline-size: clamp(1.45rem, 1.95vw, 1.9rem);
  block-size: auto;
  display: block;
  align-self: start;
}
.rules-pc__name {
  font-family: var(--sc-font-display);
  font-variation-settings: "wght" 800, "wdth" 96;
  font-size: clamp(0.94rem, 1.15vw, 1.1rem);
  letter-spacing: -0.01em;
  line-height: 1;
  color: var(--tt-paper-ink);     /* 14.55:1 on the stock */
  align-self: end;
  margin: 0;
}
.rules-pc__rule {
  font-family: var(--sc-font-text);
  font-size: clamp(0.74rem, 0.86vw, 0.83rem);
  line-height: 1.4;
  color: var(--tt-paper-soft);    /* 5.13:1 on the stock */
  margin: 0;
  text-wrap: pretty;
}

/* --- d · the closing line ----------------------------------------------
   Small, alone, on the darkest ground the act reaches. data-sc-rise="0"
   keeps it from moving at all: it simply arrives. #A28E77 over the veiled
   ground is 8.83:1, and 5.73:1 on the bare surface before the veil. */
.rules-close {
  font-family: var(--sc-font-text);
  font-size: clamp(1rem, 1.25vw, 1.18rem);
  line-height: 1.55;
  color: var(--sc-ink-soft);
  max-width: 46ch;
  margin: 0;
}

/* --- the rule line that grows ------------------------------------------
   The act's one continuous element. It draws itself across the foot of the
   stage as the act runs, completes exactly as the closing line comes up at
   0.86, and is gone by then, so the last thing on screen has nothing moving
   beside it. */
.rules-rule {
  grid-row: 2;
  height: 1px;
  background: var(--tt-line);
  opacity: clamp(0, calc((0.86 - var(--sc-p, 0)) * 8.333), 1);
}
.rules-rule__grow {
  display: block;
  height: 100%;
  background: color-mix(in oklab, var(--sc-accent) 62%, var(--sc-surface));
  transform: scaleX(clamp(0, calc(var(--sc-p, 0) * 1.163), 1));
  transform-origin: 0 50%;
}

/* --- tablet -------------------------------------------------------------
   The columns collapse, so the alternating anchor is the only thing keeping
   two crossing states apart, and the height budget becomes the whole game.
   At 860x900 the field is about 763px; c and b together come to about 705,
   which is the closest the act gets on a normal window. */
@media (max-width: 860px) {
  .rules-frame {
    padding-block: clamp(4rem, 8vh, 5.6rem) clamp(2rem, 4.5vh, 3rem);
    row-gap: clamp(1.2rem, 2.6vh, 2rem);
  }

  .rules-state {
    grid-template-columns: minmax(0, 1fr);
    justify-items: start;
    gap: clamp(1.05rem, 2.2vh, 1.6rem);
  }
  .rules-state--a,
  .rules-state--b,
  .rules-state--c,
  .rules-state--d { grid-column: 1 / -1; }
  .rules-state--c > .rules-said,
  .rules-state--c > .rules-pic { grid-column: 1; grid-row: auto; }

  .rules-head { font-size: clamp(1.95rem, 4.4vw, 3.3rem); }
  .rules-head--a,
  .rules-head--b,
  .rules-head--c { max-width: 18ch; }

  .rules-pic--round { --rules-drop: clamp(0.7rem, 2vh, 1.2rem); }
  .rules-face { block-size: min(clamp(5rem, 12.5vh, 9rem), 24vw); }
  .rules-yc,
  .rules-slot { block-size: min(clamp(3.5rem, 8vh, 5.4rem), 15vw); }
  .rules-pc { inline-size: min(clamp(6.9rem, 10vw, 9.4rem), 20vh); }
  .rules-pc__rule { font-size: 0.76rem; }
}

/* --- phone --------------------------------------------------------------
   At 390x844 the field is about 711px and the crossing pair comes to about
   660. The two outer cards leave the timeline here, which keeps the opening
   in the middle of the row (so the face still hangs over it) and the whole
   picture inside the gutter. */
@media (max-width: 620px) {
  .rules-frame { padding-block: clamp(3.8rem, 9vh, 5.2rem) clamp(1.6rem, 4vh, 2.4rem); }
  .rules-state { gap: clamp(0.9rem, 2vh, 1.3rem); }

  .rules-head { font-size: clamp(1.85rem, 8vw, 2.5rem); }
  .rules-head--a,
  .rules-head--b,
  .rules-head--c { max-width: 15ch; }

  .rules-note { font-size: 0.95rem; max-width: 36ch; }

  .rules-yc--edge { display: none; }
  .rules-tl { gap: 0.35rem; }

  .rules-pc { inline-size: min(clamp(6.2rem, 28vw, 8rem), 20vh); padding: 0.65rem; }
  .rules-pc__name { font-size: 0.9rem; }
  .rules-pc__rule { font-size: 0.7rem; line-height: 1.36; }
  .rules-pic--deck { --rules-ch-rot: -2.2deg; --rules-jk-rot: 1.8deg; --rules-jk-drop: 0.6rem; }

  .rules-close { max-width: 24ch; }
  /* The corner disc drops to a 4.2rem watermark down here and the two lower
     states run the full width. Lift them clear of it. */
  .rules-state--b,
  .rules-state--d { padding-bottom: 1.1rem; }
}

/* --- short viewports ----------------------------------------------------
   The stage is clipped at 100svh, so a laptop in a shallow window must not
   lose the bottom of a state. The stock already follows viewport height, so
   only the frame and the gaps need saying. */
@media (max-height: 820px) {
  .rules-frame { padding-block: clamp(3.6rem, 8vh, 4.6rem) clamp(1.4rem, 3.5vh, 2.2rem); }
  .rules-state { gap: clamp(0.8rem, 1.8vh, 1.3rem); }
  .rules-said { gap: clamp(0.7rem, 1.5vh, 1.1rem); }
}
/* Short AND narrow is the hardest window the act meets (a 375x667 phone, or a
   tablet-width browser in a shallow one): the states are stacked, so their
   heights add, and there is the least room to add them in. Type and stock
   both step down a rung. */
@media (max-width: 860px) and (max-height: 820px) {
  .rules-frame {
    padding-block: clamp(3.2rem, 7vh, 4rem) clamp(1.2rem, 3vh, 1.8rem);
    row-gap: clamp(1rem, 2.2vh, 1.6rem);
  }
  .rules-head { font-size: clamp(1.7rem, 3.7vw, 2.6rem); }
  .rules-note { font-size: 0.92rem; line-height: 1.5; }
  .rules-face { block-size: min(clamp(4.4rem, 10.5vh, 8rem), 22vw); }
  .rules-yc,
  .rules-slot { block-size: min(clamp(3.2rem, 7vh, 4.8rem), 14vw); }
  .rules-pc { inline-size: min(clamp(6rem, 26vw, 8.6rem), 15vh); }
}

/* --- reduced motion -----------------------------------------------------
   Fewer and gentler, not zero. The engine already drops the cue rise; the
   opacity crossfade that carries the reading order stays, and every state is
   still reachable by scrolling. The printed objects give up their angles so
   nothing reads as mid-motion. */
@media (prefers-reduced-motion: reduce) {
  .rules-pic--hands { --rules-h1-rot: 0deg; --rules-h2-rot: 0deg; --rules-fan: 0deg; }
  .rules-hand > .rules-yc + .rules-yc { margin-inline-start: 0.3rem; }
  .rules-hand--one,
  .rules-hand--two { transform: none; }
  .rules-face { --rules-face-rot: 0deg; }
  .rules-pic--deck { --rules-ch-rot: 0deg; --rules-jk-rot: 0deg; --rules-jk-drop: 0rem; }
}
