/* Comic component styles. Task SC-05, spec Part II section 5.2.
 *
 * These are the only visual rules in the system. A story never ships its
 * own CSS: if a page needs something these components cannot express, the
 * component grows a variant here and every existing story gets it too.
 *
 * Every value comes from tokens.css. */

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

/* The site has no global reset, so this system brings its own. Without
 * it a page declared 377px wide renders 423px once its padding and border
 * are added, which is exactly how a comic page ends up wider than the
 * phone holding it. */
.sc-reader,
.sc-reader *,
.sc-reader *::before,
.sc-reader *::after { box-sizing: border-box; }

/* Tilted and overlapping panels lean past their grid cell by design. The
 * page's own padding gives them room; this is the backstop so a lean can
 * never become a sideways scroll on a phone. `clip` rather than `hidden`
 * so it does not create a scroll container and break the sticky toolbar. */
html.sc-html { overflow-x: clip; }

.sc-reader {
  margin: 0;
  padding: 0 0 64px;
  background: var(--ui-bg);
  color: var(--ui-fg);
  font-family: var(--font-ui);
  /* the page body never scrolls sideways, at any width */
  overflow-x: clip;
}

.sc-page {
  position: relative;
  width: min(100% - 2 * var(--gutter), var(--page-max));
  margin: var(--gutter) auto;
  padding: clamp(18px, 4vw, 32px);
  background: var(--sc-paper);
  border: 5px solid var(--sc-ink);
  border-radius: 10px;
  box-shadow: 0 14px 0 rgba(0, 0, 0, .28), 0 30px 60px rgba(0, 0, 0, .35);
  /* the faint tooth of newsprint */
  background-image: radial-gradient(rgba(0, 0, 0, .045) 1px, transparent 1px);
  background-size: 4px 4px;
}

.sc-page__number {
  position: absolute;
  right: 10px;
  bottom: 6px;
  font-family: var(--font-display);
  font-size: 16px;
  letter-spacing: 1px;
  color: #b3b8c4;
}

/* --- the 12 column grid ----------------------------------------------- */

.sc-grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: var(--gutter);
}

/* --- panels ------------------------------------------------------------ */

.sc-panel {
  position: relative;
  grid-column: span 12;
  border: var(--panel-border);
  border-radius: 4px;
  background: #fff;
  padding: clamp(12px, 2.4vw, 18px);
  /* text never touches a panel border: 10px is the floor at every width */
  min-height: 0;
  /* "Antidisestablishmentarianism" in a four-column panel has to wrap,
   * not spill over the border into the panel next door. */
  overflow-wrap: break-word;
  word-break: break-word;
}

/* Stands in for a drawing that has not been moved into the art bucket
 * yet. A labelled frame reads as a promise; an empty one reads as a bug. */
.sc-art-placeholder {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 12px;
  text-align: center;
  font-family: var(--font-balloon);
  font-size: var(--text-small);
  color: #fff;
  opacity: .7;
}

/* an art panel and its caption travel together */
.sc-figure {
  grid-column: span 12;
  margin: 0;
  display: flex;
  flex-direction: column;
}

.sc-panel--art {
  padding: 0;
  overflow: hidden;
  background: var(--sc-blue-dark);
  aspect-ratio: 16 / 9;
}

.sc-panel--art.is-square { aspect-ratio: 1 / 1; }
.sc-panel--art.is-tall   { aspect-ratio: 4 / 5; }

.sc-panel--plain {
  border: none;
  background: transparent;
  padding: 0;
}

/* Angled and overlapping shapes. Kept to two degrees: any more and the
 * text inside starts to feel like it is sliding off the page. */
.sc-panel--tilt-left  { transform: rotate(-2deg); }
.sc-panel--tilt-right { transform: rotate(2deg); }
.sc-panel--jagged {
  clip-path: polygon(0 3%, 12% 0, 34% 4%, 61% 0, 88% 3%, 100% 0,
                     100% 97%, 76% 100%, 48% 96%, 22% 100%, 0 97%);
}

/* fx layers */
.sc-fx-halftone::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: radial-gradient(var(--sc-ink) 1.2px, transparent 1.2px);
  background-size: 6px 6px;
  opacity: .08;
}

.sc-fx-speedlines::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: repeating-linear-gradient(
    100deg, rgba(255, 255, 255, .55) 0 2px, transparent 2px 9px);
  opacity: .5;
}

/* --- headings ---------------------------------------------------------- */

.sc-eyebrow {
  margin: 0;
  font-family: var(--font-display);
  font-size: 18px;
  letter-spacing: 2px;
  text-align: center;
  color: var(--sc-blue);
}

.sc-title {
  margin: 2px 0 20px;
  font-family: var(--font-display);
  font-size: clamp(28px, 7vw, 46px);
  line-height: .95;
  text-align: center;
  color: var(--sc-ink);
  text-shadow: 3px 3px 0 var(--sc-yellow);
}

/* --- prose and captions ------------------------------------------------ */

.sc-prose p {
  margin: 0 0 15px;
  font-family: var(--font-balloon);
  font-size: var(--text-page);
  line-height: var(--line-page);
  color: #23272f;
  /* 38 to 62 characters is the comfortable measure for a new reader */
  max-width: 62ch;
}

.sc-prose p.is-big {
  font-size: calc(var(--text-page) * 1.15);
  font-weight: 700;
  text-align: center;
  color: var(--sc-blue-dark);
}

.sc-prose p.has-dropcap::first-letter {
  float: left;
  padding: 6px 10px 0 0;
  font-family: var(--font-display);
  font-size: 3.2em;
  line-height: .8;
  color: var(--sc-red);
}

.sc-caption {
  margin: 0 0 12px;
  padding: 10px 14px;
  background: var(--sc-caption);
  border: 2px solid var(--sc-ink);
  font-family: var(--font-balloon);
  font-size: var(--text-page);
  line-height: var(--line-page);
  font-variant-caps: small-caps;
}

.sc-figcaption {
  margin-top: 8px;
  font-family: var(--font-balloon);
  font-size: var(--text-small);
  text-align: center;
  color: var(--ui-muted);
}

/* --- balloons ----------------------------------------------------------
 * Four kinds, per the spec: talking, shouting, thinking, villain. */

.sc-balloon {
  position: relative;
  display: inline-block;
  max-width: 62%;
  margin: 0 0 14px;
  padding: 8px 12px;
  background: #fff;
  border: 3px solid var(--sc-ink);
  border-radius: var(--radius-balloon);
  font-family: var(--font-balloon);
  font-size: var(--text-page);
  font-weight: 700;
  line-height: 1.25;
  box-shadow: 2px 2px 0 rgba(0, 0, 0, .25);
}

.sc-balloon__tail {
  position: absolute;
  bottom: -18px;
  width: 0;
  height: 0;
  border: 11px solid transparent;
  border-top-color: var(--sc-ink);
}

.sc-balloon__tail::after {
  content: "";
  position: absolute;
  top: -13px;
  left: -8px;
  border: 8px solid transparent;
  border-top-color: #fff;
}

.sc-balloon--left  .sc-balloon__tail { left: 18px; }
.sc-balloon--right .sc-balloon__tail { right: 18px; }

.sc-balloon--shout {
  border-radius: 0;
  clip-path: polygon(0 12%, 7% 0, 22% 10%, 38% 0, 55% 9%, 72% 0, 88% 11%, 100% 4%,
                     96% 46%, 100% 88%, 84% 100%, 64% 90%, 44% 100%, 26% 91%,
                     8% 100%, 0 86%);
  padding: 16px 22px;
  text-transform: uppercase;
}

.sc-balloon--thought {
  border-radius: 46% 54% 50% 50% / 52% 48% 52% 48%;
}

.sc-balloon--thought .sc-balloon__tail {
  border: none;
  bottom: -22px;
  left: 22px;
  width: 12px;
  height: 12px;
  background: #fff;
  box-shadow: 0 0 0 3px var(--sc-ink), -12px 12px 0 -3px #fff,
              -12px 12px 0 0 var(--sc-ink);
  border-radius: 50%;
}

.sc-balloon--thought .sc-balloon__tail::after { content: none; }

/* Villains get the icicle edge and the dark fill. Their words should look
 * colder than everyone else's before you have read one of them. */
.sc-balloon--villain {
  background: var(--sc-blue-dark);
  color: #fff;
  border-color: var(--sc-ink);
  clip-path: polygon(0 0, 100% 0, 100% 82%, 92% 100%, 84% 84%, 74% 98%,
                     64% 84%, 54% 97%, 44% 84%, 34% 99%, 24% 84%, 14% 97%,
                     6% 84%, 0 96%);
  padding-bottom: 22px;
}

.sc-balloon--villain .sc-balloon__tail { display: none; }

/* --- action words ------------------------------------------------------
 * KRAKOOM. Doubles as the sound button when the panel names an SFX. */

.sc-action {
  display: inline-block;
  margin: 4px 10px 4px 0;
  padding: 0;
  border: 0;
  background: none;
  font-family: var(--font-display);
  font-size: clamp(34px, 9vw, 56px);
  line-height: 1;
  letter-spacing: 2px;
  color: var(--sc-yellow);
  text-shadow:
     3px  3px 0 var(--sc-ink),
    -2px -2px 0 var(--sc-ink),
     2px -2px 0 var(--sc-ink),
    -2px  2px 0 var(--sc-ink),
     7px  7px 0 var(--sc-red);
  transform: rotate(-8deg);
  cursor: default;
}

.sc-action--sm { font-size: clamp(24px, 6vw, 34px); }
.sc-action--lg { font-size: clamp(42px, 12vw, 72px); }

.sc-action--impact_red    { color: var(--sc-red);    text-shadow: 3px 3px 0 var(--sc-ink), 7px 7px 0 var(--sc-yellow); }
.sc-action--impact_orange { color: var(--sc-orange); text-shadow: 3px 3px 0 var(--sc-ink), 7px 7px 0 var(--sc-yellow); }
.sc-action--impact_cyan   { color: #2fe6ff;          text-shadow: 3px 3px 0 var(--sc-ink), 7px 7px 0 var(--sc-blue-dark); }
.sc-action--splash_blue   { color: var(--sc-blue);   text-shadow: 3px 3px 0 var(--sc-ink), 7px 7px 0 #fff; }
.sc-action--zap_yellow    { color: var(--sc-yellow); text-shadow: 3px 3px 0 var(--sc-ink), 7px 7px 0 var(--sc-red); }

/* When it plays a sound it is a button, so it has to look and behave like
 * one: big enough to hit, and it pulses to invite the tap. */
.sc-action[data-sfx] {
  cursor: pointer;
  min-width: var(--tap-target-min);
  min-height: var(--tap-target-min);
  animation: sc-pulse 2s ease-in-out infinite;
}

@keyframes sc-pulse {
  0%, 100% { transform: rotate(-8deg) scale(1); }
  50%      { transform: rotate(-8deg) scale(1.06); }
}

/* --- read-along --------------------------------------------------------
 * Exactly one word carries .is-speaking at any moment. */

.sc-w {
  border-radius: 4px;
  transition: background-color 120ms ease, transform 120ms ease;
}

.sc-w.is-speaking {
  background: var(--highlight);
  box-shadow: var(--highlight-glow);
  transform: scale(1.06);
  display: inline-block;
}

/* Tapping a word to hear it is a real control, so it gets a real target. */
.sc-w[data-w] {
  cursor: pointer;
  padding: 2px 1px;
}

/* --- guided mode -------------------------------------------------------- */

.sc-page.is-guided .sc-panel        { opacity: .25; transition: opacity 200ms ease; }
.sc-page.is-guided .sc-panel.is-lit { opacity: 1; }

/* --- power words --------------------------------------------------------- */

.sc-powerword {
  background: linear-gradient(transparent 62%, rgba(106, 27, 154, .28) 0);
  border-radius: 3px;
  cursor: pointer;
  font-weight: 700;
}

.sc-powerword.is-collected {
  background: linear-gradient(transparent 62%, rgba(46, 125, 50, .32) 0);
}

/* --- wide things scroll inside themselves, never the page ---------------- */

.sc-scroll-x {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

/* --- motion ------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .sc-action[data-sfx] { animation: none; }
  .sc-w                { transition: none; }
  .sc-page             { transition: none; }
}
