/* ============================================================
   ambilight.css — the three-set showroom on /motion/

   Adapted from jh3y's "Pure CSS Home Media (Ambilight)" pen:
   https://codepen.io/jh3y/pen/BaNGKPw
   The trick is the whole thing: a second copy of the same video
   sits behind the screen, blurred and over-brightened, so the
   colour bleeds out past the bezel the way a Philips set does.

   Two changes from the original. It has been re-expressed in
   ratio-relative units so one rule set drives a 16:9, a 9:16 and
   a 1:1 cabinet, and "lights on" lifts the wall to charcoal
   rather than white — this site is black everywhere else and a
   white flash would read as a bug.
   ============================================================ */

.room {
  --speed: 0.35s;

  /* the eight values the light switch moves */
  --wall: 4%;
  --bezel: 13%;
  --door: 5%;
  --brightness: 260%;
  --blur: 0.30;          /* x screen height */
  --shadow: 0;
  --plate: 16%;
  --rocker: 30%;
  --prop-light: 0.26;    /* how much of the cabinet you can make out */

  position: relative;
  padding: clamp(2.5rem, 6vw, 5rem) 0 clamp(2rem, 4vw, 3.5rem);
  background: hsl(0 0% var(--wall));
  transition: background var(--speed) var(--e-inout);
  isolation: isolate;
}

/* The glow is the point, so it must not be trimmed. `clip` keeps the
   page from gaining a sideways scrollbar without turning .room into a
   containing block for the bleed.

   Three named rows: the sets stand on one floor line, the cabinet runs
   the whole width beneath them, and each set's controls sit back under
   its own screen. */
.room__floor {
  display: grid;
  grid-template-columns: auto auto auto;
  grid-template-areas:
    "tv1 tv2 tv3"
    "cab cab cab"
    "pn1 pn2 pn3";
  align-items: end;
  justify-content: center;
  justify-items: center;
  column-gap: clamp(1.5rem, 4vw, 4rem);
  row-gap: clamp(1rem, 2.2vw, 1.75rem);
  overflow-x: clip;
  padding-inline: var(--gutter);
}

/* ---------- 1. One set ---------- */
/* The screen and its controls are separate grid items so the cabinet can
   pass between them; .tvset survives only to carry the ratio variables. */
.tvset {
  display: contents;
  --tv-w: calc(var(--tv-h) * var(--ratio));
}

.tvset--wide   > .tv { grid-area: tv1; }
.tvset--tall   > .tv { grid-area: tv2; }
.tvset--square > .tv { grid-area: tv3; }
.tvset--wide   > .tvset__panel { grid-area: pn1; }
.tvset--tall   > .tvset__panel { grid-area: pn2; }
.tvset--square > .tvset__panel { grid-area: pn3; }

.tvset--wide   { --ratio: calc(16 / 9); --tv-h: clamp(6.5rem, 13.5vw, 14rem); }
.tvset--tall   { --ratio: calc(9 / 16); --tv-h: clamp(12rem,  24vw,   25rem); }
.tvset--square { --ratio: 1;            --tv-h: clamp(9rem,   17.5vw, 18rem); }

/* ---------- 2. The set ---------- */
.tv {
  position: relative;
  width: var(--tv-w);
  height: var(--tv-h);
  background: #000;
  box-shadow: 0 calc(var(--tv-h) * 0.17) calc(var(--tv-h) * 0.17)
              hsl(0 0% 35% / var(--shadow));
  transition: box-shadow var(--speed) var(--e-inout);
}

.tv video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: #000;
}

/* the copy that bleeds out the back */
.tv__ambi {
  filter: brightness(var(--brightness)) blur(calc(var(--tv-h) * var(--blur)));
  transition: filter var(--speed) var(--e-inout);
  pointer-events: none;
}

.tv__screen {
  border: calc(var(--tv-h) * 0.022) solid hsl(0 0% var(--bezel));
  transition: border-color var(--speed) var(--e-inout);
}

/* ---------- 3. Channel change ---------- */
/* A single frame of interference, then it settles — the same beat an
   old set gives you between channels. */
.tv__static {
  position: absolute;
  inset: 0;
  z-index: 2;
  opacity: 0;
  pointer-events: none;
  background:
    repeating-linear-gradient(0deg,
      hsl(0 0% 100% / 0.16) 0 1px, transparent 1px 3px),
    hsl(0 0% 62%);
  mix-blend-mode: screen;
}

.tv.is-switching .tv__static { animation: tv-static 0.34s steps(4) 1; }
.tv.is-switching .tv__screen { animation: tv-roll 0.34s var(--e-out) 1; }

@keyframes tv-static {
  0%   { opacity: 0.85; }
  55%  { opacity: 0.35; }
  100% { opacity: 0; }
}

@keyframes tv-roll {
  0%   { transform: scaleY(0.02); filter: brightness(3); }
  35%  { transform: scaleY(1.04); filter: brightness(1.6); }
  100% { transform: scaleY(1);    filter: brightness(1); }
}

/* ---------- 4. The cabinet ---------- */
/* One bench running under all three sets, three glass bays deep. Roughly
   180cm x 28cm, which is what fixes the aspect ratio. */
.cabinet {
  grid-area: cab;
  position: relative;
  display: flex;
  gap: 0.35%;
  width: 100%;
  aspect-ratio: 6.4;
  margin-top: clamp(0.5rem, 1.4vw, 1.25rem);
  background: #000;
  box-shadow: 0 clamp(10px, 2vw, 26px) clamp(10px, 2vw, 26px)
              hsl(0 0% 35% / var(--shadow));
}

/* the sheen across the glass, only readable with the lights up */
.cabinet::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(-35deg, transparent 25%,
              hsl(0 0% 85% / calc(var(--shadow) * 0.32)), transparent);
}

.cabinet__bay {
  flex: 1;
  position: relative;
  background: hsl(0 0% var(--door));
  transition: background var(--speed) var(--e-inout);
}

/* the dark interior behind the door frame */
.cabinet__shelf {
  position: absolute;
  inset: 9% 3%;
  overflow: hidden;
  background: #000;
}

/* warmth spilling off the shelf once the room is lit */
.cabinet__shelf::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(120% 90% at 50% 120%,
              hsl(34 60% 60% / calc(var(--shadow) * 0.14)), transparent 70%);
}

/* ---------- 5. What is on the shelves ---------- */
/* Everything sits on the shelf floor and is sized as a share of the bay,
   so the whole set of props scales with the cabinet and never needs a
   breakpoint of its own. Each prop's --x is its offset from the left. */
.cabinet__props {
  position: absolute;
  inset: 0;
  opacity: var(--prop-light);
  transition: opacity var(--speed) var(--e-inout);
}

.prop {
  position: absolute;
  bottom: 0;
  left: var(--x);
}

/* a cassette, face out */
.prop--cassette {
  width: 19%;
  aspect-ratio: 1.58;
  background: linear-gradient(#2e2a26, #201d1a);
  border-radius: 5% / 8%;
  box-shadow: inset 0 0 0 1px hsl(40 20% 70% / 0.18);
}

.prop--cassette::before {              /* the paper label */
  content: '';
  position: absolute;
  inset: 11% 8% 48%;
  border-radius: 1px;
  background: var(--tape, #cfc2a8);
  box-shadow: inset 0 -32% 0 hsl(0 0% 0% / 0.09);
}

/* The window has to be lighter than the shell or the two reels vanish and
   the whole thing reads as a plain block at cabinet size. */
.prop--cassette::after {
  content: '';
  position: absolute;
  inset: 56% 14% 12%;
  border-radius: 1px;
  background:
    radial-gradient(circle closest-side at 24% 50%, #0a0a0a 0 68%, transparent 69%),
    radial-gradient(circle closest-side at 76% 50%, #0a0a0a 0 68%, transparent 69%),
    linear-gradient(#8b8177, #6d645a);
}

/* the same tapes, stacked flat */
.prop--stack {
  width: 17%;
  height: 34%;
  background: repeating-linear-gradient(to top,
    #211e1b 0 22%, #383029 22% 25%, transparent 25% 28%);
}

/* a row of spines */
.prop--books {
  display: flex;
  align-items: flex-end;
  gap: 4%;
  width: 26%;
  height: 72%;
}

.prop--books i { flex: 1; border-radius: 1px 1px 0 0; }
.prop--books i:nth-child(1) { height: 100%; background: #7d3f34; }
.prop--books i:nth-child(2) { height: 88%;  background: #c9b184; }
.prop--books i:nth-child(3) { height: 96%;  background: #3f5148; }
.prop--books i:nth-child(4) { height: 78%;  background: #2f3a4a; }
.prop--books i:nth-child(5) { height: 92%;  background: #8a7a5e; }
.prop--books i:nth-child(6) { height: 84%;  background: #5a4a55; }

.prop--books-sm { width: 18%; height: 54%; }

/* two more lying on their sides */
.prop--flatbooks {
  width: 16%;
  height: 15%;
  background: linear-gradient(to top,
    #3f5148 0 42%, #0b0b0b 42% 48%, #8a7a5e 48% 94%, #0b0b0b 94%);
}

/* a sleeve leaning against the back */
.prop--record {
  width: 30%;
  aspect-ratio: 1;
  background: #14120f;
  box-shadow: inset 0 0 0 1px hsl(0 0% 100% / 0.1);
}

.prop--record::after {
  content: '';
  position: absolute;
  inset: 34%;
  border-radius: 50%;
  background: var(--acid);
  opacity: 0.75;
}

/* and a candle, which is the only thing in here that moves */
.prop--candle {
  width: 5%;
  height: 42%;
  background: linear-gradient(to top, #cfc3aa, #efe6d2);
  border-radius: 2px 2px 1px 1px;
}

.prop--candle::before {                /* flame */
  content: '';
  position: absolute;
  left: 50%;
  bottom: 100%;
  width: 190%;
  aspect-ratio: 0.62;
  transform: translateX(-50%);
  border-radius: 50% 50% 46% 46%;
  background: radial-gradient(ellipse at 50% 72%,
              #fff2c4 8%, #ffc247 48%, hsl(34 100% 55% / 0) 72%);
  animation: candle 2.6s ease-in-out infinite;
}

@keyframes candle {
  0%, 100% { transform: translateX(-50%) scale(1);           opacity: 0.95; }
  35%      { transform: translateX(-50%) scale(0.9, 1.08);   opacity: 0.8;  }
  70%      { transform: translateX(-52%) scale(1.06, 0.94);  opacity: 1;    }
}

/* ---------- 5. Channel readout + button ---------- */
.tvset__panel {
  width: var(--tv-w);
  text-align: center;
}

.tvset__ch {
  font-family: var(--f-ui);
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--acid);
}

.tvset__title {
  margin-top: 0.35rem;
  font-family: var(--f-case);
  font-size: clamp(1rem, 1.5vw, 1.25rem);
  font-weight: 600;
  line-height: 1.2;
}

.tvset__format {
  margin-top: 0.15rem;
  font-family: var(--f-ui);
  font-size: var(--t-xs);
  color: var(--fg-meta);
}

/* room for the switch's label, which hangs outside the plate */
.tvset__panel { padding-bottom: 1.75rem; }

/* The channel control is the same wall switch as the lights, in the
   site's lime rather than the room's greys — so the two things you can
   press on this page are obviously the same kind of object. */
.ch-switch {
  position: relative;
  display: grid;
  place-items: center;
  width: 44px;
  height: 60px;
  margin: clamp(1.1rem, 2.2vw, 1.6rem) auto 0;
  cursor: pointer;
}

.ch-switch::before {                   /* the plate */
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 3px;
  background: var(--acid);
  box-shadow: 0 2px 4px hsl(0 0% 35% / var(--shadow));
  transition: background var(--d-fast) var(--e-out),
              box-shadow var(--speed)  var(--e-inout);
}

.ch-switch::after {                    /* the rocker */
  content: '';
  position: relative;
  width: 20px;
  height: 30px;
  border: 2px solid hsl(66 100% 26%);
  background: linear-gradient(#15170a, #2b2f12);
  transition: background var(--d-fast) var(--e-out);
}

/* flipped by the script on every press, so the switch actually throws */
.ch-switch.is-down::after { background: linear-gradient(#2b2f12, #15170a); }

.ch-switch:hover::before,
.ch-switch:focus-visible::before { background: #f2ff5c; }

.ch-switch:active::before { box-shadow: none; }

.ch-switch__label {
  position: absolute;
  top: calc(100% + 0.5rem);
  left: 50%;
  transform: translateX(-50%);
  font-family: var(--f-ui);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--acid);
  white-space: nowrap;
}

/* ---------- 6. The light switch on the wall ---------- */
.room__lights { position: absolute; height: 0; width: 0; opacity: 0; }

.light-switch {
  position: absolute;
  top: clamp(1.5rem, 4vw, 3rem);
  right: var(--gutter);
  display: grid;
  place-items: center;
  width: 44px;
  height: 60px;
  cursor: pointer;
  z-index: 3;
}

/* the wall plate */
.light-switch::before {
  content: '';
  position: absolute;
  inset: 0;
  background: hsl(0 0% var(--plate));
  border-radius: 3px;
  box-shadow: 0 2px 4px hsl(0 0% 35% / var(--shadow));
  transition: background var(--speed) var(--e-inout),
              box-shadow var(--speed) var(--e-inout);
}

/* the rocker */
.light-switch::after {
  content: '';
  position: relative;
  width: 20px;
  height: 30px;
  border: 2px solid hsl(0 0% calc(var(--plate) * 0.7));
  background: linear-gradient(hsl(0 0% calc(var(--rocker) * 0.7)),
                              hsl(0 0% var(--rocker)));
  transition: border-color var(--speed) var(--e-inout),
              background   var(--speed) var(--e-inout);
}

.room__lights:focus-visible + .light-switch::before {
  outline: 2px solid var(--acid);
  outline-offset: 4px;
}

/* Lights on. Charcoal, not white — see the note at the top. */
.room:has(.room__lights:checked) {
  --wall: 15%;
  --bezel: 46%;
  --door: 13%;
  --brightness: 420%;
  --blur: 0.11;
  --shadow: 0.6;
  --plate: 78%;
  --rocker: 92%;
  --prop-light: 1;
}

.light-switch__label {
  position: absolute;
  top: calc(100% + 0.5rem);
  left: 50%;
  transform: translateX(-50%);
  font-family: var(--f-ui);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--fg-meta);
  white-space: nowrap;
}

/* ---------- 7. Narrow screens ---------- */
/* Three cabinets will not sit side by side on a phone. They stack, and
   the switch leaves the wall for the flow so it cannot land on a set. */
@media (max-width: 900px) {
  /* Drop the named rows and let the source order stand: each screen is
     immediately followed by its own controls, with the cabinet closing
     the room. */
  .room__floor {
    grid-template-columns: 1fr;
    grid-template-areas: none;
    row-gap: clamp(2.5rem, 8vw, 4rem);
  }

  /* These have to out-specify the `.tvset--wide > .tv` area rules above,
     or the items keep hunting for grid lines that no longer exist and
     pile into one cell. */
  .room__floor .tvset > .tv,
  .room__floor .tvset > .tvset__panel,
  .room__floor > .cabinet { grid-area: auto; }

  /* a sixth of the width means a sixth of the height, and the props stop
     being legible — so the bench gets deeper rather than longer */
  .cabinet { aspect-ratio: 3.1; margin-top: 0; }

  .tvset--wide   { --tv-h: min(38vw, 13rem); }
  .tvset--tall   { --tv-h: min(78vw, 25rem); }
  .tvset--square { --tv-h: min(52vw, 17rem); }

  /* Relative, not static — the label still hangs off the plate and needs
     the plate to be its containing block. */
  .light-switch {
    position: relative;
    inset: auto;
    margin: 0 auto clamp(3rem, 8vw, 4rem);
  }
}

/* ---------- 8. Reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  .tv.is-switching .tv__static,
  .tv.is-switching .tv__screen,
  .prop--candle::before { animation: none; }
}
