/* ===========================================================================
   404motivation — depth.

   Kinetic Spark's palette and type are untouched. What was missing was
   *material*: every surface in this world was the same flat #121217 rectangle
   with a 1px #26262f line around it, so nineteen rooms read as nineteen
   identical boxes and nothing on the page had a front or a back.

   This sheet gives the world three things it did not have.

   1. A material.  Surfaces are now glass over the living field rather than
      paint on top of it — a translucent gradient that is lighter where light
      would fall, a hairline that catches that light at the top edge and loses
      it at the bottom, and a shadow in three parts (contact, mid, far) instead
      of one. The WebGL substrate already moves behind the page; letting it
      through is free light.

   2. Real depth.  The cards are 3D objects, not pictures of them. Each one
      carries its own perspective, its children sit at different translateZ
      distances, and the pointer rotates the whole assembly — so the title
      genuinely moves further than the blurb underneath it. That parallax is
      the part the eye reads as solid. The shadow swings opposite the tilt,
      because the light source does not move when the card does.

   3. A light.  A specular pool follows the pointer across the surface in the
      card's own hue, and the lit edge brightens with it.

   Everything here degrades in the right order:
     · no JavaScript   — no tilt, no sheen; the material and the shadows stay,
                         and they are what carry the design.
     · reduced motion  — the same, deliberately. No rotation, no lift, no
                         stagger. A designed static version, not a stripped one.
     · coarse pointer  — no tilt (there is no pointer to track); tap gets the
                         lift and the lit edge instead.

   Loaded last, after spark.css / rooms.css / studio.css, so it can raise the
   floor for all three without any of them needing to know about it.
   ======================================================================== */

:root{
  --e-out:cubic-bezier(.16,1,.3,1);
  --e-soft:cubic-bezier(.22,.61,.36,1);

  /* Light comes from above and slightly in front. Every surface below states
     the same two edges, so they all agree about where it is. */
  --edge-lit:inset 0 1px 0 rgba(255,255,255,.075);
  --edge-dark:inset 0 -1px 0 rgba(0,0,0,.5);

  /* Three shadows, not one: the contact line that pins an object to what it
     sits on, the mid that gives it mass, the far that gives it height. A
     single blurred box-shadow is the tell of a flat design. */
  --sh-contact:0 1px 2px rgba(0,0,0,.55);
  --sh-mid:0 10px 28px -14px rgba(0,0,0,.85);
  --sh-far:0 34px 70px -34px rgba(0,0,0,.9);
  --sh-rest:var(--sh-contact),var(--sh-mid),var(--edge-lit),var(--edge-dark);

  /* Hues, in the locked palette's own terms, so the tint system and the
     accent variables cannot drift apart.
       186 = cyan #00f0ff   ·   100 = green #39ff14
        26 = ember #ff7a18  ·   330 = pink  #ff007f          */
  --h:186;
}

/* --------------------------------------------------------------- grain --- */
/* Six percent of monochrome noise over the whole page. It is there for the
   gradients: large soft radial fields on a near-black ground band badly on
   8-bit panels, and dither is the standard fix. It also does what film grain
   does — stops the flat areas reading as empty. Self-contained SVG, no request. */
body::after{
  content:"";position:fixed;inset:0;z-index:2;pointer-events:none;
  opacity:.055;mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size:160px 160px;
}

/* ------------------------------------------------------- section rules --- */
/* The kicker used to sit alone above the heading. A hairline running out of it
   to the right gives the eye the width of the section before it reads a word,
   and costs one pseudo-element. */
.sec-h{display:flex;align-items:center;gap:.9rem}
.sec-h::after{
  content:"";flex:1;height:1px;
  background:linear-gradient(90deg,rgba(255,255,255,.16),rgba(255,255,255,.02) 60%,transparent);
}

/* =========================================================== the material ==
   One surface definition, stated once. Anything that is a raised plane in this
   world uses it: the room cards, the panels, the stage, the mood readout.
   ======================================================================== */
.card,.panel,.stage,.mood-out,.nojs{
  position:relative;
  background:
    /* the light that falls on the top-left of the plane */
    linear-gradient(157deg,rgba(255,255,255,.055),rgba(255,255,255,.012) 38%,transparent 64%),
    /* the plane itself, translucent so the field behind is doing work */
    linear-gradient(157deg,rgba(26,26,36,.80),rgba(11,11,17,.66));
  border:1px solid rgba(255,255,255,.085);
  box-shadow:var(--sh-rest);
}

/* The big surfaces get the blur as well. Nineteen blurred cards is a real
   cost on a laptop GPU for a difference nobody can name, so the cards make do
   with translucency; the four or five large panels earn it. */
.panel,.stage,.mood-out,.today{
  -webkit-backdrop-filter:blur(18px) saturate(135%);
  backdrop-filter:blur(18px) saturate(135%);
}

/* The quiet room stays quiet. It gets the depth and none of the light show —
   that contrast is the reason it is on the page. */
.today{
  box-shadow:var(--sh-contact),var(--sh-far),inset 0 1px 0 rgba(255,255,255,.06);
}

/* ============================================================ the 3D card ==
   The tilt is expressed entirely in custom properties, so JavaScript only ever
   writes numbers and CSS decides what they mean. With no JavaScript every one
   of them keeps its fallback and the card is a well-lit static plane.
   ======================================================================== */
.cards .card{
  --rx:0deg; --ry:0deg; --tz:0px;      /* rotation and lift  */
  --mx:50%;  --my:0%;                   /* the pointer, for the sheen */
  --lit:0;                              /* how lit the edges are, 0..1 */
  --h:186;
  /* Restated here, not on :root. A custom property holding var() resolves
     against the element it is DECLARED on, so --tint on :root would resolve
     once against :root's hue and every card would inherit the same cyan. */
  --tint:hsl(var(--h) 100% 62%);
  border-radius:14px;
  padding:1.55rem;
  transform-style:preserve-3d;
  transform:
    perspective(1000px)
    rotateX(var(--rx)) rotateY(var(--ry))
    translateZ(var(--tz));
  transition:
    transform .55s var(--e-out),
    box-shadow .55s var(--e-out),
    border-color .4s ease;
}

/* The lit edge. A gradient ring, masked to the border, in the card's own hue —
   bright where the light lands, gone by the time it reaches the bottom. It is
   at half strength at rest and full under the pointer, which is what makes a
   grid of them feel lit rather than outlined. */
.cards .card::before{
  content:"";position:absolute;inset:0;border-radius:inherit;padding:1px;
  background:linear-gradient(
    157deg,
    hsl(var(--h) 100% 72% / .55),
    hsl(var(--h) 90% 60% / .10) 34%,
    transparent 58%,
    hsl(var(--h) 100% 58% / .16));
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;
          mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
          mask-composite:exclude;
  opacity:calc(.34 + var(--lit) * .66);
  transition:opacity .45s var(--e-out);
  pointer-events:none;
}

/* The specular pool. It tracks the pointer and it is tinted, so moving across
   a row of cards reads as one light passing over different materials. */
.cards .card::after{
  content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;
  background:
    radial-gradient(420px circle at var(--mx) var(--my),
      hsl(var(--h) 100% 70% / .16),
      hsl(var(--h) 100% 62% / .05) 32%,
      transparent 62%);
  opacity:var(--lit);
  transition:opacity .45s var(--e-out);
}

/* The card is a link end to end. It also has to be the flex column, or the
   blurb cannot be pushed to the foot of a stretched card — which is why the
   grid had a hole under every short description. */
.cards .card > a{
  position:relative;
  display:flex;flex-direction:column;height:100%;
  text-decoration:none;color:inherit;
  transform-style:preserve-3d;
}

/* ------------------------------------------------------------ the layers --
   The part that makes it three-dimensional rather than tilted. Three planes at
   three distances: on rotation the title travels further across the screen
   than the blurb below it, and the eye reads the difference as thickness. */
.cards .card .k{transform:translateZ(26px)}
.cards .card h3{transform:translateZ(46px)}
.cards .card p{transform:translateZ(14px)}
.cards .card .k,.cards .card h3,.cards .card p{
  transition:transform .55s var(--e-out);
  transform-style:preserve-3d;
}

/* The spine. A hairline of the card's hue down the leading edge, dark at rest,
   lit when the card is. One mark, no new element. */
.cards .card > a::before{
  content:"";position:absolute;left:-.65rem;top:.15rem;bottom:.15rem;width:2px;
  border-radius:2px;
  background:linear-gradient(180deg,var(--tint),hsl(var(--h) 100% 50% / 0));
  opacity:calc(.22 + var(--lit) * .78);
  transform:translateZ(20px);
  transition:opacity .45s var(--e-out);
}

/* Hover and keyboard focus are the same state: lift, light, and a shadow that
   grows because the object is further from the surface it sits on. */
.cards .card:hover,.cards .card:focus-within{
  --tz:26px; --lit:1;
  border-color:hsl(var(--h) 100% 70% / .30);
  box-shadow:
    var(--sh-contact),
    var(--sh-far),
    var(--edge-lit),
    var(--edge-dark),
    0 0 44px -14px hsl(var(--h) 100% 55% / .45);
}

/* --------------------------------------------------------- the hue cycle --
   The old sheet coloured the first four cards and left the other fifteen grey,
   because it named them one at a time. Four hues on a cycle covers nineteen
   rooms, or any number of them, and cannot fall out of step with the content. */
.cards .card:nth-child(4n+1){--h:186;--tint:hsl(186 100% 62%)}
.cards .card:nth-child(4n+2){--h:100;--tint:hsl(100 100% 55%)}
.cards .card:nth-child(4n+3){--h:26;--tint:hsl(26 100% 58%)}
.cards .card:nth-child(4n+4){--h:330;--tint:hsl(330 100% 62%)}
.cards .card .k{color:var(--tint)}
.cards .card h3{
  font-size:1.12rem;
  transition:transform .55s var(--e-out),color .3s ease;
}
.cards .card:hover h3,.cards .card:focus-within h3{color:#fff}

/* The blurb sat at the foot of a stretched card, which left a band of nothing
   between it and the title. Copy belongs together; the slack belongs at the
   bottom, where the chevron uses it. */
#galleries .card p{margin-top:.15rem;padding-top:0}
.cards .card h3{margin-bottom:.5rem}

/* The chevron. It lives at the far corner, sits proud of the face, and steps
   out when the card is live — the smallest possible statement that the whole
   card is a door. */
#galleries .card > a::after{
  content:"→";
  position:absolute;right:-.35rem;bottom:-.2rem;
  font-family:var(--mono);font-size:.95rem;line-height:1;
  color:var(--tint);opacity:0;transform:translate3d(-6px,0,34px);
  transition:opacity .4s var(--e-out),transform .4s var(--e-out);
}
#galleries .card:hover > a::after,
#galleries .card:focus-within > a::after{opacity:.9;transform:translate3d(0,0,34px)}

/* The entrance. Cards unfold from below the plane rather than sliding up it,
   staggered along the grid — the stagger is what stops nineteen of them
   arriving as one block. --i is set by depth.js; without it they are already
   in place, which is the correct no-JavaScript result. */
html.depth .cards .card{
  opacity:0;
  transform:perspective(1000px) rotateX(11deg) translate3d(0,22px,-70px);
}
html.depth .cards.lit .card{
  opacity:1;
  transform:perspective(1000px) rotateX(0) translate3d(0,0,0);
  transition:opacity .7s var(--e-out),transform .8s var(--e-out);
  transition-delay:calc(var(--i,0) * 45ms);
}

/* ===================================================== the room pages =====
   .exhibit and .room-card already carry the glass from rooms.css. What they
   were missing is the third dimension, so they get the engine and keep their
   own surface.
   ======================================================================== */
.exhibit,.room-card{
  --rx:0deg;--ry:0deg;--tz:0px;--mx:50%;--my:0%;--lit:0;--h:186;
  --tint:hsl(var(--h) 100% 62%);
  position:relative;
  transform-style:preserve-3d;
  transform:perspective(1100px) rotateX(var(--rx)) rotateY(var(--ry)) translateZ(var(--tz));
  transition:transform .55s var(--e-out),box-shadow .55s var(--e-out),border-color .4s ease;
}
.exhibit::after,.room-card::after{
  content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;
  background:radial-gradient(460px circle at var(--mx) var(--my),
    hsl(var(--h) 100% 70% / .13),transparent 60%);
  opacity:var(--lit);transition:opacity .45s var(--e-out);
}
.exhibit:hover,.exhibit:focus-within,.room-card:hover,.room-card:focus-within{
  --tz:22px;--lit:1;transform:perspective(1100px) rotateX(var(--rx)) rotateY(var(--ry)) translateZ(var(--tz));
}
.exhibit blockquote,.exhibit cite{transform:translateZ(24px);transform-style:preserve-3d}
.exhibit .provenance{transform:translateZ(10px)}
.room-card h3{transform:translateZ(30px)}
.room-card p{transform:translateZ(12px)}

/* The exhibits do NOT cycle hue. The lobby is a contents page and colour is
   how it separates nineteen rooms; a room is one view, and the design system's
   first principle is one source of heat in it. So the shelf stays cold and lit
   and the ember keeps its single appearance. */

/* The label sat at the foot of a stretched figure, so a short quotation left a
   hundred-pixel hole between the line and whoever said it. The words belong
   together. The slack goes under the button, where it reads as margin. */
.exhibit figcaption{margin-top:0}
.exhibit .exhibit-actions{margin-top:auto;padding-top:.6rem}

/* The room plate. A white mat is right on a white wall and wrong on this one:
   it was the only pure-white rectangle in the world. Dark frame, real shadow,
   and the print sits inside it rather than being it. */
.room-plate{
  background:linear-gradient(157deg,#14141c,#0a0a10);
  border:1px solid rgba(255,255,255,.09);
  border-radius:14px;padding:10px;margin-inline:0;
  box-shadow:var(--sh-contact),var(--sh-far),var(--edge-lit);
}
.room-plate img{display:block;width:100%;height:auto;border-radius:8px;box-shadow:0 2px 10px rgba(0,0,0,.6)}
.room-plate figcaption{padding-top:.7rem}

/* The room studio's fields came from the white-cube sheet and stayed white —
   two blank paper rectangles in the middle of the void. */
.studio input[type="text"],.studio input[type="search"],.studio textarea,.studio select,
.fieldset input,.fieldset textarea,.fieldset select,.ctrl input,.ctrl select,.ctrl textarea{
  background:rgba(255,255,255,.045);
  color:var(--text-white,#fff);
  border:1px solid rgba(255,255,255,.12);
  border-radius:5px;
  box-shadow:inset 0 1px 2px rgba(0,0,0,.5);
}
.studio input::placeholder,.studio textarea::placeholder,
.fieldset input::placeholder,.fieldset textarea::placeholder{color:#6a6a7a}
.studio select option{background:#12121a;color:#fff}

/* ========================================================== the controls ==
   Buttons were flat fills with a 2px radius. A control that is meant to be
   pressed should look like it stands off the page and then does not.
   ======================================================================== */
.btn,button.btn,a.btn{
  position:relative;border-radius:4px;
  background:linear-gradient(180deg,#6ff9ff,#00d9ec 55%,#00bcd0);
  color:#031318;border:1px solid rgba(255,255,255,.28);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.55),
    inset 0 -1px 0 rgba(0,0,0,.22),
    0 2px 4px rgba(0,0,0,.45),
    0 10px 24px -12px rgba(0,240,255,.75);
  transition:transform .18s var(--e-out),box-shadow .25s var(--e-out),filter .2s;
}
.btn:hover,.btn:focus-visible{
  transform:translateY(-2px);
  filter:brightness(1.06);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.6),
    inset 0 -1px 0 rgba(0,0,0,.22),
    0 4px 8px rgba(0,0,0,.5),
    0 18px 34px -14px rgba(0,240,255,.85);
}
.btn:active{
  transform:translateY(1px);
  box-shadow:
    inset 0 2px 5px rgba(0,0,0,.35),
    0 1px 2px rgba(0,0,0,.5);
}
.btn.ghost,.btn--ghost{
  background:linear-gradient(180deg,rgba(255,255,255,.075),rgba(255,255,255,.02));
  color:var(--white,#fff);border-color:rgba(255,255,255,.14);
  box-shadow:var(--edge-lit),0 2px 4px rgba(0,0,0,.4),0 10px 22px -14px rgba(0,0,0,.9);
}
.btn.ghost:hover,.btn.ghost:focus-visible,.btn--ghost:hover{
  border-color:rgba(255,255,255,.34);
  background:linear-gradient(180deg,rgba(255,255,255,.12),rgba(255,255,255,.04));
  box-shadow:var(--edge-lit),0 4px 10px rgba(0,0,0,.5),0 16px 30px -16px rgba(0,0,0,.9);
  filter:none;
}

/* Pills — the filter tabs, the mood buttons, the size buttons. Same material
   as the surfaces they sit on, one step brighter. */
.tab,.fmt button,.moods button,.mood-rooms a,.today .acts a{
  border-radius:4px;
  background:linear-gradient(180deg,rgba(255,255,255,.055),rgba(255,255,255,.015));
  box-shadow:var(--edge-lit),0 1px 2px rgba(0,0,0,.35);
  transition:transform .22s var(--e-out),box-shadow .3s,border-color .3s,color .3s,background .3s;
}
.tab:hover,.fmt button:hover,.moods button:hover,.mood-rooms a:hover,.today .acts a:hover{
  transform:translateY(-2px);
  box-shadow:var(--edge-lit),0 6px 14px -6px rgba(0,0,0,.8);
}
.tab[aria-selected="true"],.fmt button[aria-pressed="true"]{
  background:linear-gradient(180deg,#ffffff,#dfe3ea);
  box-shadow:inset 0 1px 0 #fff,0 2px 6px rgba(0,0,0,.5),0 0 22px -8px rgba(255,255,255,.5);
}
.moods button[aria-pressed="true"]{
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.6),
    0 2px 6px rgba(0,0,0,.5),
    0 12px 26px -12px rgba(0,240,255,.7);
}

/* The thumbnails. These are the only place in the world where a grid of tiny
   images has to read as pickable, so the selected one lifts out of the sheet
   rather than only changing its border colour. */
.tmpl button,.pal button,.swatch,.tpl{
  transition:transform .25s var(--e-out),box-shadow .3s var(--e-out),border-color .25s;
  box-shadow:0 1px 2px rgba(0,0,0,.5);
}
.tmpl button:hover,.pal button:hover,.swatch:hover,.tpl:hover{
  transform:translateY(-3px) scale(1.03);
  box-shadow:0 8px 18px -8px rgba(0,0,0,.9);
  z-index:2;
}
.tmpl button[aria-pressed="true"],.pal button[aria-pressed="true"]{
  transform:translateY(-2px);
  box-shadow:
    0 0 0 1px var(--cyan,#00f0ff) inset,
    0 6px 16px -8px rgba(0,240,255,.8),
    0 2px 4px rgba(0,0,0,.6);
}

/* ============================================================== the stage ==
   The poster is the object being made, so it is lit like one: a plane in front
   of the panel with a real shadow under it and a cold rim behind, and it turns
   with the pointer instead of sitting flat against the page.
   ======================================================================== */
.stage{--rx:0deg;--ry:0deg;--mx:50%;--my:50%;perspective:1600px}
.stage #poster,#poster{
  border-radius:8px;
  transform:rotateX(var(--rx)) rotateY(var(--ry));
  transform-style:preserve-3d;
  box-shadow:
    0 2px 4px rgba(0,0,0,.6),
    0 26px 50px -22px rgba(0,0,0,.95),
    0 0 60px -26px rgba(0,240,255,.35);
  transition:transform .5s var(--e-out),box-shadow .5s var(--e-out);
}
.stage:hover #poster{
  box-shadow:
    0 3px 6px rgba(0,0,0,.65),
    0 40px 72px -26px rgba(0,0,0,.95),
    0 0 80px -22px rgba(0,240,255,.5);
}

/* ================================================================ detail ==
   The parts nobody names and everybody notices.
   ======================================================================== */

/* One focus ring, everywhere, visible against the void. */
:where(a,button,input,textarea,select,summary,[tabindex]):focus-visible{
  outline:2px solid var(--cyan,#00f0ff);
  outline-offset:3px;
  border-radius:3px;
}

/* Scrollbars inside panels. The default is a wide grey slab that breaks the
   material the moment a list is long enough to need one. */
.qlist,.bay-scroll,.tmpl--mini,.stage{scrollbar-width:thin;scrollbar-color:rgba(255,255,255,.16) transparent}
.qlist::-webkit-scrollbar,.bay-scroll::-webkit-scrollbar,.tmpl--mini::-webkit-scrollbar,
.stage::-webkit-scrollbar{width:9px}
.qlist::-webkit-scrollbar-track,.bay-scroll::-webkit-scrollbar-track,
.tmpl--mini::-webkit-scrollbar-track,.stage::-webkit-scrollbar-track{background:transparent}
.qlist::-webkit-scrollbar-thumb,.bay-scroll::-webkit-scrollbar-thumb,
.tmpl--mini::-webkit-scrollbar-thumb,.stage::-webkit-scrollbar-thumb{
  background:linear-gradient(180deg,rgba(255,255,255,.22),rgba(255,255,255,.09));
  border:3px solid transparent;background-clip:padding-box;border-radius:9px;
}
.qlist::-webkit-scrollbar-thumb:hover,.bay-scroll::-webkit-scrollbar-thumb:hover{
  background:linear-gradient(180deg,rgba(0,240,255,.5),rgba(0,240,255,.2));
  background-clip:padding-box;
}

/* Rows in the line list. The old hover was a flat fill edge to edge; a lit
   leading edge and a small step to the right reads as selecting a card out of
   a stack, which is what it is. */
.qlist li{position:relative}
.qlist button{
  position:relative;border-radius:4px;
  transition:background .25s,transform .25s var(--e-out),padding-left .25s var(--e-out);
}
.qlist button::before{
  content:"";position:absolute;left:0;top:6px;bottom:6px;width:2px;border-radius:2px;
  background:linear-gradient(180deg,var(--cyan,#00f0ff),rgba(0,240,255,0));
  opacity:0;transition:opacity .25s;
}
.qlist button:hover,.qlist button:focus-visible{
  background:linear-gradient(90deg,rgba(0,240,255,.075),rgba(255,255,255,.02) 45%,transparent);
  padding-left:.85rem;
}
.qlist button:hover::before,.qlist button:focus-visible::before{opacity:1}
.qlist button[aria-current="true"]{background:linear-gradient(90deg,rgba(0,240,255,.12),transparent)}
.qlist button[aria-current="true"]::before{opacity:1}

/* The display line. The gradient word was flat against a black ground; a bloom
   underneath gives it the light it is supposed to be emitting. */
h1.kinetic .grad{
  position:relative;
  filter:drop-shadow(0 0 26px rgba(0,240,255,.20)) drop-shadow(0 0 60px rgba(255,122,24,.14));
}

/* The four readouts under the hero. Each number now carries its own glow at
   the same hue as its ink, which is the difference between a figure printed on
   the page and a figure lit on a panel. */
.stat:nth-child(1) b{text-shadow:0 0 26px rgba(0,240,255,.45)}
.stat:nth-child(2) b{text-shadow:0 0 26px rgba(57,255,20,.35)}
.stat:nth-child(3) b{text-shadow:0 0 26px rgba(255,122,24,.45)}
.stat:nth-child(4) b{text-shadow:0 0 26px rgba(255,0,127,.40)}

/* The wordmark's dot is the one thing on the page that is always the same, so
   it is the right place for the only pulse. */
.wordmark i,.mark i{
  display:inline-block;
  animation:markpulse 4.5s var(--e-soft) infinite;
}
@keyframes markpulse{
  0%,100%{opacity:1;text-shadow:0 0 10px rgba(0,240,255,.6)}
  50%{opacity:.55;text-shadow:0 0 2px rgba(0,240,255,.2)}
}

/* Panels and the studio bays get the same lit top edge as everything else. */
.studio-panel,.bay .card,.fieldset{
  box-shadow:var(--sh-contact),var(--sh-mid),var(--edge-lit),var(--edge-dark);
}

/* ======================================================== the floor rules ==
   Reduced motion gets the material, the shadows, the lit edges and the hues —
   the whole design — and none of the movement. It is a different setting of
   the same page, not a fallback.
   ======================================================================== */
@media (prefers-reduced-motion:reduce){
  html.depth .cards .card,
  html.depth .cards.lit .card{opacity:1;transform:none;transition:none}
  .card,.exhibit,.room-card,.stage #poster,#poster{
    transform:none!important;transition:box-shadow .3s,border-color .3s!important;
  }
  .card:hover,.card:focus-within{--tz:0px}
  .card .k,.card h3,.card p,
  .exhibit blockquote,.exhibit cite,.exhibit .provenance,
  .room-card h3,.room-card p,.card > a::before,#galleries .card > a::after{transform:none}
  .btn:hover,.tab:hover,.moods button:hover,.tmpl button:hover,.pal button:hover,
  .fmt button:hover,.mood-rooms a:hover,.today .acts a:hover{transform:none}
  .wordmark i,.mark i{animation:none}
  .qlist button:hover{padding-left:.4rem}
}

/* A pointer that cannot hover has nothing to track, so the tilt is not offered
   there. The lift and the lit edge still fire on tap. */
@media (hover:none){
  .card,.exhibit,.room-card{transform:none}
  .card:hover,.card:focus-within,.exhibit:hover,.room-card:hover{transform:translateY(-3px)}
}

/* Small screens: the substrate is off there by design, so the surfaces stop
   being glass and become solid — translucency over nothing is just grey. */
@media (max-width:760px){
  .card,.panel,.stage,.mood-out,.nojs{
    background:linear-gradient(157deg,rgba(255,255,255,.05),transparent 42%),
               linear-gradient(157deg,#16161e,#0c0c12);
  }
  .panel,.stage,.mood-out,.today{-webkit-backdrop-filter:none;backdrop-filter:none}
  body::after{opacity:.04}
}


/* ============================================================== the moods ==
   Every mood in the data already names a palette — the press retints itself
   when one is chosen. The chips now carry the same hue, so the choice is
   visible before it is made and the page's colour change is not a surprise.
   depth.js reads the hue off window.MOODS; without it they are all cyan,
   which is what they were.
   ======================================================================== */
.moods button{
  --h:186;--tint:hsl(var(--h) 100% 62%);
  position:relative;overflow:hidden;
  padding:.85em 1.25em;
  border-color:rgba(255,255,255,.10);
}
.moods button::before{
  content:"";position:absolute;left:0;top:0;bottom:0;width:3px;
  background:linear-gradient(180deg,var(--tint),hsl(var(--h) 100% 50% / .1));
  opacity:.5;transition:opacity .3s,width .3s var(--e-out);
}
.moods button:hover::before,.moods button:focus-visible::before{opacity:1;width:4px}
.moods button:hover,.moods button:focus-visible{
  border-color:hsl(var(--h) 100% 65% / .38);
  color:#fff;
  box-shadow:var(--edge-lit),0 8px 20px -10px hsl(var(--h) 100% 50% / .55);
}
.moods button[aria-pressed="true"]{
  background:linear-gradient(135deg,var(--tint),hsl(var(--h) 80% 72%));
  color:#04141a;border-color:transparent;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.6),
    0 2px 6px rgba(0,0,0,.5),
    0 14px 30px -12px hsl(var(--h) 100% 50% / .7);
}
.moods button[aria-pressed="true"]::before{opacity:0}

/* The readout takes the hue of whatever was chosen, so the answer and the
   question are visibly the same colour. */
.mood-out{border-left-color:var(--tint,var(--cyan))}

/* ================================================================ the hero =
   The headline sits closer to the reader than the paragraph under it, and the
   kicker closer still. Moving each by a different amount under the pointer is
   the cheapest honest parallax there is: no rotation, so nothing blurs, and
   text stays exactly as crisp as it was.
   ======================================================================== */
.hero{--px:0;--py:0}
.hero .eyebrow{transform:translate3d(calc(var(--px) * -13px),calc(var(--py) * -7px),0)}
.hero h1.kinetic{transform:translate3d(calc(var(--px) * -9px),calc(var(--py) * -5px),0)}
.hero .lede{transform:translate3d(calc(var(--px) * -5px),calc(var(--py) * -3px),0)}
.hero .cta-row{transform:translate3d(calc(var(--px) * -3px),calc(var(--py) * -2px),0)}
.hero .eyebrow,.hero h1.kinetic,.hero .lede,.hero .cta-row{
  transition:transform .9s var(--e-out);will-change:transform;
}

/* The nav's rule is the first line on the page. It gets a light in the middle
   rather than being a flat grey border edge to edge. */
.nav{position:relative;border-bottom-color:transparent}
.nav::after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:1px;
  background:linear-gradient(90deg,
    rgba(255,255,255,.03),rgba(0,240,255,.28) 22%,rgba(255,122,24,.16) 62%,rgba(255,255,255,.03));
}

@media (prefers-reduced-motion:reduce){
  .hero .eyebrow,.hero h1.kinetic,.hero .lede,.hero .cta-row{transform:none!important}
  .moods button:hover::before{width:3px}
}

/* ============================================== the white-cube leftovers ===
   museum.css is the 404 Quotes sheet and its ground is gallery white, so a
   handful of its components name #FBFBFC literally rather than through a
   token. rooms.css repointed the tokens and those literals stayed behind — a
   white caption bar under the room plate, white placards, white doors. They
   are only wrong here, so they are corrected here, and the museum's own pages
   are not touched by any of it.
   ======================================================================== */
.room-plate figcaption,.placard,.door,.fieldset,.hit a,.studio-panel > .fieldset{
  background:
    linear-gradient(157deg,rgba(255,255,255,.05),rgba(255,255,255,.01) 40%,transparent 66%),
    linear-gradient(157deg,rgba(24,24,33,.82),rgba(11,11,17,.68));
  border-color:rgba(255,255,255,.09);
  color:var(--text-gray,#888899);
}
.room-plate figcaption{border-top:1px solid rgba(255,255,255,.08);border-radius:0 0 8px 8px}
.placard strong,.door h3,.hit a strong{color:var(--text-white,#fff)}
.desk input[type="search"]{
  background:rgba(255,255,255,.045);color:var(--text-white,#fff);
  border:1px solid rgba(255,255,255,.12);border-radius:6px;
  box-shadow:inset 0 1px 2px rgba(0,0,0,.5);
}
.door{
  border-radius:12px;
  box-shadow:var(--sh-contact),var(--sh-mid),var(--edge-lit);
  transition:transform .4s var(--e-out),box-shadow .4s var(--e-out),border-color .3s;
}
.door:hover,.door:focus-visible{
  transform:translateY(-3px);
  border-color:rgba(0,240,255,.24);
  box-shadow:var(--sh-contact),var(--sh-far),var(--edge-lit),0 0 34px -12px rgba(0,240,255,.4);
}

/* ====================================================== small screens, nav ==
   Measured at 375x812: the nav is one flex row that does not wrap, so "The
   press" and "404meanings" ran off the right edge and body{overflow-x:hidden}
   quietly cut them off. Two links were unreachable on a phone. The wordmark
   takes its own line and the rest wrap under it.
   ======================================================================== */
@media (max-width:760px){
  .nav{flex-wrap:wrap;gap:.55rem 1.05rem;padding:.9rem 0 .8rem}
  .wordmark{flex:1 0 100%;margin-right:0;margin-bottom:.15rem}
  .nav a{font-size:.68rem}
  .nav .up{border-left:0;padding-left:0}
  .topbar{flex-wrap:wrap;gap:.5rem .9rem}
}

/* ============================================================== the footer ==
   The page ended on a row of grey links with a flat border above it. The rule
   now carries the same light as the one under the nav, so the page closes the
   way it opened, and the links read as links.
   ======================================================================== */
footer{position:relative;border-top-color:transparent}
footer::before{
  content:"";position:absolute;left:0;right:0;top:0;height:1px;
  background:linear-gradient(90deg,
    rgba(255,255,255,.03),rgba(0,240,255,.22) 26%,rgba(255,122,24,.14) 66%,rgba(255,255,255,.03));
}
footer .frow a{
  position:relative;padding-bottom:2px;
  transition:color .25s;
}
footer .frow a::after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:1px;
  background:currentColor;opacity:0;transform:scaleX(.3);transform-origin:left;
  transition:opacity .3s var(--e-out),transform .3s var(--e-out);
}
footer .frow a:hover::after,footer .frow a:focus-visible::after{opacity:.55;transform:scaleX(1)}

/* ================================================================ the stats =
   Four readouts on one rule. Each gets a hairline of its own colour above it,
   so they read as four instruments rather than four sentences.
   ======================================================================== */
.stat{position:relative;padding-top:.9rem}
.stat::before{
  content:"";position:absolute;left:0;top:0;width:26px;height:2px;border-radius:2px;
}
.stat:nth-child(1)::before{background:var(--cyan)}
.stat:nth-child(2)::before{background:var(--green)}
.stat:nth-child(3)::before{background:var(--ember)}
.stat:nth-child(4)::before{background:var(--pink)}
.stats{border-top:0;position:relative;padding-top:1.9rem}
.stats::before{
  content:"";position:absolute;left:0;right:0;top:0;height:1px;
  background:linear-gradient(90deg,rgba(255,255,255,.14),rgba(255,255,255,.03) 70%,transparent);
}

/* =========================================================== panel headings =
   Every panel title is a mono label in the dim grey. A lit tick in front of it
   gives the panels a shared mark and tells the eye where each one starts.
   ======================================================================== */
.panel > h3,.stage > h3{display:flex;align-items:center;gap:.6rem}
.panel > h3::before,.stage > h3::before{
  content:"";width:6px;height:6px;border-radius:1px;flex:none;
  background:var(--cyan);box-shadow:0 0 10px rgba(0,240,255,.7);
}

/* On a phone the four readouts wrapped 1 / 2 / 1 because they are a flex row
   of different widths. Two even columns is the only arrangement that does not
   look like an accident. */
@media (max-width:640px){
  .stats{display:grid;grid-template-columns:1fr 1fr;gap:1.4rem 1.2rem}
}

/* One column, one row per card — and grid-auto-rows:1fr then gives every card
   the height of the tallest one in the whole grid. Equal heights are only
   worth having when cards sit side by side. */
@media (max-width:640px){
  #galleries .cards{grid-auto-rows:auto}
}

/* ============================================== one light over the whole grid
   Per-card specular lights the card under the pointer and leaves its
   neighbours dark, which is how a screen behaves and not how a room does. A
   single soft pool over the grid itself lights whatever is near it — the
   hovered card most, the two beside it a little — so nineteen cards read as
   nineteen objects under one lamp rather than nineteen independent widgets.

   The pool is an absolutely positioned pseudo-element, so it is taken out of
   the grid's flow and does not become a twentieth cell. It blends by screen,
   so it only ever adds light, and at five percent it is felt before it is
   seen. Without JavaScript --gx/--gy never change and the whole thing stays
   at opacity 0.
   ======================================================================== */
.cards{position:relative}
.cards::after{
  content:"";position:absolute;inset:-8% -4%;pointer-events:none;z-index:3;
  background:radial-gradient(380px circle at var(--gx,50%) var(--gy,50%),
    rgba(255,255,255,.07),rgba(255,255,255,.02) 34%,transparent 66%);
  mix-blend-mode:screen;
  opacity:0;transition:opacity .6s var(--e-out);
}
html.depth .cards:hover::after{opacity:1}

@media (prefers-reduced-motion:reduce){ .cards::after{display:none} }
@media (hover:none){ .cards::after{display:none} }

/* ======================================================= the header, in two ==
   One row was doing two unrelated jobs: saying where you are, and listing what
   is on the page. They read as one undifferentiated list of eight links, and
   on a phone two of them fell off the end.

   Top tier  — identity, and the doors out of this world.
   Lower tier — this page's own contents.

   The hairline between them belongs to the pair; the lit rule still closes the
   header as a whole.
   ======================================================================== */
.hdr{border-bottom:0}
.hdr-top{
  display:flex;align-items:baseline;gap:1.2rem;
  padding:1.05rem 0 .8rem;
  border-bottom:1px solid rgba(255,255,255,.055);
}
.hdr-say{
  margin:0;font-family:var(--mono);font-size:.68rem;letter-spacing:.16em;
  text-transform:uppercase;color:var(--dim);
  padding-left:1.1rem;border-left:1px solid var(--line);
}
.hdr-out{
  margin-left:auto;display:flex;gap:1.2rem;
  font-family:var(--mono);font-size:.7rem;letter-spacing:.09em;text-transform:uppercase;
}
.hdr-out a{color:var(--dim);text-decoration:none;transition:color .2s}
.hdr-out a:hover,.hdr-out a:focus-visible{color:var(--white)}
.hdr-out .up{color:var(--gray);border-left:1px solid var(--line);padding-left:1.2rem}

.hdr-nav{
  position:relative;display:flex;flex-wrap:wrap;gap:0 1.5rem;
  padding:.7rem 0 .85rem;
  font-family:var(--mono);font-size:.74rem;letter-spacing:.09em;text-transform:uppercase;
}
.hdr-nav a{
  position:relative;color:var(--gray);text-decoration:none;padding:.15rem 0;
  transition:color .2s;
}
.hdr-nav a::after{
  content:"";position:absolute;left:0;right:0;bottom:-.2rem;height:1px;
  background:var(--cyan);box-shadow:0 0 10px rgba(0,240,255,.8);
  opacity:0;transform:scaleX(.2);transform-origin:left;
  transition:opacity .3s var(--e-out),transform .3s var(--e-out);
}
.hdr-nav a:hover,.hdr-nav a:focus-visible{color:var(--white)}
.hdr-nav a:hover::after,.hdr-nav a:focus-visible::after{opacity:1;transform:scaleX(1)}
/* The one link that is a verb rather than a place. */
.hdr-nav a.is-do{color:var(--white)}
.hdr-nav a.is-do::before{
  content:"";display:inline-block;width:5px;height:5px;border-radius:50%;
  background:var(--ember);margin-right:.5rem;vertical-align:middle;
  box-shadow:0 0 9px rgba(255,122,24,.9);
}
/* The lit rule now closes the pair rather than the single row. */
.hdr::after{
  content:"";display:block;height:1px;
  background:linear-gradient(90deg,
    rgba(255,255,255,.03),rgba(0,240,255,.28) 22%,rgba(255,122,24,.16) 62%,rgba(255,255,255,.03));
}

@media (max-width:760px){
  .hdr-top{flex-wrap:wrap;gap:.45rem .9rem;padding:.85rem 0 .65rem}
  .hdr-say{display:none}          /* the title tag already says it */
  .hdr-out{margin-left:0;flex:1 0 100%;gap:.9rem;font-size:.64rem}
  .hdr-out .up{border-left:0;padding-left:0}
  .hdr-nav{gap:.35rem .95rem;font-size:.66rem;padding:.55rem 0 .7rem}
}

/* ================================================================ the bento ==
   Nineteen equal rectangles is a table, not a contents page. It says every
   room is the same size, and they are not: Dreams holds seventeen lines,
   Training holds eight.

   So the tile is the measure. A room's card is as big as the room —

     17 and 16 lines   feature, two columns by two rows, with a line from the
                       room printed on it
     14 and 15         two columns by one
     13 and under      one by one

   — which makes the grid say something true before a word of it is read.

   Dense packing closes the gaps a mixed grid leaves. It changes which cell a
   tile lands in and never the order of the markup, so a keyboard still walks
   the rooms in the order they were arranged in.
   ======================================================================== */
@media (min-width:720px){
  #galleries .cards{
    grid-template-columns:repeat(4,minmax(0,1fr));
    grid-auto-rows:1fr;
    grid-auto-flow:row dense;
    gap:1.05rem;
  }
  #galleries .card--wide{grid-column:span 2}
  #galleries .card--feature{grid-column:span 2;grid-row:span 2}
}
/* Between one column and four, three columns with the big tiles at two. */
@media (min-width:720px) and (max-width:1080px){
  #galleries .cards{grid-template-columns:repeat(3,minmax(0,1fr))}
}

/* A feature tile has room to say more, and is the only place on this page
   where a room shows its own voice rather than a description of it. */
.card--feature h3{font-size:1.75rem;letter-spacing:-.02em;margin-bottom:.7rem}
.card--feature p{font-size:1rem;max-width:34ch}
.card--feature .k{font-size:.68rem}
.card-q{
  margin:auto 0 0;padding:1.1rem 0 0;
  border-top:1px solid rgba(255,255,255,.08);
  font-family:var(--serif);font-size:1.12rem;line-height:1.38;color:#e8e8f2;
  transform:translateZ(30px);max-width:32ch;text-wrap:pretty;
}
.card-q cite{
  display:block;margin-top:.6rem;font-style:normal;
  font-family:var(--mono);font-size:.63rem;letter-spacing:.13em;text-transform:uppercase;
  color:var(--tint);
}
.card-q cite em{display:block;margin-top:.22rem;color:var(--dim);font-style:normal;letter-spacing:.1em}

/* The blurb no longer needs to hold the foot of the card on a feature tile —
   the quotation does that. */
#galleries .card--feature p{margin-top:.15rem}

/* Wide tiles get one step of type, so the three sizes are legible as three
   sizes and not as an accident of the grid. */
.card--wide h3{font-size:1.3rem}
.card--wide p{max-width:44ch}

/* A bigger plane tilts less, or the far corner travels far enough to look
   like it is falling over. */
.cards .card--wide{--tilt-scale:.7}
.cards .card--feature{--tilt-scale:.55}

/* A wide tile is twice the width of a normal one and was carrying the same two
   sentences, so the extra space read as a mistake rather than as emphasis. It
   shows a line from the room now, one step down from a feature's. */
.card-q--sm{
  font-size:1rem;padding-top:.9rem;max-width:42ch;
  transform:translateZ(24px);
}
.card-q--sm cite{margin-top:.5rem;font-size:.6rem}

/* Seven rows rather than eight, and each of them tighter. A bento costs height
   by nature — a mixed grid cannot pack as densely as an even one — so the
   padding and the quotation's leading are pulled in to pay some of it back. */
@media (min-width:720px){
  #galleries .card{padding:1.3rem}
  #galleries .card--feature{padding:1.55rem}
}
.card-q--sm{line-height:1.3;padding-top:.8rem}
.card-q{line-height:1.32}

/* ========================================================== the aurora bands ==
   Seven 1600x640 originals from motivationalquotesinenglish.com, owner-made and
   unused since that site was written. They go on the five tiles in the bento
   that are larger than one cell — the ones with the area to show an image
   rather than a smear — underneath the material, not instead of it.

   Kept at low opacity and blended, because the job is to give the big tiles a
   different substance from the small ones, not to put a picture behind text.
   The hue each tile already carries decides which band it gets.
   ======================================================================== */
#galleries .card[data-art]::before{
  /* the lit edge is still drawn on top of the art */
  z-index:2;
}
#galleries .card[data-art]{
  background:
    linear-gradient(157deg,rgba(255,255,255,.055),rgba(255,255,255,.012) 38%,transparent 64%),
    linear-gradient(157deg,rgba(20,20,28,.86),rgba(9,9,14,.80)),
    var(--art) center/cover no-repeat;
  transition:transform .55s var(--e-out),box-shadow .55s var(--e-out),
             border-color .4s ease,background-size .8s var(--e-out);
}
#galleries .card[data-art="teal"]    {--art:url("art/realm-teal.webp")}
#galleries .card[data-art="jade"]    {--art:url("art/realm-jade.webp")}
#galleries .card[data-art="ember"]   {--art:url("art/realm-ember.webp")}
#galleries .card[data-art="saffron"] {--art:url("art/realm-saffron.webp")}
#galleries .card[data-art="electric"]{--art:url("art/realm-electric.webp")}
#galleries .card[data-art="rose"]    {--art:url("art/realm-rose.webp")}
#galleries .card[data-art="bloom"]   {--art:url("art/realm-bloom.webp")}

/* On hover the veil thins rather than the image moving: the art comes forward,
   the text stays exactly where it was. */
#galleries .card[data-art]:hover,
#galleries .card[data-art]:focus-within{
  background:
    linear-gradient(157deg,rgba(255,255,255,.06),rgba(255,255,255,.015) 38%,transparent 64%),
    linear-gradient(157deg,rgba(18,18,26,.72),rgba(8,8,13,.66)),
    var(--art) center/cover no-repeat;
}

/* The quiet room gets one too, at a quarter of the strength — it is the only
   card on the page that is meant to be calm, and a band at full weight would
   make it the loudest thing on it. */
#today[data-art-section] .today{
  background:
    linear-gradient(180deg,rgba(11,13,26,.93),rgba(8,10,20,.97)),
    url("art/realm-rose.webp") center/cover no-repeat;
}

/* The seamless tile, on the reading pages. It is 1024px square and almost
   black; at three percent it is a paper texture rather than a picture. */
.essay-body::before{
  content:"";position:fixed;inset:0;z-index:-1;pointer-events:none;
  background:url("art/nebula-tile.webp") repeat;
  background-size:520px 520px;opacity:.5;
}

@media (max-width:760px){
  /* A 1600px band behind a 340px card is 23KB spent on something nobody can
     make out. The tiles keep their material and drop the image. */
  #galleries .card[data-art],
  #galleries .card[data-art]:hover{
    background:linear-gradient(157deg,rgba(255,255,255,.05),transparent 42%),
               linear-gradient(157deg,#16161e,#0c0c12);
  }
  .essay-body::before{display:none}
}
