/* Mythlark: the page's own layer over the engine floor.

   A toy theatre. The frame is cream paper with a gilt edge and a velvet drape;
   inside it, the studio's cut-paper landscape and then each production's set.
   Every colour the sun can change is a custom property. The values under
   :root are the sun at rest, so the first paint is right; as the sun moves,
   page.js writes the new ones on the pieces it lights, and nowhere else. The
   frame, the curtain and the programme cards keep one light of their own, so
   no copy's contrast depends on the sun.

   Stacking, inside the stage (the engine makes it the stacking context):
     back wall (the stage's own background)     1 the sun's glow on it
     10 drops        20 the sun's rig, its wire and track
     30 landscape planes and each production's flats
     40 each production's phone      50 the curtain
     60 the proscenium               70 the lark      75 the sun's handle
     80 the cards and the sun's caption              90 the pelmet's name and programme
   Nothing that holds these is a stacking context of its own: .house-set,
   .land, .play and .set take no transform, opacity, filter or z-index. */

@font-face {
  font-family: "Playfair Display";
  src: url("/assets/fonts/playfair-display-latin-wght-normal-e0c764a8e9.woff2") format("woff2");
  font-weight: 400 900; font-style: normal; font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Playfair Display";
  src: url("/assets/fonts/playfair-display-latin-ext-wght-normal-42898ad49a.woff2") format("woff2");
  font-weight: 400 900; font-style: normal; font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Playfair Display";
  src: url("/assets/fonts/playfair-display-latin-wght-italic-54af24bd0f.woff2") format("woff2");
  font-weight: 400 900; font-style: italic; font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "DM Sans";
  src: url("/assets/fonts/dm-sans-latin-wght-normal-9fea608a94.woff2") format("woff2");
  font-weight: 100 1000; font-style: normal; font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "DM Sans";
  src: url("/assets/fonts/dm-sans-latin-ext-wght-normal-a5d38fe99f.woff2") format("woff2");
  font-weight: 100 1000; font-style: normal; font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  --sc-canvas: #f4ecdf;
  --sc-surface: #fffaf1;
  --sc-ink: #131c33;
  --sc-ink-soft: #4f5661;
  --sc-accent: #d02b1c;
  --sc-accent-ink: #ffffff;
  --sc-font-display: "Playfair Display", "Iowan Old Style", Georgia, serif;
  --sc-font-text: "DM Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  --sc-shadow-color: 28 30% 14%;

  /* The light, at rest. */
  --sky: #e2edf2;      --sky-low: #f0f2eb;
  --far: #d8d4ee;      --snow: #fcfcfa;
  --mid: #2952a5;      --coral: #ea5639;   --gold: #f0b43b;
  --water: #1e5ac8;    --forest: #357f4e;  --pine: #1a4a3e;  --pine2: #265e4d;
  --sand: #f1e8d9;     --dune: #e3d6bf;    --cloud: #fcfbf7;
  --sun: #f6bf4e;
  --shadow: rgb(48 38 28 / 0.22);
  --wash: rgb(255 255 255 / 0);
  --shx: 2.4;  --shy: 3.6;

  /* The theatre's own colours, which the sun leaves alone. */
  --frame: #f4ecdf;
  --gilt: #d9a441;
  --gilt-line: rgb(110 74 22 / 0.55);
  --card: #fffaf1;
  --rule: rgb(19 28 51 / 0.12);
  --accent: #d02b1c;  --accent-deep: #b3251a;
  --card-shadow: 0 1px 0 rgb(255 255 255 / 0.7) inset, 0 0 0 1px rgb(90 60 20 / 0.08),
                 0 2px 3px rgb(40 26 12 / 0.16), 0 16px 32px -12px rgb(16 10 4 / 0.5);
}

/* The engine writes the act's progress to --sc-p on the act every frame of a
   scroll. Nothing here reads it, and a value that changed would restyle the
   whole stage under it and repaint the back wall on every frame. Held here, it
   never changes, so the write costs nothing. */
.theatre { --sc-p: 0 !important; }

html { background: var(--frame); }
body { background: var(--frame); color: var(--sc-ink); }

.defs { position: absolute; width: 0; height: 0; overflow: hidden; }

.skip {
  position: fixed; left: 12px; top: 12px; z-index: 200;
  padding: 11px 16px;
  border-radius: 4px;
  background: var(--sc-ink); color: #fff;
  font: 600 15px/1 var(--sc-font-text);
  text-decoration: none;
  transform: translateY(calc(-100% - 24px));
}
.skip:focus-visible, .skip:focus { transform: none; outline-color: var(--gilt); }

/* ------------------------------------------------------------ the stage -- */
/* The frame's sizes. page.js measures the frame, so these are the only place
   they are set; in portrait it also sets --ab from the tallest card. */
.stage {
  --pw: clamp(22px, 3.6vw, 64px);     /* each pillar */
  --tv: clamp(58px, 9.2vh, 96px);     /* the pelmet, across the top */
  --ab: clamp(46px, 7.6vh, 84px);     /* the apron, across the bottom */
  --vd: clamp(14px, 2.6vh, 26px);     /* the drape under the pelmet */
  --g: clamp(18px, 2.2vw, 40px);
  --lark: 34px;
  --bar: 0px;                         /* the apron's run under the browser's bars */
  /* The back wall: bare, dark, lit where the sun hangs (.glow). */
  background:
    radial-gradient(ellipse 70% 42% at 50% 100%, rgb(255 190 110 / 0.12), transparent 70%),
    url("/assets/fibre-965e5f7073.webp") 0 0 / 320px 320px,
    linear-gradient(180deg, #222c45, #1a2236 55%, #121829);
}
/* The stage fills the screen, whatever the browser's own bars do. A phone's
   browser puts its bars away as the page scrolls and brings them back, and
   the screen's height changes with them. The stage is as tall as the screen
   with the bars away (100lvh), and the frame is laid out in the part that
   shows with the bars out (100svh). The apron takes the difference, --bar:
   with the bars out, the front of the stage floor is under them, and with
   them away it runs on to the bottom of the screen. Nothing is laid out
   again as they come and go, so nothing on stage moves. */
@supports (height: 100lvh) {
  html.ml-ready .stage { height: 100lvh; --bar: calc(100lvh - 100svh); }
}
/* page.js reads --bar here, as a length. */
.stage::after {
  content: ""; position: absolute; left: 0; top: 0;
  width: 0; height: var(--bar);
  visibility: hidden; pointer-events: none;
}
/* The sun's glow on the back wall, on a layer of its own, so the sun can
   carry it without the wall being redrawn. page.js moves its centre to where
   the sun hangs. The light fades out at 70% of its radius, and the layer ends
   there. */
.glow {
  position: absolute; left: 0; top: 0; z-index: 1;
  width: 58.8vmax; height: 58.8vmax;
  margin: -29.4vmax 0 0 -29.4vmax;
  background: radial-gradient(circle 42vmax at 50% 50%,
    rgb(255 214 150 / 0.2), rgb(255 214 150 / 0.07) 34%, transparent 70%);
  pointer-events: none;
  will-change: transform;
}

/* A drop hangs 40px past the opening on every side, behind the frame. */
.drop {
  position: absolute; z-index: 10;
  left: calc(var(--pw) - 40px); right: calc(var(--pw) - 40px);
  top: calc(var(--tv) - 40px); bottom: calc(var(--ab) + var(--bar) - 40px);
  will-change: transform;
}
.drop--sky {
  background:
    url("/assets/fibre-965e5f7073.webp") 0 0 / 320px 320px,
    linear-gradient(180deg, var(--sky) 0%, var(--sky) 38%, var(--sky-low) 72%);
}
/* A production's drop is its own texture on its own ink, lit by the sun's
   glow (page.js puts --dx/--dy where the sun hangs) and vignetted. */
.play .drop {
  background:
    radial-gradient(circle 46vmin at var(--dx, 62%) var(--dy, 24%),
      rgb(255 224 164 / 0.3), rgb(255 224 164 / 0.09) 46%, transparent),
    radial-gradient(ellipse 78% 74% at 50% 42%, transparent 52%, rgb(4 10 22 / 0.46)),
    linear-gradient(var(--wash), var(--wash)),
    var(--drop) 0 0 / var(--drop-size, 320px) var(--drop-size, 320px),
    var(--drop-ink, #0f2a44);
}

/* Every drop is weighted along its hem by a batten, seen as it flies. */
.drop::after {
  content: "";
  position: absolute; left: 0; right: 0; bottom: 0;
  height: 10px;
  background: linear-gradient(180deg, #4a3620, #2a1d10 60%, #1b130a);
  box-shadow: 0 2px 6px rgb(0 0 0 / 0.35);
}

/* The studio's landscape, fitted to the opening. */
.land {
  position: absolute;
  left: var(--pw); right: var(--pw); top: var(--tv); bottom: calc(var(--ab) + var(--bar));
  pointer-events: none;
}
.land--tall { display: none; }
.use-tall .land--wide { display: none; }
.use-tall .land--tall { display: block; }

.plane { position: absolute; inset: 0; z-index: 30; will-change: transform; }
/* The cut paper's shadow sits on the svg, not the moving plane, so it is
   painted into the plane's layer once. The svg reaches --pm past the opening
   (page.js sets it with the viewBox) and clips there. */
.plane svg {
  position: absolute;
  left: calc(var(--pm, 0) * -1px); top: calc(var(--pm, 0) * -1px);
  width: calc(100% + var(--pm, 0) * 2px); height: calc(100% + var(--pm, 0) * 2px);
  max-width: none; overflow: hidden;
  filter: drop-shadow(calc(var(--shx) * var(--gap) * 1px) calc(var(--shy) * var(--gap) * 1px)
                      calc(1.5px + var(--gap) * 2px) var(--shadow));
}

.f-cloud { fill: var(--cloud); }
.f-far { fill: var(--far); }
.f-snow { fill: var(--snow); }
.f-mid { fill: var(--mid); }
.f-coral { fill: var(--coral); }
.f-gold { fill: var(--gold); }
.f-water { fill: var(--water); }
.f-forest { fill: var(--forest); }
.f-pine { fill: var(--pine); }
.f-pine2 { fill: var(--pine2); }
.f-sand { fill: var(--sand); }
.f-dune { fill: var(--dune); }
.fib { fill: url(#fibre); }

/* ------------------------------------------------------------- the sun -- */
/* A paper disc on a wire from the flies. It hangs in front of any drop and
   behind every flat, so the far ridge can hide it at sunrise and sunset. */
.rig { position: absolute; inset: 0; z-index: 20; pointer-events: none; }
.wire {
  position: absolute; left: 0; top: 0;
  width: 1.5px; height: 0;
  background: linear-gradient(180deg, rgb(176 132 62 / 0), rgb(176 132 62 / 0.8) 36px);
  will-change: transform;
}
.sun {
  position: absolute; left: 0; top: 0;
  width: calc(var(--sun-d, 88) * 1px); height: calc(var(--sun-d, 88) * 1px);
  border-radius: 50%;
  background: url("/assets/fibre-965e5f7073.webp") 0 0 / 200px 200px, var(--sun);
  box-shadow: calc(var(--shx) * 1.2px) calc(var(--shy) * 1.2px) 7px var(--shadow),
              0 0 0 1px rgb(120 70 10 / 0.12);
  will-change: transform;
}
/* The path it can travel, shown while it is in hand. Cream with a dark edge,
   so it reads on a pale sky and on a dark drop alike. Once it has faded out
   it is hidden too, or it would hold a layer the size of the stage. */
.track {
  position: absolute; left: 0; top: 0; z-index: 20;
  width: 100%; height: 100%; max-width: none;
  overflow: visible; pointer-events: none;
  opacity: 0; visibility: hidden;
  transition: opacity 320ms var(--sc-ease-out), visibility 0s linear 320ms;
  filter: drop-shadow(0 0 1.2px rgb(16 12 8 / 0.8));
}
.show-track .track {
  opacity: 1; visibility: visible;
  transition: opacity 320ms var(--sc-ease-out), visibility 0s;
}
.track path {
  fill: none; stroke: #fff6e4;
  stroke-width: 2.4; stroke-linecap: round; stroke-dasharray: 0.1 11;
}

/* A transparent target over the disc. */
.sun-handle {
  position: absolute; left: 0; top: 0; z-index: 75;
  width: calc(var(--sun-d, 88) * 1px + 28px); height: calc(var(--sun-d, 88) * 1px + 28px);
  border-radius: 50%;
  cursor: grab;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
  will-change: transform;
}
.sun-handle.is-dragging { cursor: grabbing; }
.sun-handle:focus-visible { outline: 2px solid #fff6e4; outline-offset: -12px; border-radius: 50%; box-shadow: 0 0 0 13px transparent, inset 0 0 0 12px rgb(16 12 8 / 0.001); }
.sun-handle.is-off { cursor: default; }
.sun-handle.is-off:focus-visible { outline-color: transparent; }

/* The caption is a slip laid on the apron. */
.sun-caption {
  position: absolute; left: 0; top: 0; z-index: 80;
  /* As wide as it may be, whatever it says: page.js also holds it as tall as
     the longest thing it can say, so the slip keeps one size as the sun moves. */
  width: 100%; max-width: min(330px, calc(100vw - 32px));
  margin: 0; padding: 9px 13px 10px;
  border-radius: 3px;
  background: url("/assets/fibre-965e5f7073.webp") 0 0 / 200px 200px, var(--card);
  box-shadow: var(--card-shadow);
  font-size: 13.5px; line-height: 1.45;
  color: var(--sc-ink-soft);
  text-wrap: pretty;
  pointer-events: none;
  will-change: transform, opacity;
}
.sun-caption #sun-caption { color: var(--sc-ink); }

/* --------------------------------------------------- the productions --- */
.flat { position: absolute; left: 0; top: 0; z-index: 30; will-change: transform; }
.flat:not(.flat--garland) img {
  width: 100%; height: 100%;
  filter: drop-shadow(calc(var(--shx) * 1.6px) calc(var(--shy) * 1.6px) 10px rgb(0 0 0 / 0.45));
}
/* Medallions on threads. page.js hangs them and draws the threads. */
.flat--garland { --thread: rgb(226 190 122 / 0.78); }
.flat--garland img {
  position: absolute;
  filter: drop-shadow(calc(var(--shx) * 0.9px) calc(var(--shy) * 0.9px) 6px rgb(0 0 0 / 0.5));
}

/* The phone rises through the trap. */
.phone {
  position: absolute; left: 0; top: 0; z-index: 40; margin: 0;
  width: calc(var(--phone-h, 450) * 0.4625px); height: calc(var(--phone-h, 450) * 1px);
  padding: 2.4%;
  border-radius: 7.5% / 3.4%;
  background: linear-gradient(180deg, #241a12, #17110d 55%, #0f0b08);
  box-shadow: 0 0 0 1px rgb(155 119 61 / 0.7), 0 2px 0 rgb(255 255 255 / 0.06) inset;
  filter: drop-shadow(calc(var(--shx) * 2.2px) calc(var(--shy) * 2.2px) 14px rgb(0 0 0 / 0.55));
  will-change: transform;
}
.phone__screen {
  position: relative; width: 100%; height: 100%;
  overflow: hidden; border-radius: 5.4% / 2.4%;
  background: #0f0b08;
}
.phone__shot { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.phone__next { position: absolute; inset: 0; }
.phone__glass {
  position: absolute; inset: 0; pointer-events: none;
  background:
    linear-gradient(118deg, rgb(255 255 255 / 0.13) 0%, rgb(255 255 255 / 0.03) 26%, transparent 46%),
    var(--wash);
  box-shadow: 0 0 16px rgb(0 0 0 / 0.5) inset;
}

/* ---------------------------------------------------------- the curtain -- */
.curtain {
  position: absolute; z-index: 50;
  left: var(--pw); right: var(--pw); top: var(--tv); bottom: calc(var(--ab) + var(--bar));
  display: grid; grid-template-rows: 38fr auto 62fr; justify-items: center;
  will-change: transform;
}
/* Velvet folds, darker in the flies, warmer where the footlights reach, on a
   gilt hem. It runs up behind the pelmet and out behind the pillars. */
.curtain__cloth {
  position: absolute; left: -40px; right: -40px; top: -60px; bottom: 0;
  background:
    linear-gradient(0deg, #f0c25a 0 3px, #9c6b22 3px 4px, #e2ac48 4px 7px, rgb(58 10 4 / 0.4) 7px 9px, transparent 9px),
    linear-gradient(180deg, rgb(40 6 2 / 0.5), transparent 28%, transparent 70%, rgb(255 168 90 / 0.16)),
    url("/assets/fibre-965e5f7073.webp") 0 0 / 320px 320px,
    repeating-linear-gradient(90deg, #97240f 0, #bf3620 28px, #d9492d 52px, #bf3620 76px, #97240f 104px);
}
.curtain__line {
  grid-row: 2; position: relative;
  margin: 0; padding: 0 6%;
  text-align: center;
  color: #fbf1dc;
  font: 600 clamp(44px, min(7.4vw, 12.5vh), 118px) / 0.98 var(--sc-font-display);
  letter-spacing: -0.022em;
  text-shadow: 0 2px 0 rgb(90 16 6 / 0.45), 0 0 32px rgb(60 8 2 / 0.35);
}
.curtain__line span { display: block; }
.curtain__line:focus { outline: none; }
.curtain__line:focus-visible { outline: 2px solid #fbf1dc; outline-offset: 10px; }

/* ------------------------------------------------------ the proscenium -- */
.proscenium { position: absolute; inset: 0; z-index: 60; pointer-events: none; }
.pillar, .valance, .apron {
  position: absolute;
  background: url("/assets/fibre-965e5f7073.webp") 0 0 / 320px 320px, var(--frame);
}
.pillar { top: 0; bottom: 0; width: var(--pw); }
.pillar--l { left: 0; }
.pillar--r { right: 0; }
.valance { left: 0; right: 0; top: 0; height: var(--tv); }
.apron { left: 0; right: 0; bottom: 0; height: calc(var(--ab) + var(--bar)); }

/* The opening's depth, under the frame's edge. Painted first, so the drape
   hangs over it. */
.proscenium::before {
  content: ""; position: absolute;
  left: var(--pw); right: var(--pw); top: var(--tv); bottom: calc(var(--ab) + var(--bar));
  box-shadow: inset 0 34px 26px -18px rgb(0 0 0 / 0.42),
              inset 14px 0 22px -14px rgb(0 0 0 / 0.34),
              inset -14px 0 22px -14px rgb(0 0 0 / 0.34);
}
/* The gilt moulding up the pillars and across the top. The stage floor runs
   on under the footlights, so it stops there. */
.proscenium::after {
  content: ""; position: absolute;
  left: var(--pw); right: var(--pw); top: var(--tv); bottom: calc(var(--ab) + var(--bar));
  box-shadow: 0 0 0 1px var(--gilt-line), 0 0 0 4px var(--gilt), 0 0 0 5px var(--gilt-line),
              0 0 0 9px var(--frame), 0 0 0 10px rgb(154 109 34 / 0.45);
  clip-path: inset(-12px -12px 0 -12px);
}
/* The drape: velvet scallops on a gilt trim. */
.valance::before, .valance::after {
  content: ""; position: absolute;
  left: var(--pw); right: var(--pw); top: 100%;
  --r: calc(var(--vd) / 2);
  -webkit-mask:
    radial-gradient(circle var(--r) at 50% calc(100% - var(--r)), #000 97%, transparent) 0 0 / calc(var(--r) * 2) 100% repeat-x,
    linear-gradient(#000 0 0) 0 0 / 100% calc(100% - var(--r)) no-repeat;
          mask:
    radial-gradient(circle var(--r) at 50% calc(100% - var(--r)), #000 97%, transparent) 0 0 / calc(var(--r) * 2) 100% repeat-x,
    linear-gradient(#000 0 0) 0 0 / 100% calc(100% - var(--r)) no-repeat;
}
.valance::before { height: calc(var(--vd) + 3px); background: var(--gilt); }
.valance::after {
  height: var(--vd);
  background:
    url("/assets/fibre-965e5f7073.webp") 0 0 / 200px 200px,
    linear-gradient(180deg, #8e2311, #b8331e 55%, #cf4529);
}
/* The footlights: a lip along the stage's edge, a row of lamps, and their
   light thrown up onto whatever is on stage. */
.apron::before {
  content: ""; position: absolute;
  left: var(--pw); right: var(--pw); top: 0; height: 9px;
  background:
    radial-gradient(circle at 50% 45%, #fffbe8 0 1.6px, #ffd680 2.6px, rgb(255 200 110 / 0) 5px) 0 0 / 44px 9px repeat-x,
    linear-gradient(180deg, #6b4f31, #45321d);
  box-shadow: 0 1px 0 rgb(255 255 255 / 0.4);
}
.apron::after {
  content: ""; position: absolute;
  left: var(--pw); right: var(--pw); bottom: 100%;
  height: clamp(36px, 10vh, 120px);
  background: linear-gradient(0deg, rgb(255 200 120 / 0.2), rgb(255 200 120 / 0.06) 45%, transparent);
}

/* ------------------------------------------------------------ the pelmet -- */
.pelmet { position: absolute; inset: 0; z-index: 90; pointer-events: none; }
.pelmet__name {
  position: absolute; left: 50%; top: calc(var(--tv) / 2 - 2px);
  transform: translate(-50%, -50%);
  display: inline-flex; align-items: center; gap: 10px;
  padding: 6px 6px;
  font: 600 clamp(22px, 1.05rem + 0.7vw, 32px) / 1 var(--sc-font-display);
  letter-spacing: -0.01em;
  color: var(--sc-ink); text-decoration: none;
  pointer-events: auto;
}
/* Where the lark sits when it is home. */
.pelmet__perch { flex: none; width: var(--lark); height: var(--lark); }

/* The act card: an easel on the apron naming what is on stage. It opens the
   programme, which lists every scene. */
.bill {
  position: absolute; right: calc(var(--pw) + var(--g)); bottom: calc(var(--bar) + var(--ab) * 0.36);
  pointer-events: auto;
}
.actcard {
  position: relative;
  display: grid; justify-items: start; gap: 3px;
  min-width: 154px;
  margin: 0; padding: 9px 38px 10px 14px;
  border: 0; border-radius: 4px;
  background: url("/assets/fibre-965e5f7073.webp") 0 0 / 200px 200px, var(--card);
  box-shadow: var(--card-shadow);
  color: var(--sc-ink);
  text-align: left;
  cursor: pointer;
}
.actcard::after {
  content: ""; position: absolute; right: 15px; top: 50%;
  width: 8px; height: 8px; margin-top: -2px;
  border: solid var(--sc-ink); border-width: 0 1.6px 1.6px 0;
  transform: translateY(-50%) rotate(-135deg);
  transition: transform 220ms var(--sc-ease-out);
}
.is-open .actcard::after { transform: translateY(-20%) rotate(45deg); }
.actcard__label {
  font: 650 11px/1 var(--sc-font-text);
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--accent-deep);
}
.actcard__now { font: 600 18px/1.15 var(--sc-font-display); white-space: nowrap; }

.programme {
  position: absolute; right: 0; bottom: calc(100% + 8px);
  min-width: 100%;
  margin: 0; padding: 7px;
  list-style: none;
  border-radius: 4px;
  background: url("/assets/fibre-965e5f7073.webp") 0 0 / 200px 200px, var(--card);
  box-shadow: var(--card-shadow);
}
.programme[hidden] { display: none; }
.programme a {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 12px;
  border-radius: 3px;
  font: 600 17px/1.2 var(--sc-font-display);
  color: var(--sc-ink); text-decoration: none; white-space: nowrap;
}
.programme a::before {
  content: ""; flex: none; width: 6px; height: 6px; border-radius: 50%;
  background: transparent; box-shadow: 0 0 0 1px rgb(19 28 51 / 0.3);
}
.programme a:hover { background: rgb(208 43 28 / 0.08); }
.programme a[aria-current] { color: var(--accent-deep); }
.programme a[aria-current]::before { background: var(--accent); box-shadow: none; }

/* ------------------------------------------------------------- the cards -- */
/* Programme cards stand on the apron in front of the frame. page.js places
   each one; the engine lights and dims it. */
.card {
  position: absolute; left: 0; top: 0; z-index: 80;
  margin: 0;
  pointer-events: none;
  will-change: transform;
}
.card--house { width: clamp(260px, 29vw, 420px); }
.card--play { width: clamp(270px, 28vw, 400px); }
.card--playbill { width: min(780px, calc(100vw - 2 * var(--pw) - 2 * var(--g) - 196px)); }

/* The paper is the element the engine cues, so it fades and rises with its
   words; a card that tilts does so from a wrapper around it. */
.card__paper {
  margin: 0;
  border-radius: 4px;
  background: url("/assets/fibre-965e5f7073.webp") 0 0 / 200px 200px, var(--card);
  box-shadow: var(--card-shadow);
  color: var(--sc-ink);
  /* a printed rule, just inside the edge */
  outline: 1px solid rgb(208 43 28 / 0.22); outline-offset: -6px;
}
.card__paper > * { margin: 0; }

.house-line {
  padding: 18px 22px 19px;
  font: 500 clamp(18px, 0.98rem + 0.36vw, 23px) / 1.36 var(--sc-font-display);
  letter-spacing: -0.006em;
  text-wrap: pretty;
}

.card--play .card__paper { padding: clamp(20px, 1.8vw, 28px) clamp(20px, 1.9vw, 30px) clamp(16px, 1.5vw, 22px); }
.card__kicker {
  font: 650 12px/1.2 var(--sc-font-text);
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--accent-deep);
}
.card__name {
  margin-top: 0.3em !important;
  font: 600 clamp(36px, 1.25rem + 2vw, 54px) / 1 var(--sc-font-display);
  letter-spacing: -0.022em;
  color: var(--sc-ink);
}
.card__name:focus { outline: none; }
.card__name:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }
.card__line {
  margin-top: 0.34em !important;
  font: italic 500 clamp(17px, 0.92rem + 0.4vw, 22px) / 1.25 var(--sc-font-display);
  color: var(--sc-ink);
  text-wrap: balance;
}
.card__text {
  margin-top: 0.8em !important;
  font-size: clamp(14.5px, 0.84rem + 0.18vw, 16.5px);
  line-height: 1.52;
  color: var(--sc-ink-soft);
  text-wrap: pretty;
}
.card__act {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 12px 14px;
  margin-top: 1.15em !important;
}
.cta {
  display: inline-flex; align-items: center; gap: 0.7em;
  padding: 0.9em 1.4em 0.93em;
  border-radius: 5px;
  background: var(--accent);
  color: #fff;
  font: 550 clamp(15px, 0.9rem + 0.12vw, 17px) / 1 var(--sc-font-text);
  text-decoration: none; white-space: nowrap;
  box-shadow: 0 1px 0 rgb(255 255 255 / 0.18) inset, 0 3px 8px -2px rgb(90 20 10 / 0.45);
  transition: background-color 180ms var(--sc-ease-out);
}
.cta:hover { background: var(--accent-deep); }
.cta:focus-visible { outline-color: var(--sc-ink); outline-offset: 3px; }
.cta__arrow { width: 1.15em; height: 0.8em; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
/* The store row's pieces join the act row, so the button and both badges
   share a line and wrap together under it.
   Each store's own badge, unaltered. Google's file carries the quarter-height
   clear space it asks for inside the image — a 564x168 badge with 41px all
   round, so the badge is 67.2% of the image's height — and Apple's does not.
   So the Play image is drawn 1/0.672 taller, and its padding is pulled back
   in, for the two badges to come out the same height on the same line. */
.card__stores { display: contents; }
.badge { display: block; border-radius: 7px; }
.badge img { width: auto; height: var(--badge-h, 40px); }
.badge--play { margin: calc(var(--badge-h, 40px) / -4); }
.badge--play img { height: calc(var(--badge-h, 40px) / 0.672); }
.card__links {
  display: flex; flex-wrap: wrap; gap: 0 16px;
  margin-top: 1.05em !important; padding-top: 0.7em;
  border-top: 1px solid var(--rule);
  font-size: 13px; line-height: 1.4;
}
/* Padded so each link is at least 24px tall. */
.card__links a { display: inline-block; padding: 4px 0; color: var(--sc-ink); text-decoration-color: rgb(19 28 51 / 0.32); }
.card__links a:hover { text-decoration-color: currentColor; }

/* The playbill: the house's address, and every production on the bill. */
.card--playbill .card__paper {
  display: grid; grid-template-columns: 1.2fr 1fr;
  gap: 18px 34px;
  padding: 26px 30px 18px;
}
.card--playbill .card__name { margin-top: 0 !important; font-size: clamp(34px, 1.2rem + 1.6vw, 48px); }
.playbill__hello > *, .playbill__bill > * { margin: 0; }
.playbill__mail { margin-top: 0.85em !important; }
.playbill__mail a {
  font: 600 clamp(17px, 0.95rem + 0.3vw, 20px) / 1.3 var(--sc-font-display);
  color: var(--accent-deep);
  text-decoration-color: rgb(208 43 28 / 0.4);
  overflow-wrap: anywhere;
}
.playbill__bill { padding-left: 30px; border-left: 1px solid var(--rule); }
.playbill__plays { display: grid; gap: 12px; margin: 0.8em 0 0; padding: 0; list-style: none; }
.playbill__plays li { display: grid; gap: 2px; }
.playbill__name {
  justify-self: start;
  font: 600 25px/1.1 var(--sc-font-display);
  color: var(--sc-ink);
  text-decoration-color: rgb(19 28 51 / 0.3);
}
.playbill__name:hover { text-decoration-color: currentColor; }
.playbill__kind { font-size: 13px; color: var(--sc-ink-soft); }
.playbill__small {
  grid-column: 1 / -1;
  padding-top: 11px;
  border-top: 1px solid var(--rule);
  font-size: 12.5px; color: var(--sc-ink-soft);
}

.lark {
  position: absolute; left: 0; top: 0; z-index: 70;
  width: var(--lark); height: var(--lark);
  pointer-events: none;
  transform-origin: 50% 50%;
  will-change: transform, opacity;
}

/* -------------------------------------------------------------- portrait -- */
/* A narrow screen keeps the whole theatre: the pillars thin, the pelmet
   carries the programme, and the apron deepens into a forestage the cards
   stand on, below the opening rather than in front of it. */
@media (max-aspect-ratio: 11/10) {
  .stage { --pw: 10px; --tv: 58px; --ab: 38vh; --vd: 12px; --g: 16px; --lark: 28px; }
  .pelmet__name { left: 12px; transform: translateY(-50%); gap: 8px; font-size: 22px; }
  .bill { right: 10px; bottom: auto; top: calc(var(--tv) / 2 - 2px); transform: translateY(-50%); }
  .actcard { min-width: 0; padding: 6px 32px 7px 12px; gap: 2px; }
  .actcard::after { right: 12px; transform: translateY(-50%) rotate(45deg); margin-top: -3px; }
  .is-open .actcard::after { transform: translateY(-10%) rotate(-135deg); }
  .actcard__label { font-size: 10px; }
  .actcard__now { font-size: 15px; }
  .programme { top: calc(100% + 8px); bottom: auto; }
  .proscenium::after {
    box-shadow: 0 0 0 1px var(--gilt-line), 0 0 0 3px var(--gilt), 0 0 0 4px var(--gilt-line);
    clip-path: inset(-6px -6px 0 -6px);
  }
  .apron::before { background-size: 34px 9px, auto; }
  /* The forestage is a floor, its boards running out toward the audience,
     with the footlights' spill across its near edge. */
  .apron {
    background:
      linear-gradient(180deg, rgb(255 214 140 / 0.18), transparent 30%),
      url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' preserveAspectRatio='none'%3E%3Cpath d='M50 -70L-104 100 M50 -70L-90 100 M50 -70L-76 100 M50 -70L-62 100 M50 -70L-48 100 M50 -70L-34 100 M50 -70L-20 100 M50 -70L-6 100 M50 -70L8 100 M50 -70L22 100 M50 -70L36 100 M50 -70L50 100 M50 -70L64 100 M50 -70L78 100 M50 -70L92 100 M50 -70L106 100 M50 -70L120 100 M50 -70L134 100 M50 -70L148 100 M50 -70L162 100 M50 -70L176 100 M50 -70L190 100 M50 -70L204 100' fill='none' stroke='rgb(110,74,22)' stroke-opacity='.17' stroke-width='1' vector-effect='non-scaling-stroke'/%3E%3C/svg%3E") 0 0 / 100% 100% no-repeat,
      url("/assets/fibre-965e5f7073.webp") 0 0 / 320px 320px,
      var(--frame);
  }

  .card--house, .card--play, .card--playbill { width: min(560px, calc(100vw - 32px)); }
  .sun-caption { max-width: min(560px, calc(100vw - 32px)); }
  .house-line { padding: 14px 18px 15px; font-size: 18px; text-align: center; }
  .card--play .card__paper { padding: 17px 19px 12px; }
  .card__name { font-size: 34px; margin-top: 0.22em !important; }
  .card__line { font-size: 17px; }
  .card__text { font-size: 14.5px; line-height: 1.45; margin-top: 0.6em !important; }
  .card__act { --badge-h: 38px; gap: 10px 12px; margin-top: 0.9em !important; }
  .cta { padding: 0.82em 1.15em 0.85em; font-size: 15px; }
  .card__links { gap: 0 14px; margin-top: 0.8em !important; padding-top: 0.45em; }
  .card--playbill .card__paper { grid-template-columns: 1fr; gap: 14px; padding: 20px 20px 14px; }
  .card--playbill .card__name { font-size: 34px; }
  .playbill__bill { padding: 14px 0 0; border-left: 0; border-top: 1px solid var(--rule); }
  .playbill__plays { margin-top: 0.6em; }
  .playbill__name { font-size: 22px; }
}

/* ------------------------------------------------------ short and wide -- */
/* A phone on its side keeps the wide stage, with a slimmer frame and tighter
   cards, so that every card fits the height and its links stay on screen.
   The programme moves up to the pelmet's right-hand end, as on a narrow
   screen, and leaves the whole apron to the cards. */
@media (min-aspect-ratio: 11/10) and (max-height: 620px) {
  .stage { --tv: clamp(44px, 11vh, 58px); --ab: clamp(32px, 8.5vh, 46px); --vd: 11px; --lark: 26px; }
  .pelmet__name { gap: 8px; font-size: 21px; }
  .bill { right: calc(var(--pw) + 6px); bottom: auto; top: calc(var(--tv) / 2 - 2px); transform: translateY(-50%); }
  .actcard { min-width: 0; padding: 5px 30px 6px 11px; gap: 2px; }
  .actcard::after { right: 11px; transform: translateY(-50%) rotate(45deg); margin-top: -3px; }
  .is-open .actcard::after { transform: translateY(-10%) rotate(-135deg); }
  .actcard__label { font-size: 9.5px; }
  .actcard__now { font-size: 14.5px; }
  .programme { top: calc(100% + 8px); bottom: auto; }
  .card--playbill { width: min(780px, calc(100vw - 2 * var(--pw) - 2 * var(--g))); }
  .curtain { grid-template-rows: 14fr auto 86fr; }
  .curtain__line { font-size: clamp(32px, 11.5vh, 60px); }

  .card--house { width: clamp(240px, 32vw, 380px); }
  .card--play { width: clamp(270px, 36vw, 380px); }
  .house-line { padding: 11px 15px 12px; font-size: 15.5px; }
  .sun-caption { max-width: min(300px, 40vw); padding: 7px 11px 8px; font-size: 12px; }
  .card--play .card__paper { padding: 13px 16px 8px; }
  .card__kicker { font-size: 10.5px; }
  .card__name { font-size: 28px; margin-top: 0.2em !important; }
  .card__line { font-size: 15px; margin-top: 0.25em !important; }
  .card__text { font-size: 12.5px; line-height: 1.42; margin-top: 0.5em !important; }
  .card__act { --badge-h: 32px; gap: 7px 10px; margin-top: 0.65em !important; }
  .cta { padding: 0.66em 0.95em 0.7em; font-size: 13.5px; }
  .card__links { gap: 0 12px; margin-top: 0.5em !important; padding-top: 0.25em; font-size: 12px; }
  .card--playbill .card__paper { gap: 10px 22px; padding: 14px 18px 10px; }
  .card--playbill .card__name { font-size: 26px; }
  .playbill__mail { margin-top: 0.55em !important; }
  .playbill__mail a { font-size: 16px; }
  .playbill__plays { gap: 8px; margin-top: 0.5em; }
  .playbill__name { font-size: 18px; }
}

@media (prefers-reduced-motion: reduce) {
  .track, .actcard::after { transition: none; }
}

/* Before page.js has placed things, the first paint is the frame and the
   curtain alone: nothing that still needs placing. Everything else is behind
   the curtain until then. The stage is already sticky, as the engine makes
   it, because the engine checks that its stage pins before page.js is ready.
   Kept to :where() so that noscript.css, the page without script, can undo it
   plainly. */
:where(html:not(.ml-ready)) .stage { position: sticky; top: 0; height: 100vh; height: 100svh; overflow: clip; }
:where(html:not(.ml-ready)) :where(.glow, .lark, .sun-handle, .sun-caption, .card, .rig, .track, .phone, .flat, .play .drop) { visibility: hidden; }
