/* ==========================================================================
   singmuse.app — static showcase for the Iliad visual novel.

   Palette and type are lifted from the app itself (see vnengine/lib and
   vnengine/assets/fonts) so the site and the game read as one thing. The
   design is deliberately dark-only; there is no light variant.
   ========================================================================== */

@font-face {
  font-family: 'Cinzel';
  src: url('/fonts/Cinzel-VariableFont_wght.ttf') format('truetype-variations');
  font-weight: 400 900;
  font-display: swap;
}
@font-face {
  font-family: 'Lora';
  src: url('/fonts/Lora-VariableFont_wght.ttf') format('truetype-variations');
  font-weight: 400 700;
  font-display: swap;
}
/* Lato ships as statics, not a variable font, so the four faces we actually
   use are declared by hand. */
@font-face {
  font-family: 'Lato';
  src: url('/fonts/Lato-Regular.ttf') format('truetype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Lato';
  src: url('/fonts/Lato-Italic.ttf') format('truetype');
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: 'Lato';
  src: url('/fonts/Lato-Bold.ttf') format('truetype');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Lato';
  src: url('/fonts/Lato-BoldItalic.ttf') format('truetype');
  font-weight: 700;
  font-style: italic;
  font-display: swap;
}

:root {
  --ink:        #0d0a08;
  --ink-lift:   #14100c;
  --ink-deep:   #080605;
  --gold:       #ffd77a;
  --gold-soft:  #e8c77a;
  --gold-deep:  #b98f3e;
  --parchment:  #f7e7be;
  /* The one cool note in a warm palette — near the gold's true complement, but
     pulled towards lapis, the blue that actually sat next to gold in the
     ancient world. Used for a single word; anything more and it fights. */
  --lapis:      #8fbfe8;
  --text:       #e8dcc4;
  --muted:      rgba(232, 220, 196, 0.60);
  --hairline:   rgba(232, 199, 122, 0.22);

  --display: 'Cinzel', 'Iowan Old Style', Georgia, serif;
  /* Body is sans; swap back to 'Lora', Georgia, serif for the serif setting. */
  --body:    'Lato', system-ui, -apple-system, 'Segoe UI', Helvetica, Arial, sans-serif;

  --gutter: clamp(1.25rem, 4vw, 3.5rem);
  --shell:  76rem;
  --cta-w:  19.5rem;   /* badge row, divider and button all measure to this */
}

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--ink);
  color: var(--text);
  font-family: var(--body);
  font-size: 16px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img { max-width: 100%; display: block; }

a { color: var(--gold); }

.sr-only {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  clip-path: inset(50%); overflow: hidden; white-space: nowrap;
}

.kicker {
  margin: 0;
  font-family: var(--display);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--gold-deep);
}

/* ==========================================================================
   HERO
   The hero is a column of three rows: brand, stage, pitch. Brand and pitch
   are their natural height; the stage takes everything left over and the
   16:9 frame inside shrinks to fit it. That is what holds the whole section
   to a single screen on desktop, whatever the window height.
   ========================================================================== */

.hero {
  position: relative;
  padding: clamp(1rem, 2.2vh, 1.75rem) var(--gutter) clamp(1.25rem, 3vh, 2rem);
  display: flex;
  flex-direction: column;
  gap: clamp(0.75rem, 2vh, 1.5rem);
  background:
    radial-gradient(120% 80% at 50% 0%, rgba(185, 143, 62, 0.16), transparent 62%),
    radial-gradient(90% 60% at 50% 100%, rgba(185, 143, 62, 0.07), transparent 70%),
    var(--ink);
}

/* One-screen desktop hero. `height` (not `min-height`) is deliberate: the flex
   column needs a definite height before .stage will shrink, and before the
   frame's container query has anything to measure. Below this breakpoint the
   hero just flows and the page scrolls. The matching .stage/.frame overrides
   live after the carousel rules further down, where source order lets them win. */
@media (min-width: 900px) and (min-height: 620px) {
  .hero { height: 100svh; }
}

.brand {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex: 0 0 auto;
}
.brand-mark {
  width: clamp(28px, 3.4vh, 38px);
  height: auto;
  border-radius: 22%;
  box-shadow: 0 0 0 1px var(--hairline);
}
.brand-name {
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(0.95rem, 1.9vh, 1.15rem);
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--parchment);
}

/* --- carousel ------------------------------------------------------------ */

.stage {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
}

.carousel {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  align-items: center;
  justify-content: center;
}

.frame {
  position: relative;
  width: min(100%, 68rem);
  aspect-ratio: 16 / 9;
  max-height: 100%;
  margin: auto;
  border: 1px solid var(--hairline);
  border-radius: 6px;
  overflow: hidden;
  background: var(--ink-deep);
  box-shadow: 0 24px 70px -30px rgba(0, 0, 0, 0.95),
              0 0 0 1px rgba(0, 0, 0, 0.6);
}

.slides { position: absolute; inset: 0; }

.slide {
  position: absolute;
  inset: 0;
  margin: 0;
  opacity: 0;
  transition: opacity 600ms ease;
  pointer-events: none;
}
.slide.is-active { opacity: 1; pointer-events: auto; }
.slide img { width: 100%; height: 100%; object-fit: cover; }

.nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  display: grid;
  place-items: center;
  width: 2.6rem;
  height: 2.6rem;
  padding: 0;
  border: 1px solid var(--hairline);
  border-radius: 50%;
  background: rgba(13, 10, 8, 0.62);
  color: var(--gold);
  cursor: pointer;
  opacity: 0;
  transition: opacity 200ms ease, background 200ms ease;
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
}
.nav svg { width: 1.15rem; height: 1.15rem; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.nav.prev { left: 0.75rem; }
.nav.next { right: 0.75rem; }
.nav:hover { background: rgba(13, 10, 8, 0.88); }
.carousel:hover .nav,
.nav:focus-visible { opacity: 1; }

/* Touch devices get no hover, so the arrows would never appear. */
@media (hover: none) {
  .nav { opacity: 1; }
}

.dots {
  display: flex;
  gap: 0.55rem;
  flex: 0 0 auto;
}
.dot {
  width: 0.5rem;
  height: 0.5rem;
  padding: 0;
  border: 1px solid var(--gold-deep);
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
  transition: background 200ms ease, transform 200ms ease;
}
.dot[aria-selected="true"] { background: var(--gold); transform: scale(1.15); }

/* Desktop counterpart to the `height: 100svh` hero above. Placed here so it
   overrides the .frame defaults on source order. The stage becomes a size
   container, and the frame takes whichever runs out first: the available
   width, our max, or the height the stage can spare at 16:9 (less the dot
   row it has to share the space with). */
@media (min-width: 900px) and (min-height: 620px) {
  .stage { container-type: size; }
  .frame {
    flex: 0 0 auto;
    width: min(100%, 68rem, calc((100cqh - 1.6rem) * 16 / 9));
    max-height: none;
  }
}

/* --- pitch --------------------------------------------------------------- */

/* Shoulders line up with the carousel. The frame's width is decided by the
   height left over (see the container query above), so CSS alone cannot know
   it here — main.js measures the frame and publishes --frame-w. The 68rem
   fallback is the frame's own cap, which is what applies without scripting. */
.pitch {
  flex: 0 0 auto;
  width: 100%;
  max-width: var(--frame-w, 68rem);
  /* Breathing room off the dot row above and the fold below. On desktop this
     comes out of the stage, so the carousel gives the space up rather than the
     hero growing past one screen. */
  margin: clamp(0.6rem, 1.9vh, 1.5rem) auto;
  display: grid;
  gap: clamp(1rem, 3vw, 2.5rem);
  align-items: start;
}

/* Copy on the left, calls to action on the right: the shorter the pitch, the
   more height is left for the carousel above it. */
/* The CTA track is a stated width rather than `auto`: the badges are sized by
   percentage now, so an intrinsic track would size itself to the artwork's
   natural pixel width and starve the copy beside it. */
/* Top-aligned, not centred: the CTA column grows downwards when the unsupported
   browser notice appears, and centring would slide the copy down with it. */
@media (min-width: 900px) {
  .pitch {
    grid-template-columns: minmax(0, 1fr) var(--cta-w);
    align-items: start;
  }
}

/* Three beats, not four stacked lines: eyebrow, title lockup, tagline. The
   spacing carries the grouping — "Homer's" sits tight against "The Iliad"
   because they are one title, and the gaps either side of the lockup are the
   wide ones. */
.pitch-title { margin: 0; }

.pitch-title .kicker { margin-bottom: 0.8rem; }

.pitch-title h1 {
  margin: 0;
  font-family: var(--display);
  font-weight: 500;
  font-size: clamp(1.9rem, 4.4vh, 2.9rem);
  line-height: 1.05;
  letter-spacing: 0.02em;
  color: var(--parchment);
}
/* "Homer's" is the attribution, "The Iliad" is the title — size them that way,
   as the game's own title screen does. Held a step back in size and tone so it
   reads as a credit line on the title rather than a heading of its own. */
.pitch-title h1 span {
  display: block;
  margin-bottom: 0.1em;
  font-size: 0.5em;
  letter-spacing: 0.16em;
  color: rgba(247, 231, 190, 0.72);
}
.pitch-title h1 em {
  display: block;
  font-style: normal;
  font-weight: 600;
  letter-spacing: 0.06em;
  background: linear-gradient(180deg, #ffe9b4, var(--gold-soft) 55%, var(--gold-deep));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.tagline {
  margin: 1.1rem 0 0;
  max-width: 48ch;
  font-size: clamp(0.95rem, 1.85vh, 1.05rem);
  line-height: 1.55;
  text-wrap: pretty;
  color: var(--parchment);
}
/* The two words the eye should catch: what it costs, and what you can buy. */
.tagline strong { font-weight: 700; }
.tagline .free   { color: var(--lapis); }
.tagline .patron { color: var(--gold-soft); }

/* --- calls to action ----------------------------------------------------- */

/* One column width for everything here — badge row, divider and button all
   share the same shoulders instead of each finding its own. */
.pitch-cta {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 1rem;
  width: 100%;
  max-width: var(--cta-w);
  margin-inline: auto;
  container-type: inline-size;
}

/* The two badges are official artwork with different proportions (Apple
   119.66:40 = 2.9916, Google 564:168 = 3.3571). Rather than let each one derive
   its own height — two roundings that can land a pixel apart — one height is
   computed from the column's real width and given to both, so they are equal by
   construction. Solving w1 + gap + w2 = column for a shared height h is just
   h = (column - gap) / (2.9916 + 3.3571), which also makes the pair fill the
   column exactly. Google's asset has its clear space trimmed off so both are
   measured the same way; the gap and the space below supply it back. */
.badges {
  --badge-gap: 0.85rem;
  --badge-h: calc((100cqi - var(--badge-gap)) / 6.3487);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--badge-gap);
}
.badge {
  display: block;
  transition: opacity 160ms ease, transform 160ms ease;
}
.badge:hover { opacity: 0.85; transform: translateY(-1px); }
.badge img { height: var(--badge-h); width: auto; }

/* The web build is desktop-only. Gated in CSS, not JS, so it stays right with
   scripting off. `pointer: fine` keeps it away from tablets in landscape. */
.launch { display: none; }

@media (min-width: 900px) and (pointer: fine) {
  .launch {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 0.7rem;
    padding-top: 1rem;
    border-top: 1px solid var(--hairline);
    width: 100%;
  }
}

.or {
  font-size: 0.72rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  text-align: center;
  color: var(--muted);
}

.button {
  display: block;
  text-align: center;
  padding: 0.75rem 1.5rem;
  font-family: var(--display);
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-decoration: none;
  color: #1a1208;
  background: linear-gradient(180deg, #ffe9b4, var(--gold-soft) 60%, var(--gold-deep));
  border-radius: 3px;
  box-shadow: 0 8px 24px -12px rgba(255, 215, 122, 0.7);
  transition: transform 160ms ease, box-shadow 160ms ease, filter 160ms ease;
}
.button:hover { transform: translateY(-1px); filter: brightness(1.06); box-shadow: 0 12px 30px -12px rgba(255, 215, 122, 0.85); }
.button:active { transform: translateY(0); }

.button.is-disabled {
  background: linear-gradient(180deg, #4a4034, #3a322a 60%, #2f2820);
  color: var(--muted);
  box-shadow: none;
  cursor: default;
}
.button.is-disabled:hover,
.button.is-disabled:active { transform: none; filter: none; box-shadow: none; }

.browsers {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.7rem;
  font-size: 0.78rem;
  color: var(--muted);
}
.browsers-label { letter-spacing: 0.06em; }
.browser { display: flex; align-items: center; gap: 0.3rem; }
.browser img { width: 18px; height: 18px; }

/* `display: flex` from an author sheet beats the UA's `[hidden] { display: none }`,
   so the attribute needs restating here or the warning shows unconditionally. */
.warning[hidden] { display: none; }

.warning {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  margin: 0;
  padding: 0.4rem 0.7rem;
  font-size: 0.78rem;
  color: #ffb37a;
  background: rgba(255, 158, 122, 0.08);
  border: 1px solid rgba(255, 158, 122, 0.3);
  border-radius: 3px;
}
.warning svg {
  flex: 0 0 auto;
  width: 1rem; height: 1rem;
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}

/* ==========================================================================
   ABOUT
   ========================================================================== */

.about {
  padding: clamp(3.5rem, 9vw, 7rem) var(--gutter);
  background:
    linear-gradient(180deg, var(--ink), var(--ink-lift) 40%, var(--ink-lift));
  border-top: 1px solid var(--hairline);
}

.about-inner { max-width: 46rem; margin: 0 auto; }

.about h2 {
  margin: 0.6rem 0 1.2rem;
  font-family: var(--display);
  font-weight: 500;
  font-size: clamp(1.6rem, 4vw, 2.4rem);
  line-height: 1.2;
  color: var(--parchment);
}

.about p { margin: 0 0 1.1rem; color: var(--muted); }
.about .lead { font-size: 1.08rem; color: var(--text); }

.pillars {
  display: grid;
  gap: 1.5rem;
  margin: 2.75rem 0 0;
  padding: 2.25rem 0 0;
  border-top: 1px solid var(--hairline);
  list-style: none;
}
@media (min-width: 720px) {
  .pillars { grid-template-columns: repeat(3, 1fr); gap: 2rem; }
}
.pillars h3 {
  margin: 0 0 0.4rem;
  font-family: var(--display);
  font-weight: 600;
  font-size: 0.8rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--gold);
}
.pillars p { margin: 0; font-size: 0.92rem; }

/* ==========================================================================
   SUPPORT
   Shares the about section's measure and rhythm; the darker ground sets it
   apart as the last thing before the footer.
   ========================================================================== */

.support {
  padding: clamp(3rem, 7vw, 5rem) var(--gutter);
  background: var(--ink-lift);
  border-top: 1px solid var(--hairline);
}

.support-inner { max-width: 46rem; margin: 0 auto; }

.support h1,
.support h2 {
  margin: 0.6rem 0 1rem;
  font-family: var(--display);
  font-weight: 500;
  font-size: clamp(1.4rem, 3.4vw, 2rem);
  line-height: 1.2;
  color: var(--parchment);
}

.support .lead { margin: 0 0 1.75rem; font-size: 1.05rem; color: var(--text); }

/* The mail link is a button, but it should not shout as loudly as the store
   badges above it, so it only takes the width its address needs. */
.support-button {
  display: inline-block;
  letter-spacing: 0.06em;
  overflow-wrap: anywhere;
}

.support-note { margin: 1rem 0 0; font-size: 0.88rem; color: var(--muted); }

/* support.html is this one section and nothing else, so the shell stretches to
   push the footer to the bottom of the viewport instead of leaving it mid-screen. */
.page-support { min-height: 100dvh; display: flex; flex-direction: column; }
.page-support .support {
  flex: 1;
  display: flex;
  align-items: center;
  border-top: 0;
  background: var(--ink);
}
.page-support .support-inner { width: 100%; }

/* ==========================================================================
   LEGAL PAGES  (privacy.html)
   A single column of running text. Shares the hero's brand lockup and the
   about section's measure, so a policy page still reads as part of the site.
   ========================================================================== */

.page-head {
  padding: clamp(1rem, 2.2vh, 1.75rem) var(--gutter);
  border-bottom: 1px solid var(--hairline);
  background:
    radial-gradient(120% 140% at 50% 0%, rgba(185, 143, 62, 0.16), transparent 70%),
    var(--ink);
}
.page-head-inner {
  max-width: var(--shell);
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}
/* The lockup doubles as the way home, so it loses the link underline and
   picks up the same hover the footer nav uses. */
.brand-link { text-decoration: none; }
.brand-link:hover .brand-name { color: var(--gold); }
.page-head .back {
  font-size: 0.9rem;
  color: var(--text);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color 160ms ease, border-color 160ms ease;
}
.page-head .back:hover { color: var(--gold); border-bottom-color: var(--gold-deep); }

.legal {
  padding: clamp(2.5rem, 7vw, 5rem) var(--gutter);
  background: linear-gradient(180deg, var(--ink), var(--ink-lift) 30%, var(--ink-lift));
}
.legal-inner { max-width: 46rem; margin: 0 auto; }

.legal h1 {
  margin: 0.6rem 0 0.5rem;
  font-family: var(--display);
  font-weight: 500;
  font-size: clamp(1.8rem, 4.6vw, 2.6rem);
  line-height: 1.15;
  color: var(--parchment);
}
.legal h2 {
  margin: 2.75rem 0 0.9rem;
  padding-top: 1.75rem;
  border-top: 1px solid var(--hairline);
  font-family: var(--display);
  font-weight: 500;
  font-size: clamp(1.15rem, 2.6vw, 1.45rem);
  line-height: 1.25;
  color: var(--parchment);
}
.legal h3 {
  margin: 1.75rem 0 0.4rem;
  font-family: var(--display);
  font-weight: 600;
  font-size: 0.8rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--gold);
}
.legal p { margin: 0 0 1.1rem; color: var(--muted); }
.legal .lead { font-size: 1.08rem; color: var(--text); }
.legal strong { color: var(--text); font-weight: 700; }

.updated {
  margin: 0 0 2rem;
  font-size: 0.82rem;
  letter-spacing: 0.04em;
  color: var(--muted);
}

/* The short answer, before the long one. */
.summary {
  margin: 0 0 2.5rem;
  padding: 1.25rem 1.5rem;
  border: 1px solid var(--hairline);
  border-radius: 4px;
  background: rgba(255, 215, 122, 0.04);
}
.summary p { margin: 0 0 0.8rem; color: var(--text); }
.summary p:last-child { margin-bottom: 0; }

.legal ul {
  margin: 0 0 1.1rem;
  padding-left: 1.1rem;
  list-style: none;
  color: var(--muted);
}
.legal li { position: relative; margin-bottom: 0.6rem; }
.legal li::before {
  content: '';
  position: absolute;
  left: -1.1rem;
  top: 0.68em;
  width: 0.32rem;
  height: 0.32rem;
  border-radius: 50%;
  background: var(--gold-deep);
}
.legal li strong { color: var(--parchment); }

.legal a {
  color: var(--gold);
  text-decoration: underline;
  text-decoration-color: var(--gold-deep);
  text-underline-offset: 0.15em;
  transition: text-decoration-color 160ms ease;
}
.legal a:hover { text-decoration-color: var(--gold); }

/* Long addresses and DSN-style strings must not push the page sideways. */
.legal code {
  font-size: 0.9em;
  color: var(--parchment);
  overflow-wrap: anywhere;
}

/* ==========================================================================
   FOOTER  (structure mirrors codestream.de)
   ========================================================================== */

footer {
  padding: clamp(2rem, 5vw, 3rem) var(--gutter);
  background: var(--ink-deep);
  border-top: 1px solid var(--hairline);
}

.footer-inner { max-width: var(--shell); margin: 0 auto; }

.footer-grid {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
}

.footer-brand { display: flex; align-items: center; gap: 0.75rem; }
.avatar {
  width: 40px; height: 40px;
  border-radius: 22%;
  box-shadow: 0 0 0 1px var(--hairline);
}
.who { display: flex; flex-direction: column; line-height: 1.35; }
.who strong {
  font-family: var(--display);
  font-weight: 600;
  letter-spacing: 0.1em;
  color: var(--parchment);
}
.who span { font-size: 0.82rem; color: var(--muted); }
/* Inline in a sentence, so it keeps an underline — the nav links opposite can
   go bare because a row of them reads as links on sight; a single word inside
   running text cannot. */
.who a {
  color: inherit;
  text-decoration: underline;
  text-decoration-color: var(--gold-deep);
  text-underline-offset: 0.15em;
  transition: color 160ms ease, text-decoration-color 160ms ease;
}
.who a:hover { color: var(--gold); text-decoration-color: var(--gold); }

.footer-links { display: flex; flex-wrap: wrap; gap: 1.5rem; }
.footer-links a {
  font-size: 0.9rem;
  color: var(--text);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color 160ms ease, border-color 160ms ease;
}
.footer-links a:hover { color: var(--gold); border-bottom-color: var(--gold-deep); }

.footer-copy {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  margin: 2rem 0 0;
  padding-top: 1.5rem;
  border-top: 1px solid var(--hairline);
  font-size: 0.8rem;
  color: var(--muted);
}
.footer-location { display: inline-flex; align-items: center; gap: 0.3rem; }
.footer-location svg { width: 0.9rem; height: 0.9rem; stroke: currentColor; }

/* ========================================================================== */

:where(a, button):focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}
