/* ===========================================================================
   CHANNEL VOCABULARY

   The transitions, element effects and type roles are the product's own,
   copied out of player/scene.css by name so the site moves exactly the way
   the thing it is selling moves. Every one is transform, opacity or clip-path
   only, so they all composite on the GPU.

   One deliberate difference: the sizes. The player is read from across a
   room, so a hero there is 132 of 1080. A website is read from two feet, so
   the roles keep their names and get web proportions. The grammar is shared.
   The scale is not, and pretending otherwise would just look shouty.
   ========================================================================= */

/* ---------------------------------------------------------------------------
   THEMES, one per channel, fixed.

   Changing channel visibly changes the look. That is the whole argument for
   putting a remote on the page, so the palettes are pushed well apart. Token
   names match player/scene.css exactly, which is why effect CSS lifts across
   unchanged. --prose, --meta and --rule are derived from --ink, so a theme
   only supplies a handful of real colors.
   ------------------------------------------------------------------------ */
.page {
  --prose: color-mix(in srgb, var(--ink) 90%, transparent);
  --meta:  color-mix(in srgb, var(--ink) 70%, transparent);
  --rule:  color-mix(in srgb, var(--ink) 30%, transparent);
  --hero-weight: 400;
  --em-weight: 400;
}

/* The ink that sits ON the accent: button labels, chips, the scroll arrow.
   Dark by default, because most accents here are light. A channel with a dark
   accent flips it, or it would be dark text on a dark button. Declared on
   :root so the theme blocks below, which are equally specific, can override
   it on source order. */
:root { --on-accent: #0B0A1C; }

/* 01 LIVE. The house identity, taken off the logo: navy, slate blue and
   purple. The logo's lime is deliberately not used. */
[data-theme='live'] {
  --display: 'Instrument Serif', Georgia, serif; --text: 'Outfit', sans-serif;
  --ink: #F3F1FB; --accent: #A98FE0; --flash: #D8CCF5;
  --ground-a: #0C1038; --ground-b: #04051A;
}
[data-theme='live'] .ground {
  background:
    radial-gradient(88% 66% at 78% 6%, rgba(0,5,139,0.78) 0%, transparent 62%),
    radial-gradient(72% 58% at 8% 94%, rgba(147,125,189,0.24) 0%, transparent 62%),
    radial-gradient(60% 50% at 46% 52%, rgba(76,98,178,0.20) 0%, transparent 70%),
    linear-gradient(168deg, var(--ground-a) 0%, var(--ground-b) 100%);
}

/* 02 ABOUT. Paper and navy. The light channel, so the lineup is not seven
   dark rooms in a row. */
[data-theme='what'] {
  --display: 'Instrument Serif', Georgia, serif; --text: 'Outfit', sans-serif;
  --ink: #14162A; --accent: #00058B; --flash: #937DBD;
  --ground-a: #F2F1F7; --ground-b: #D9D8E6;
  /* Navy reads beautifully on this channel's paper ground and vanishes on the
     remote, so the furniture gets a light counterpart from the same family. */
  --chrome: #93A8F0;
  --on-accent: #FFFFFF;
}
[data-theme='what'] .ground {
  background:
    radial-gradient(78% 58% at 84% 4%, rgba(0,5,139,0.13) 0%, transparent 58%),
    radial-gradient(64% 52% at 8% 96%, rgba(147,125,189,0.20) 0%, transparent 60%),
    linear-gradient(162deg, var(--ground-a) 0%, var(--ground-b) 100%);
}

/* 03 HOW. Paper and ink. The one light channel, so the set has contrast. */
[data-theme='how'] {
  --display: 'Instrument Serif', Georgia, serif; --text: 'Outfit', sans-serif;
  --ink: #EDF0FB; --accent: #8FA6EE; --flash: #D8CCF5;
  --ground-a: #131A3E; --ground-b: #070A1E;
}
[data-theme='how'] .ground {
  background:
    radial-gradient(84% 62% at 14% 8%, rgba(76,98,178,0.42) 0%, transparent 60%),
    radial-gradient(70% 56% at 90% 92%, rgba(0,5,139,0.62) 0%, transparent 62%),
    linear-gradient(158deg, var(--ground-a) 0%, var(--ground-b) 100%);
}

/* 04 SEE IT. Near black, because a wall of screens needs black around it. */
[data-theme='see'] {
  --display: 'Instrument Serif', Georgia, serif; --text: 'Outfit', sans-serif;
  --ink: #EFEDF8; --accent: #A98FE0; --flash: #FFFFFF;
  --ground-a: #0B0B14; --ground-b: #030306;
}
[data-theme='see'] .ground {
  background:
    radial-gradient(100% 80% at 50% 50%, #14161E 0%, transparent 70%),
    linear-gradient(180deg, var(--ground-a) 0%, var(--ground-b) 100%);
}

/* 05 WHO. Plum and coral. Warm, and unmistakably not the others. */
[data-theme='who'] {
  --display: 'Instrument Serif', Georgia, serif; --text: 'Outfit', sans-serif;
  --ink: #F4EFFA; --accent: #C2A9F0; --flash: #FFFFFF;
  --ground-a: #241546; --ground-b: #0B0619;
}
[data-theme='who'] .ground {
  background:
    radial-gradient(78% 60% at 20% 10%, rgba(147,125,189,0.42) 0%, transparent 58%),
    radial-gradient(72% 58% at 88% 92%, rgba(0,5,139,0.55) 0%, transparent 62%),
    linear-gradient(150deg, var(--ground-a) 0%, var(--ground-b) 100%);
}

/* 06 DEAL. Night, snow, and a cold light on the sign. */
[data-theme='deal'] {
  --display: 'Instrument Serif', Georgia, serif; --text: 'Outfit', sans-serif;
  --ink: #EFF1FF; --accent: #9FB3F5; --flash: #FFFFFF;
  --ground-a: #00058B; --ground-b: #05061C;
}
[data-theme='deal'] .ground {
  background:
    radial-gradient(96% 62% at 50% 0%, rgba(147,125,189,0.50) 0%, transparent 64%),
    linear-gradient(172deg, var(--ground-a) 0%, var(--ground-b) 76%);
}

/* 07 FAQ. A program guide at night: deep teal and a cool cyan listing light,
   so the one channel of plain answers does not look like any of the pitches. */
[data-theme='guide'] {
  --display: 'Instrument Serif', Georgia, serif; --text: 'Outfit', sans-serif;
  --ink: #EDF4F8; --accent: #7FD1E6; --flash: #FFFFFF;
  --ground-a: #0A2233; --ground-b: #030A12;
}
[data-theme='guide'] .ground {
  background:
    radial-gradient(80% 60% at 86% 10%, rgba(40,130,160,0.34) 0%, transparent 60%),
    radial-gradient(70% 56% at 6% 94%, rgba(0,5,139,0.50) 0%, transparent 62%),
    linear-gradient(165deg, var(--ground-a) 0%, var(--ground-b) 100%);
}

/* 07 PRICING. The price sheet's own colors: deep navy, a blue light in the
   corner, and the gold of its offer band, which no other channel uses. */
[data-theme='price'] {
  --display: 'Instrument Serif', Georgia, serif; --text: 'Outfit', sans-serif;
  --ink: #F2F4FB; --accent: #E6BD7C; --flash: #FFF3DC;
  --ground-a: #13224D; --ground-b: #060A1D;
  --on-accent: #0E1838;
}
[data-theme='price'] .ground {
  background:
    radial-gradient(80% 60% at 92% 4%, rgba(45,104,206,0.46) 0%, transparent 60%),
    radial-gradient(70% 56% at 4% 96%, rgba(230,189,124,0.13) 0%, transparent 62%),
    linear-gradient(160deg, var(--ground-a) 0%, var(--ground-b) 100%);
}

/* 09 REACH. Home again, so the last thing seen is the house brand. */
[data-theme='reach'] {
  --display: 'Instrument Serif', Georgia, serif; --text: 'Outfit', sans-serif;
  --ink: #F3F1FB; --accent: #A98FE0; --flash: #D8CCF5;
  --ground-a: #0C1038; --ground-b: #04051A;
}
[data-theme='reach'] .ground {
  background:
    radial-gradient(78% 58% at 16% 8%, rgba(147,125,189,0.28) 0%, transparent 58%),
    radial-gradient(90% 70% at 92% 96%, rgba(0,5,139,0.72) 0%, transparent 62%),
    linear-gradient(200deg, var(--ground-a) 0%, var(--ground-b) 100%);
}

/* ---------------------------------------------------------------------------
   TYPE ROLES

   Same names as the player: .hero .kicker .lede .em .datarow. A *starred*
   phrase in a headline becomes .em, the split-weight accent word.
   ------------------------------------------------------------------------ */
/* Nothing on this site is small. The floor is the lede, and anything that
   would once have been a caption is now simply text. */
.hero {
  font-family: var(--display);
  font-size: clamp(40px, 5.4vw, 94px);
  font-weight: var(--hero-weight, 400);
  font-style: italic;
  line-height: 1.02; letter-spacing: -0.012em;
  margin: 0; text-wrap: balance;
}
.hero.sm { font-size: clamp(32px, 3.6vw, 58px); }

.kicker {
  font-size: clamp(14px, 1.02vw, 18px);
  font-weight: 700; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--accent); margin: 0;
}
.kicker.lg { font-size: clamp(17px, 1.34vw, 24px); letter-spacing: 0.17em; }

.lede {
  font-size: clamp(17px, 1.28vw, 23px);
  line-height: 1.55; color: var(--prose);
  margin: 0; max-width: 54ch; text-wrap: pretty;
}

.em { color: var(--accent); font-style: italic; }

.datarow {
  display: flex; align-items: baseline; gap: 22px;
  font-size: clamp(18px, 1.34vw, 24px);
}
.datarow .k {
  font-size: clamp(13px, 0.92vw, 16px); font-weight: 700; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--meta);
  width: 150px; flex-shrink: 0;
}

/* ---------------------------------------------------------------------------
   ELEMENT ENTRIES, from player/scene.css

   Elements arrive one at a time. The stagger is set per element as --delay,
   so the order of attention is authored rather than accidental.
   ------------------------------------------------------------------------ */
.el { opacity: 0; will-change: opacity, transform, clip-path; }
.beat.is-in .el[data-in] { opacity: 1; }

/* Without script there is nothing to add .is-in, so an element that starts
   at zero would never arrive. The page is simply all there instead. */
html:not([data-js]) .el { opacity: 1 !important; animation: none !important; }

.beat.is-in .el[data-in='slat'] {
  animation: slat-in var(--dur, 1150ms) var(--delay, 0ms) cubic-bezier(0.33,0,0.2,1) both;
  -webkit-mask-image: repeating-linear-gradient(to bottom, #000 0 var(--slat), transparent var(--slat) 14px);
          mask-image: repeating-linear-gradient(to bottom, #000 0 var(--slat), transparent var(--slat) 14px);
}
@keyframes slat-in {
  0%   { opacity: 0; --slat: 0px;  color: var(--flash); transform: translateX(-9px); }
  25%  { opacity: 1; }
  60%  { --slat: 8px;  color: var(--flash); transform: translateX(0); }
  100% { opacity: 1; --slat: 14px; color: var(--ink);   transform: translateX(0); }
}

.beat.is-in .el[data-in='wipe']     { animation: wipe-in var(--dur,950ms) var(--delay,0ms) cubic-bezier(0.2,0,0.1,1) both; }
@keyframes wipe-in { from { opacity:1; clip-path: inset(0 100% 0 0); } to { opacity:1; clip-path: inset(0 0 0 0); } }

.beat.is-in .el[data-in='dissolve'] { animation: dissolve-in var(--dur,1300ms) var(--delay,0ms) ease both; }
@keyframes dissolve-in { from { opacity:0; } to { opacity:1; } }

.beat.is-in .el[data-in='fly']      { animation: fly-in var(--dur,820ms) var(--delay,0ms) cubic-bezier(0.16,0.8,0.28,1) both; }
@keyframes fly-in { from { opacity:0; transform: translate(-54px, 20px) scale(0.6); } to { opacity:1; transform:none; } }

.beat.is-in .el[data-in='rise']     { animation: rise-in var(--dur,950ms) var(--delay,0ms) cubic-bezier(0.16,0.8,0.28,1) both; }
@keyframes rise-in { from { opacity:0; transform: translateY(26px); } to { opacity:1; transform:none; } }

.beat.is-in .el[data-in='iris']     { animation: iris-in var(--dur,1150ms) var(--delay,0ms) cubic-bezier(0.3,0,0.2,1) both; }
@keyframes iris-in { from { opacity:1; clip-path: circle(0% at 50% 50%); } to { opacity:1; clip-path: circle(75% at 50% 50%); } }

.beat.is-in .el[data-in='barn']     { animation: barn-in var(--dur,1050ms) var(--delay,0ms) cubic-bezier(0.3,0,0.2,1) both; }
@keyframes barn-in { from { opacity:1; clip-path: inset(0 50% 0 50%); } to { opacity:1; clip-path: inset(0 0 0 0); } }

/* ---------------------------------------------------------------------------
   SCREEN TRANSITIONS, from the Scala vocabulary by way of player/scene.css.

   The incoming page sits above the outgoing one and is revealed by a clip.
   set.js picks one at random per tune, never repeating inside the last five,
   and randomizes the duration between 950 and 1500ms so it does not beat
   like a metronome.
   ------------------------------------------------------------------------ */
.is-entering[data-tx='cut']      { animation: none; }
.is-entering[data-tx='dissolve'] { animation: tx-dissolve var(--txd,1100ms) ease both; }
@keyframes tx-dissolve { from { opacity:0; } to { opacity:1; } }

.is-entering[data-tx='wipe-left']  { animation: tx-wl var(--txd,1100ms) cubic-bezier(0.4,0,0.2,1) both; }
.is-entering[data-tx='wipe-right'] { animation: tx-wr var(--txd,1100ms) cubic-bezier(0.4,0,0.2,1) both; }
.is-entering[data-tx='wipe-up']    { animation: tx-wu var(--txd,1100ms) cubic-bezier(0.4,0,0.2,1) both; }
.is-entering[data-tx='wipe-down']  { animation: tx-wd var(--txd,1100ms) cubic-bezier(0.4,0,0.2,1) both; }
@keyframes tx-wl { from { clip-path: inset(0 0 0 100%); } to { clip-path: inset(0 0 0 0); } }
@keyframes tx-wr { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
@keyframes tx-wu { from { clip-path: inset(100% 0 0 0); } to { clip-path: inset(0 0 0 0); } }
@keyframes tx-wd { from { clip-path: inset(0 0 100% 0); } to { clip-path: inset(0 0 0 0); } }

.is-entering[data-tx='scroll-left']  { animation: tx-sl var(--txd,1100ms) cubic-bezier(0.4,0,0.2,1) both; }
.is-entering[data-tx='scroll-right'] { animation: tx-sr var(--txd,1100ms) cubic-bezier(0.4,0,0.2,1) both; }
.is-entering[data-tx='scroll-up']    { animation: tx-su var(--txd,1100ms) cubic-bezier(0.4,0,0.2,1) both; }
.is-entering[data-tx='scroll-down']  { animation: tx-sd var(--txd,1100ms) cubic-bezier(0.4,0,0.2,1) both; }
@keyframes tx-sl { from { transform: translateX(100%); }  to { transform:none; } }
@keyframes tx-sr { from { transform: translateX(-100%); } to { transform:none; } }
@keyframes tx-su { from { transform: translateY(100%); }  to { transform:none; } }
@keyframes tx-sd { from { transform: translateY(-100%); } to { transform:none; } }

.is-entering[data-tx='box']     { animation: tx-box var(--txd,1150ms) cubic-bezier(0.3,0,0.2,1) both; }
@keyframes tx-box { from { clip-path: inset(50% 50% 50% 50%); } to { clip-path: inset(0 0 0 0); } }

.is-entering[data-tx='diamond'] { animation: tx-dia var(--txd,1200ms) cubic-bezier(0.3,0,0.2,1) both; }
@keyframes tx-dia {
  from { clip-path: polygon(50% 50%, 50% 50%, 50% 50%, 50% 50%); }
  to   { clip-path: polygon(50% -60%, 160% 50%, 50% 160%, -60% 50%); }
}

.is-entering[data-tx='circle']  { animation: tx-cir var(--txd,1150ms) cubic-bezier(0.3,0,0.2,1) both; }
@keyframes tx-cir { from { clip-path: circle(0% at 50% 50%); } to { clip-path: circle(75% at 50% 50%); } }

.is-entering[data-tx='corner']  { animation: tx-corner var(--txd,1150ms) cubic-bezier(0.3,0,0.2,1) both; }
@keyframes tx-corner {
  from { clip-path: polygon(0 0, 0 0, 0 0); }
  to   { clip-path: polygon(0 0, 220% 0, 0 220%); }
}

.is-entering[data-tx='curtain'] { animation: tx-curtain var(--txd,1200ms) cubic-bezier(0.4,0,0.2,1) both; }
@keyframes tx-curtain { from { clip-path: inset(0 50% 0 50%); } to { clip-path: inset(0 0 0 0); } }

.is-entering[data-tx='center']  { animation: tx-center var(--txd,1150ms) cubic-bezier(0.4,0,0.2,1) both; }
@keyframes tx-center { from { clip-path: inset(50% 0 50% 0); } to { clip-path: inset(0 0 0 0); } }

.is-entering[data-tx='clock-cw'] {
  animation: tx-clock var(--txd,1250ms) linear both;
  -webkit-mask-image: conic-gradient(from 0deg, #000 var(--sweep), transparent 0);
          mask-image: conic-gradient(from 0deg, #000 var(--sweep), transparent 0);
}
.is-entering[data-tx='clock-ccw'] {
  animation: tx-clock var(--txd,1250ms) linear both;
  -webkit-mask-image: conic-gradient(from 0deg, transparent calc(360deg - var(--sweep)), #000 0);
          mask-image: conic-gradient(from 0deg, transparent calc(360deg - var(--sweep)), #000 0);
}
@keyframes tx-clock { from { --sweep: 0deg; } to { --sweep: 360deg; } }

/* The outgoing page just holds still underneath. Moving both fights the eye,
   which is the note the reference sites all answer the same way. */
.is-leaving { animation: none; }

/* ---------------------------------------------------------------------------
   Reduced motion. Transitions become a short dissolve, entries become
   presence. Every scene still composes, nothing is lost but the performance.
   ------------------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  .is-entering[data-tx] {
    animation: tx-dissolve 200ms ease both !important;
    mask-image: none !important; -webkit-mask-image: none !important;
  }
  .beat .el, .beat.is-in .el[data-in] {
    animation: none !important; opacity: 1 !important;
    transform: none !important; clip-path: none !important;
    mask-image: none !important; -webkit-mask-image: none !important;
  }
}
