/* Spud & Root: home/window.html (you look out the window). Loaded after site.css.
   The view outside is drawn live by window-gl.js on a canvas in .outside,
   behind the room. The room's wall has a hole where the glass is (.is-live),
   and the window, curtains and sill sit in front of it. Until the view is
   live (and without JavaScript or WebGL) the glass shows a still picture of
   it instead. When you lean out of the window, window.js moves the whole
   .room past you and then hides it (.is-out). */

/* the lamp on the sill: 1 on, 0 off (window.js), fading between */
@property --lamp {
  syntax: "<number>";
  inherits: true;
  initial-value: 0;
}

/* (said only when it's true: without JavaScript nothing can be handled) */
html:not(.js) .js-only {
  display: none;
}

.window-page {
  overflow: hidden;
  background: var(--cream);
}

.window-room {
  /* Window size: the glass is --ww by --wh, and everything scales off it */
  --casing: clamp(12px, 2.4vmin, 28px);
  /* Room above the glass for the rod, and below it for the sill, apron and the controls */
  --above: calc(var(--casing) * 1.6 + 42px);
  --below: calc(var(--casing) * 2.1 + 24px);
  --ui-h: 104px; /* the hint or the button to lean out, and the link home, with room below them */
  --reserve: calc(var(--above) + var(--below) + var(--ui-h));
  /* Set by window.js from the time of day: how dark the room is (it's
     lamp-lit after dark), and how much it's night; how far the curtains
     are drawn across (0 open to 1 shut); and whether the lamp's on */
  --dim: 0;
  --night: 0;
  --drawn: 0;
  --lamp: 0;
  transition: --lamp 0.22s ease;
  --ww: min(calc(84vw - 2 * var(--casing)), 1100px, calc((100vh - var(--reserve)) * 1.75));
  --wh: min(calc(100vh - var(--reserve)), calc(var(--ww) * 1.75));
  --bar: calc(var(--ww) * 0.005 + 4px); /* muntins between panes */
  --stile: calc(var(--ww) * 0.01 + 7px); /* sash frames */
  --curtain: calc(var(--ww) * 0.08 + 30px);
  --cols: 3;
  /* Where the glass is in the room */
  --win-top: calc((100% - var(--wh) - var(--reserve)) / 2 + var(--above));
  --win-left: calc(50% - var(--ww) / 2);
  /* Paint */
  --trim: #fcf8ef;
  --trim-shade: #ebe2cf;
  --brass: #d7a63c;
  --brass-light: #f2cf74;
  --wood: #6b4728;
  --cloth: var(--herb-dark);
  --cloth-fold: #2f4c25;
  --cloth-light: #5b8445;
  --wainscot: #dfe4cf;
  position: relative;
}
@supports (height: 1svh) {
  .window-room {
    --ww: min(calc(84vw - 2 * var(--casing)), 1100px, calc((100svh - var(--reserve)) * 1.75));
    --wh: min(calc(100svh - var(--reserve)), calc(var(--ww) * 1.75));
  }
}
@media (max-aspect-ratio: 1/1) {
  .window-room {
    --cols: 2;
  }
}

.stage {
  position: relative;
  height: 100vh;
  height: 100svh;
  min-height: 320px;
  overflow: hidden;
}

/* ---------- Outside: the view, drawn live ---------- */
.outside {
  position: absolute;
  inset: 0;
  overflow: hidden;
}
.outside canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  opacity: 0;
  transition: opacity 0.8s ease;
}
.is-live .outside canvas {
  opacity: 1;
}
.is-out .outside {
  cursor: grab;
  touch-action: none;
}
.is-out.is-grabbing .outside {
  cursor: grabbing;
}

/* ---------- The room ---------- */
.room {
  position: absolute;
  inset: 0;
  transform-origin: 0 0;
}
.is-leaning .room {
  will-change: transform;
}
.is-out .room {
  visibility: hidden;
}

/* The wall: sprig wallpaper above a chair rail and beadboard, lit by the
   window by day and by the lamp on the sill after dark (and dark without it) */
.wall {
  position: absolute;
  inset: 0;
  --rail: calc(var(--win-top) + var(--wh) + var(--below) - 6px);
  /* how dark: warm and dim by the lamp, deep and blue in the moonlight without it */
  --dark: calc(var(--dim) * var(--lamp));
  --moonlit: calc(var(--dim) * 2.1 * (1 - var(--lamp)));
  background:
    /* the lamp on the sill */
    radial-gradient(ellipse calc(var(--ww) * 0.9) calc(var(--wh) * 1.1) at calc(var(--win-left) + var(--ww) * 0.07) calc(var(--win-top) + var(--wh)),
      rgba(255, 176, 92, calc((var(--dim) * 1.6 + 0.08) * var(--lamp))), rgba(255, 176, 92, 0) 75%),
    linear-gradient(rgba(58, 36, 34, var(--dark)), rgba(58, 36, 34, var(--dark))),
    linear-gradient(rgba(20, 26, 50, var(--moonlit)), rgba(20, 26, 50, var(--moonlit))),
    /* the afternoon light from the window */
    radial-gradient(ellipse 70% 60% at 50% 46%, rgba(255, 196, 120, calc((0.3 - var(--dim)) * (1 - var(--drawn) * 0.7))), rgba(255, 196, 120, 0) 70%),
    /* chair rail */
    linear-gradient(transparent calc(var(--rail) - 3px), var(--ink) calc(var(--rail) - 3px), var(--ink) var(--rail),
      var(--trim) var(--rail), var(--trim) calc(var(--rail) + 9px), var(--trim-shade) calc(var(--rail) + 9px),
      var(--trim-shade) calc(var(--rail) + 13px), var(--ink) calc(var(--rail) + 13px), var(--ink) calc(var(--rail) + 16px),
      rgba(35, 31, 32, 0.18) calc(var(--rail) + 16px), transparent calc(var(--rail) + 24px)),
    /* beadboard below it */
    linear-gradient(transparent var(--rail), var(--wainscot) var(--rail)),
    /* the wallpaper */
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='88' height='88' viewBox='0 0 88 88'%3E%3Cg fill='none' stroke='%23a2ab83' stroke-width='1.4' stroke-linecap='round'%3E%3Cpath d='M18 32c1-6 5-11 11-13M23 24c-4-1-7 0-9 2M26 21c1-4 0-7-2-9'/%3E%3Cpath d='M62 76c1-6 5-11 11-13M67 68c-4-1-7 0-9 2M70 65c1-4 0-7-2-9'/%3E%3C/g%3E%3Cg fill='%23b9c196'%3E%3Cellipse cx='14' cy='26' rx='3.4' ry='1.6' transform='rotate(-30 14 26)'/%3E%3Cellipse cx='24' cy='12' rx='3.4' ry='1.6' transform='rotate(70 24 12)'/%3E%3Cellipse cx='58' cy='70' rx='3.4' ry='1.6' transform='rotate(-30 58 70)'/%3E%3Cellipse cx='68' cy='56' rx='3.4' ry='1.6' transform='rotate(70 68 56)'/%3E%3C/g%3E%3Cg fill='%23d29b7b'%3E%3Ccircle cx='30' cy='18.6' r='1.9'/%3E%3Ccircle cx='74' cy='62.6' r='1.9'/%3E%3C/g%3E%3C/svg%3E"),
    repeating-linear-gradient(90deg, transparent 0 40px, rgba(188, 97, 36, 0.045) 40px 44px),
    #fbf3e1;
}
/* the grooves of the beadboard, only below the rail */
.wall::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  top: calc(var(--rail) + 16px);
  /* (the wall under it is already darkened: these only dim the grooves' highlights) */
  background:
    linear-gradient(rgba(58, 36, 34, calc(var(--dark) * 0.35)), rgba(58, 36, 34, calc(var(--dark) * 0.35))),
    linear-gradient(rgba(20, 26, 50, calc(var(--moonlit) * 0.35)), rgba(20, 26, 50, calc(var(--moonlit) * 0.35))),
    repeating-linear-gradient(90deg, transparent 0 22px, rgba(35, 31, 32, 0.16) 22px 24px, rgba(255, 255, 255, 0.45) 24px 25.5px, transparent 25.5px 26px);
}
/* The wall has a hole where the glass is, once the view is drawn live
   behind it */
.is-live .wall {
  clip-path: polygon(evenodd, 0 0, 100% 0, 100% 100%, 0 100%, 0 0,
    var(--win-left) var(--win-top), calc(var(--win-left) + var(--ww)) var(--win-top),
    calc(var(--win-left) + var(--ww)) calc(var(--win-top) + var(--wh)), var(--win-left) calc(var(--win-top) + var(--wh)),
    var(--win-left) var(--win-top));
}

/* ---------- The window ---------- */
/* After dark the room is lamp-lit: the woodwork, curtains and sill go warm
   and a little dim; with the lamp off, dimmer and not warm */
.casing,
.sashes,
.rod,
.curtain__art,
.sill {
  filter: brightness(calc(1 - var(--dim) * (1.4 - 0.9 * var(--lamp)))) sepia(calc(var(--dim) * 0.9 * var(--lamp)))
    saturate(calc(1 - var(--dim) * 1.2 * (1 - var(--lamp))));
}
.window {
  position: absolute;
  left: var(--win-left);
  top: var(--win-top);
  width: var(--ww);
  height: var(--wh);
}
/* Casing (the trim round the window): a frame, open where the glass is, with
   a backband round its outer edge and a head cap across the top */
.casing {
  position: absolute;
  inset: calc(-1 * var(--casing)) calc(-1 * var(--casing)) 0;
  border: var(--casing) solid var(--trim);
  border-bottom: 0;
  border-radius: 2px 2px 0 0;
  box-shadow: 0 0 0 5px var(--ink), 6px 8px 0 5px rgba(35, 31, 32, 0.08);
}
.casing::before {
  content: "";
  position: absolute;
  inset: calc(var(--casing) * -0.74) calc(var(--casing) * -0.74) 0;
  border: 2.5px solid rgba(35, 31, 32, 0.38);
  border-bottom: 0;
  border-radius: 2px 2px 0 0;
  box-shadow: inset 2px 2px 0 rgba(255, 255, 255, 0.8);
}
.casing::after {
  content: "";
  position: absolute;
  left: calc(-10px - var(--casing) * 1.35);
  right: calc(-10px - var(--casing) * 1.35);
  top: calc(-10px - var(--casing) * 1.55);
  height: calc(var(--casing) * 0.7 + 4px);
  background: linear-gradient(var(--trim) 55%, var(--trim-shade) 55%);
  border: 5px solid var(--ink);
  border-radius: 4px;
}

.glass {
  position: absolute;
  inset: 0;
  overflow: hidden;
  /* a sky-ish colour until the view's there (window.js sets it for the time of day) */
  background: var(--glass-bg, linear-gradient(#a9cbe3, #f3dcb4 60%, #c99c4c 60.5%));
  box-shadow: 0 0 0 5px var(--ink);
  /* The view is 1600 by 1000 units, scaled to cover the glass (--u is the
     size of a unit) and centred on x = 800 + --shift. On a tall window it
     looks a bit to the right, to the village. window.js reads --shift, so
     keep it a plain number. */
  --u: max(calc(var(--ww) / 1600), calc(var(--wh) / 1000));
  --shift: 0;
}
@media (max-aspect-ratio: 1/1) {
  .glass {
    --shift: 110;
  }
}
.is-live .glass {
  background: none;
}
/* The view as a picture */
.still {
  position: absolute;
  display: block;
  max-width: none;
  left: calc(50% - (800 + var(--shift)) * var(--u));
  top: calc(50% - 500 * var(--u));
  width: calc(1600 * var(--u));
  height: calc(1000 * var(--u));
}
/* the branch, pinned to the top left of the glass (its picture reaches back
   along the limb past the left edge, with a little apron all round) */
.still-branch {
  --bw: clamp(230px, 46%, 620px);
  position: absolute;
  display: block;
  max-width: none;
  left: calc(-3% - var(--bw) * 222.857 / 600);
  top: calc(-3% - var(--bw) * 2.857 / 600);
  width: calc(var(--bw) * 825.714 / 600);
  height: auto;
}
.is-live .still,
.is-live .still-branch,
.is-dark .still,
.is-dark .still-branch {
  visibility: hidden;
}

/* ---------- Sashes (two, one above the other) and their panes ---------- */
.sashes {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.sash {
  position: absolute;
  left: 0;
  right: 0;
  height: 50%;
  box-sizing: border-box;
  display: grid;
  grid-template-columns: repeat(var(--cols), 1fr);
  gap: var(--bar);
  border: calc(var(--stile) - var(--bar) / 2) solid var(--trim);
  -webkit-tap-highlight-color: transparent;
}
.sash--top {
  top: 0;
  border-bottom-width: calc(var(--stile) * 0.75);
  box-shadow: inset 0 0 0 1.5px rgba(35, 31, 32, 0.08);
}
.sash--bottom {
  bottom: 0;
  z-index: 1; /* it slides up in front of the top one */
  border-top-width: calc(var(--stile) * 0.75);
  box-shadow: 0 -3px 0 var(--ink), 0 -6px 0 rgba(35, 31, 32, 0.12);
}
/* window.js slides them; --lift is how far each has moved, in sash heights */
.sash--top {
  transform: translateY(calc(var(--top-lift, 0) * 100%));
}
.sash--bottom {
  transform: translateY(calc(var(--bottom-lift, 0) * -100%));
}
.js-room .sash {
  pointer-events: auto;
  cursor: ns-resize;
  touch-action: none;
}
.js-room .sash:focus {
  outline: none;
}
.js-room .sash:focus-visible::after {
  content: "";
  position: absolute;
  inset: 6px;
  outline: 4px solid var(--potato-gold);
  border-radius: 2px;
  pointer-events: none;
}
.sash i {
  border: 3px solid var(--ink);
  box-shadow: 0 0 0 calc(var(--bar) / 2) var(--trim);
  /* A little sheen on the glass */
  background:
    /* after dark the glass catches the lamp-lit room (not with the lamp off) */
    linear-gradient(160deg, rgba(255, 210, 150, calc(var(--night) * 0.14 * var(--lamp))), rgba(255, 210, 150, calc(var(--night) * 0.04 * var(--lamp)))),
    linear-gradient(118deg,
    rgba(255, 255, 255, 0) 0 28%,
    rgba(255, 255, 255, calc(0.13 - var(--night) * 0.09)) 28% 36%,
    rgba(255, 255, 255, 0) 36% 41%,
    rgba(255, 255, 255, calc(0.08 - var(--night) * 0.055)) 41% 44%,
    rgba(255, 255, 255, 0) 44%);
}
/* Three panes a sash, or two on a tall screen (to match --cols above) */
@media (max-aspect-ratio: 1/1) {
  .sash i:nth-of-type(3) {
    display: none;
  }
}
/* Lift handles on the bottom rail */
.lift {
  position: absolute;
  bottom: calc(var(--bar) / 2 - var(--stile) + 3px);
  width: calc(var(--stile) * 1.8);
  height: calc(var(--stile) * 0.55);
  background: linear-gradient(var(--brass-light), var(--brass) 60%);
  border: 3px solid var(--ink);
  border-radius: 4px 4px 999px 999px;
}
.lift--1 { left: 22%; }
.lift--2 { right: 22%; }

/* Crescent locks: each screwed to the bottom sash's meeting rail, its cam
   swinging over into a keeper on the top sash's. Locked, the cam reaches
   left into the keeper; unlocked, it's swung back to the right. */
.lock {
  position: absolute;
  z-index: 2;
  bottom: calc(100% + var(--stile) * 0.75 - var(--bar) / 2 - var(--stile) * 0.62);
  width: calc(var(--stile) * 3.4);
  height: calc(var(--stile) * 1.48);
  margin: 0 0 0 calc(var(--stile) * -1.7);
  padding: 0;
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  appearance: none;
  -webkit-appearance: none;
  -webkit-tap-highlight-color: transparent;
  pointer-events: none;
  perspective: calc(var(--stile) * 8);
}
.lock--1 { left: 25%; }
.lock--2 { left: 75%; }
.lock svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}
.lock path,
.lock circle {
  stroke: var(--ink);
  stroke-width: 2.6px;
  stroke-linejoin: round;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}
.lock__base path:first-child,
.lock__crescent,
.lock__knob {
  fill: var(--brass);
}
.lock__screw {
  fill: none;
  stroke-width: 1.6px !important;
}
.lock__lever {
  fill: none;
  stroke-width: 3.4px !important;
}
.lock__cam {
  position: absolute;
  inset: 0;
  transform-origin: 50% 50%;
  transform: rotateY(var(--turn, 0deg));
  transition: transform 0.36s cubic-bezier(0.3, 0.6, 0.3, 1.2);
}
.lock[aria-pressed="false"] {
  --turn: 180deg;
}
/* a bigger target than it looks, for a finger */
.lock::after {
  content: "";
  position: absolute;
  inset: -12px -8px;
}
.js-room .lock:enabled {
  pointer-events: auto;
  cursor: pointer;
}
.lock:focus {
  outline: none;
}
.lock:focus-visible .lock__base {
  outline: 3px solid var(--potato-gold);
  outline-offset: 2px;
  border-radius: 4px;
}
.lock.is-rattling {
  animation: w-rattle 0.32s linear;
}
@keyframes w-rattle {
  0%, 100% { transform: translate(0, 0) rotate(0); }
  20% { transform: translate(-1.5px, 0) rotate(-5deg); }
  45% { transform: translate(1.5px, -1px) rotate(5deg); }
  70% { transform: translate(-1px, 0) rotate(-2deg); }
}
/* The keepers the cams swing into */
.keeper {
  position: absolute;
  bottom: calc(var(--stile) * -0.75 - var(--bar) / 2 + var(--stile) * 0.42);
  width: calc(var(--stile) * 1.05);
  height: calc(var(--stile) * 0.5);
  margin-left: calc(var(--stile) * -1.72);
  background: var(--brass);
  border: 2.6px solid var(--ink);
  border-radius: 999px 3px 3px 999px;
  box-shadow: inset 0 calc(var(--stile) * 0.14) 0 var(--brass-light);
}
.keeper--1 { left: 25%; }
.keeper--2 { left: 75%; }

/* ---------- Curtain rod and curtains ---------- */
.rod {
  /* how far it reaches past the casing: less on a narrow screen, so its
     ends are still on it */
  --reach: min(var(--curtain) * 0.7, max(0px, (100vw - var(--ww)) / 2 - var(--casing) - 30px));
  position: absolute;
  z-index: 3;
  top: calc(-5px - var(--casing) - 22px);
  left: calc(-5px - var(--casing) - var(--reach));
  right: calc(-5px - var(--casing) - var(--reach));
  height: 9px;
  background: linear-gradient(#8a6038, var(--wood) 70%);
  border: 3px solid var(--ink);
  border-radius: 999px;
}
/* Finials */
.rod::before,
.rod::after {
  content: "";
  position: absolute;
  top: 50%;
  width: 16px;
  height: 16px;
  translate: 0 -50%;
  background: radial-gradient(circle at 35% 30%, #a77748, var(--wood) 70%);
  border: 3px solid var(--ink);
  border-radius: 50%;
}
.rod::before { left: -18px; }
.rod::after { right: -18px; }

/* The curtains as they are without JavaScript: tied back */
.curtain {
  position: absolute;
  z-index: 2;
  top: calc(-5px - var(--casing) - 16px);
  width: var(--curtain);
  height: calc(var(--wh) + var(--casing) * 2 + 18px);
  transform-origin: 50% 0;
}
.curtain--left {
  left: calc(-5px - var(--casing) - var(--curtain) * 0.62);
}
.curtain--right {
  right: calc(-5px - var(--casing) - var(--curtain) * 0.62);
}
.curtain__art {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}
/* (their shadow here, so it doesn't replace the room's light on the art) */
.curtain {
  filter: drop-shadow(3px 4px 0 rgba(35, 31, 32, 0.12));
}
.curtain--right .curtain__art {
  transform: scaleX(-1);
}
.curtain__art path {
  vector-effect: non-scaling-stroke;
  stroke-linejoin: round;
  stroke-linecap: round;
}
.curtain__cloth {
  fill: var(--cloth);
  stroke: var(--ink);
  stroke-width: 4px;
}
.curtain__folds {
  fill: none;
  stroke: var(--cloth-fold);
  stroke-width: 3px;
}
.curtain__shade {
  fill: var(--cloth-fold);
  opacity: 0.42;
  stroke: none;
}
.curtain__light {
  fill: none;
  stroke: var(--cloth-light);
  stroke-width: 2.5px;
}
.curtain__hem {
  fill: none;
  stroke: var(--brass);
  stroke-width: 3px;
}
.curtain__tie {
  fill: var(--potato-gold);
  stroke: var(--ink);
  stroke-width: 3.5px;
}
.curtain__tie-shade {
  fill: none;
  stroke: #d08f22;
  stroke-width: 2px;
}
.curtain__ring {
  fill: var(--brass-light);
  stroke: var(--ink);
  stroke-width: 2.4px;
}
/* where a curtain hangs over the glass, the light comes through it: warm
   gold in the afternoon, cool at dawn, nothing at night */
.curtain__glow {
  fill: rgb(255, 222, 140);
  opacity: calc(0.2 * (1 - var(--night)) * (1 - var(--dim) * 2));
  stroke: none;
}
.curtain__hook {
  fill: var(--brass);
  stroke: var(--ink);
  stroke-width: 3px;
}
.curtain__hanging-ink {
  fill: none;
  stroke: var(--ink);
  stroke-width: 11px;
}
.curtain__hanging {
  fill: none;
  stroke: var(--potato-gold);
  stroke-width: 5.5px;
}
.curtain__edge {
  fill: none;
}
/* window.js draws them to fit the window, in CSS px, hanging from rings
   round the rod, which goes behind the rings */
.js-curtains .rod {
  z-index: 1;
}
.js-curtains .curtain {
  top: 0;
  left: 0;
  right: auto;
  width: auto;
  height: auto;
  will-change: transform;
  pointer-events: none;
}
.js-curtains .curtain--right .curtain__art {
  transform: none;
}
.js-curtains .curtain__art path {
  vector-effect: none;
}
/* Buttons over the cloth and the tiebacks, for pointing and for the keyboard */
.curtain__grab,
.curtain__tie-btn {
  position: absolute;
  margin: 0;
  padding: 0;
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  appearance: none;
  -webkit-appearance: none;
  -webkit-tap-highlight-color: transparent;
  pointer-events: auto;
  cursor: pointer;
  touch-action: none;
}
.curtain__grab {
  cursor: ew-resize;
}
.curtain__grab:focus,
.curtain__tie-btn:focus {
  outline: none;
}
.curtain__grab:focus-visible,
.curtain__tie-btn:focus-visible {
  outline: 4px solid var(--potato-gold);
  outline-offset: 2px;
  border-radius: 6px;
}
/* The hook a tieback hangs on when it's undone */
.holdback {
  position: absolute;
  z-index: 1;
  width: 14px;
  height: 14px;
  margin: -7px 0 0 -7px;
  background: radial-gradient(circle at 35% 30%, var(--brass-light), var(--brass) 70%);
  border: 3px solid var(--ink);
  border-radius: 50%;
}

/* ---------- The lamp on the sill ---------- */
.lamp {
  position: absolute;
  z-index: 5;
  left: calc(var(--casing) * 0.5 + 3%);
  bottom: -1px;
  width: clamp(38px, 5.2%, 66px);
  aspect-ratio: 60 / 90;
  margin: 0;
  padding: 0;
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  appearance: none;
  -webkit-appearance: none;
  -webkit-tap-highlight-color: transparent;
}
.lamp svg {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
}
.lamp path,
.lamp circle {
  stroke: var(--ink);
  stroke-width: 3px;
  stroke-linejoin: round;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}
/* its brass foot and stem, lamp-lit like the rest of the room */
.lamp__body {
  fill: var(--brass);
  filter: brightness(calc(1 - var(--dim) * (1.4 - 0.9 * var(--lamp))));
}
/* the shade: linen, glowing warm when it's on, dim in a dark room when it's off */
.lamp__shade {
  fill: #f3e6cc;
  stroke: none !important;
}
.lamp__lit {
  fill: #ffe2a0;
  stroke: none !important;
  opacity: var(--lamp);
}
.lamp__dark {
  fill: #2a2222;
  stroke: none !important;
  opacity: calc(var(--dim) * (1 - var(--lamp)) * 1.4);
}
.lamp__pleats {
  fill: none;
  stroke: rgba(35, 31, 32, 0.3) !important;
  stroke-width: 1.6px !important;
}
.lamp__rim {
  fill: none;
}
.lamp__spill {
  fill: #fff1c4;
  stroke: none !important;
  opacity: calc(var(--lamp) * 0.9);
}
.lamp__glow {
  position: absolute;
  left: -260%;
  right: -260%;
  top: -160%;
  bottom: -60%;
  pointer-events: none;
  background: radial-gradient(closest-side, rgba(255, 200, 110, 0.55), rgba(255, 200, 110, 0.18) 45%, rgba(255, 200, 110, 0));
  opacity: calc(var(--lamp) * (0.35 + var(--dim) * 1.9));
}
.js-room .lamp:enabled {
  cursor: pointer;
}
.lamp:focus {
  outline: none;
}
.lamp:focus-visible {
  outline: 3px solid var(--potato-gold);
  outline-offset: 3px;
  border-radius: 6px;
}

/* ---------- Sill ---------- */
.sill {
  position: absolute;
  left: calc(-5px - var(--casing) * 2);
  right: calc(-5px - var(--casing) * 2);
  top: 100%;
  height: calc(var(--casing) * 0.8 + 8px);
  /* the afternoon sun comes in across it */
  background:
    linear-gradient(rgba(255, 255, 255, 0.7) 0 2px, transparent 2px),
    linear-gradient(90deg, #fff8e8, #fffdf6 30%, #ffefcc 70%, #fff6e2);
  border: 5px solid var(--ink);
  border-radius: 5px;
  z-index: 4;
  box-shadow: 0 5px 0 rgba(35, 31, 32, 0.1);
}
/* Apron, under the sill */
.sill::after {
  content: "";
  position: absolute;
  top: calc(100% + 5px);
  left: var(--casing);
  right: var(--casing);
  height: calc(var(--casing) * 1.3 + 6px);
  background: linear-gradient(var(--trim) 70%, var(--trim-shade) 70%);
  border: 5px solid var(--ink);
  border-top: 0;
  border-radius: 0 0 4px 4px;
}
.sill__things {
  position: absolute;
  right: calc(var(--casing) * 2 + 5%);
  bottom: calc(100% + 1px);
  width: clamp(130px, 24%, 300px);
  height: auto;
  overflow: visible;
}

/* ---------- Leaves blown in onto the sill (window.js) ---------- */
.blown {
  position: absolute;
  inset: 0;
  z-index: 5;
  pointer-events: none;
}
.blown span {
  position: absolute;
  left: 0;
  top: 0;
  width: var(--leaf);
  height: var(--leaf);
  margin: calc(var(--leaf) / -2) 0 0 calc(var(--leaf) / -2);
  transform: translate(var(--x1), var(--y1)) scale(1, 0.5) rotate(var(--r1));
  animation: w-blow 2.6s cubic-bezier(0.3, 0.1, 0.3, 1);
  transition: opacity 1s ease;
}
.blown span.is-gone {
  opacity: 0;
}
/* a tap brushes one off the sill: it flips up and falls into the room */
.js-room .blown span {
  pointer-events: auto;
  cursor: pointer;
}
.blown span.is-brushed {
  pointer-events: none;
  animation: w-brush 0.9s cubic-bezier(0.4, 0, 0.7, 1) forwards;
}
@keyframes w-brush {
  0% { transform: translate(var(--x1), var(--y1)) scale(1, 0.5) rotate(var(--r1)); opacity: 1; }
  30% { transform: translate(calc(var(--x1) + var(--bx) * 0.4), calc(var(--y1) - 34px)) scale(1, 0.9) rotate(calc(var(--r1) + 100deg)); }
  100% { transform: translate(calc(var(--x1) + var(--bx)), calc(var(--y1) + 150px)) scale(1, 1) rotate(calc(var(--r1) + 280deg)); opacity: 0; }
}
.blown svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
}
@keyframes w-blow {
  0% { transform: translate(var(--x0), var(--y0)) scale(0.4, 0.4) rotate(0deg); opacity: 0; }
  12% { opacity: 1; }
  55% { transform: translate(var(--xm), var(--ym)) scale(1.3, 1.1) rotate(var(--rm)); }
  80% { transform: translate(var(--x1), calc(var(--y1) - 14px)) scale(1.05, 0.8) rotate(var(--r1)); }
  100% { transform: translate(var(--x1), var(--y1)) scale(1, 0.5) rotate(var(--r1)); opacity: 1; }
}

/* ---------- Controls ---------- */
.ui {
  position: absolute;
  z-index: 5;
  left: 0;
  right: 0;
  top: calc(var(--win-top) + var(--wh) + var(--below) + 10px);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  transition: opacity 0.4s ease;
}
.ui__slot {
  position: relative;
  display: grid;
  place-items: center;
  min-height: 46px;
}
.ui__slot > * {
  grid-area: 1 / 1;
}
.hint {
  margin: 0;
  pointer-events: none;
  font-family: var(--font-script);
  font-size: 1.2rem;
  line-height: 1.4;
  text-align: center;
  color: var(--ink-soft);
  opacity: 0;
  transition: opacity 1.2s ease;
}
.is-hinting .hint {
  opacity: 1;
}
.hint,
.leave {
  text-shadow: 0 0 0.3em rgba(251, 243, 225, 0.9), 0 0 0.1em rgba(251, 243, 225, 0.9);
}
.is-dimmed .hint {
  color: var(--ink);
}
/* in a dark room (the lamp off, after dark) */
.is-unlit .hint,
.is-unlit .leave {
  color: #f1ead9;
  text-shadow: 0 0 0.3em rgba(20, 26, 50, 0.9), 0 0 0.1em rgba(20, 26, 50, 0.9);
}
.leave {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1rem;
  white-space: nowrap;
  color: var(--ink);
}
.pill {
  padding: 0.4em 1.1em;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1rem;
  line-height: 1.2;
  white-space: nowrap;
  color: var(--ink);
  background: var(--white);
  border: var(--stroke) solid var(--ink);
  border-radius: var(--radius-pill);
  box-shadow: var(--shadow-sm);
  cursor: pointer;
  transition: transform 0.18s var(--ease-out), box-shadow 0.18s var(--ease-out), opacity 0.4s ease;
}
.pill:hover {
  transform: translate(-1px, -1px);
  box-shadow: 5px 5px 0 var(--ink);
}
.pill:active {
  transform: translate(3px, 3px);
  box-shadow: 1px 1px 0 var(--ink);
}
.pill[hidden] {
  display: none;
}
.pill--go {
  background: var(--logo-green);
  animation: w-pop 0.5s var(--ease-spring);
}
@keyframes w-pop {
  from { transform: scale(0.6); opacity: 0; }
}
/* With your head out: the way back in, top left, clear of anything a browser
   (or a preview's toolbar) puts along the bottom of the window */
.back {
  position: absolute;
  z-index: 6;
  top: max(14px, env(safe-area-inset-top));
  left: max(14px, env(safe-area-inset-left));
}
.sound {
  position: absolute;
  z-index: 6;
  bottom: max(14px, env(safe-area-inset-bottom));
  right: max(14px, env(safe-area-inset-right));
  padding: 0.3em 0.9em;
  font-size: 0.95rem;
}
/* (on a tall screen there's room above the window, and not beside the button
   that brings your head back in) */
@media (max-aspect-ratio: 1/1) {
  .sound {
    top: max(12px, env(safe-area-inset-top));
    bottom: auto;
  }
}
.sound[aria-pressed="false"] {
  background: #d9cfb8;
}
/* leaning out the first time: how to look about (under the way back in) */
.look-hint {
  position: absolute;
  z-index: 6;
  left: 0;
  right: 0;
  top: calc(max(14px, env(safe-area-inset-top)) + 58px);
  padding: 0 16px;
  margin: 0;
  pointer-events: none;
  font-family: var(--font-script);
  font-size: 1.3rem;
  text-align: center;
  color: var(--white);
  text-shadow: 0 1px 2px rgba(35, 31, 32, 0.7), 0 0 12px rgba(35, 31, 32, 0.45);
  opacity: 0;
  transition: opacity 1s ease;
}
.is-out.is-look-hinting .look-hint {
  opacity: 1;
}
.is-leaning .ui,
.is-out .ui {
  opacity: 0;
  pointer-events: none;
}
/* (and out of reach of the keyboard, with your head out) */
.is-out .ui {
  visibility: hidden;
}

/* ---------- Things that move ---------- */
.sill .steam {
  transform-box: fill-box;
  transform-origin: 50% 100%;
  transition: transform 1.5s ease;
}
.is-open .sill .steam {
  transform: skewX(-24deg);
}
.sill .steam path {
  opacity: 0;
  animation: w-steam 3.2s ease-out infinite;
}
.sill .steam path:nth-child(2) { animation-delay: -1.1s; }
.sill .steam path:nth-child(3) { animation-delay: -2.2s; }
@keyframes w-steam {
  0% { opacity: 0; transform: translateY(6px); }
  30% { opacity: 0.9; }
  100% { opacity: 0; transform: translateY(-12px); }
}
/* the window jolts when it's tugged while locked */
.sash.is-stuck {
  animation: w-stuck 0.3s ease-out;
}
@keyframes w-stuck {
  30% { translate: 0 -3px; }
  60% { translate: 0 1px; }
}

@media (prefers-reduced-motion: reduce) {
  .window-room *,
  .window-room *::before,
  .window-room *::after {
    animation-play-state: paused !important;
  }
  .lock__cam,
  .outside canvas {
    transition-duration: 0.01s;
  }
}
