/* ===========================================================================
   THE LIGHT SYSTEM — tokens and resting states.

   Issue #30. The site's whole visual language lived in one token block
   (`--ground: #14101f` on :root) and every page inherited the dark. There was
   exactly one light scene on the entire site, `.band.turnlight` on the home
   page, and it proved the palette works. It was never extended.

   THE RULE THIS FILE ENCODES: a scene owns its light. Tokens are named for
   MATERIAL and ROLE, never for colour, so a scene can be re-lit by changing
   one class and nothing needs renaming.

   THE SECOND RULE: every motion pattern's RESTING STATE is written here, in
   CSS, and it is the correct finished frame. motion.js only moves you to it.
   That is what makes "JavaScript never arrived" and "this visitor asked for
   reduced motion" the same free outcome instead of two afterthoughts.
   =========================================================================== */

/* --- the scene ---------------------------------------------------------- */

.scene {
  /* Pearl is the default ground. Light, not white — a true #fff page has no
     air in it and every shadow on it looks like dirt. */
  --ground: #f6f2ea;
  --ground-2: #ebe5d9;
  --ink: #17121f;
  --ink-2: rgba(23, 18, 31, .72);
  --ink-3: rgba(23, 18, 31, .48);
  --edge: rgba(23, 18, 31, .14);
  --edge-lit: rgba(255, 255, 255, .85);
  --glass: rgba(255, 255, 255, .42);
  --glass-blur: 14px;
  --steel: linear-gradient(115deg, #c9ccd1, #eef0f2 28%, #b9bdc4 52%, #e7e9ec 74%, #c2c6cc);
  --steel-lit: rgba(255, 255, 255, .92);
  --accent: #6f5fd8;
  --contact: 0 18px 40px -22px rgba(23, 18, 31, .45);
  --light-from: 155deg;

  position: relative;
  background: var(--ground);
  color: var(--ink);
}

/* The four families, each with its own temperature. The violet that used to
   wash the whole site is now ONE family's colour. */
.scene--companion { --ground: #f7f1e8; --ground-2: #efe6d8; --accent: #b8753a; --light-from: 140deg; }
.scene--assistant { --ground: #f2f4f6; --ground-2: #e6eaee; --accent: #3f6fa8; --light-from: 165deg; }
.scene--family    { --ground: #f8f3ee; --ground-2: #f0e8e0; --accent: #a8604f; --light-from: 130deg; }

/* THE CONTRAST SCENE. One or two per page, never the shell. It inverts the
   roles rather than redefining the names, so everything inside keeps working. */
.scene--dark {
  --ground: #14101f;
  --ground-2: #1c1729;
  --ink: #f2eee5;
  --ink-2: rgba(242, 238, 229, .74);
  --ink-3: rgba(242, 238, 229, .5);
  --edge: rgba(242, 238, 229, .16);
  --edge-lit: rgba(255, 255, 255, .3);
  --glass: rgba(255, 255, 255, .06);
  --steel: linear-gradient(115deg, #3a3f47, #585e68 28%, #32363d 52%, #4d535c 74%, #363a41);
  --steel-lit: rgba(255, 255, 255, .45);
  --contact: 0 22px 52px -26px rgba(0, 0, 0, .8);
}

/* --- the materials ------------------------------------------------------ */

/* GLASS IS A MATERIAL, NOT rgba() PLUS A BLUR.
   Four properties, and a pane needs at least three to be believable: an edge
   (it has thickness), refraction (what is behind it is displaced, not merely
   dimmed), contact (a shadow where it meets its ground), and response (it
   picks up nearby colour). A pane with no contact shadow floats and reads as
   pasted on, which is the glassmorphism look #30 prohibits. */
.glass {
  position: relative;
  background: var(--glass);
  backdrop-filter: blur(var(--glass-blur)) saturate(1.25);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(1.25);
  box-shadow:
    inset 0 1px 0 0 var(--edge-lit),          /* the lit edge, top */
    inset 0 -1px 0 0 var(--edge),             /* the shaded edge, bottom */
    var(--contact);                           /* where it meets the ground */
  border: 1px solid var(--edge);
}
/* Glass is for layers content passes BEHIND. If it is not in front of
   something it is a grey box, and this class should not be on it. */
.glass--pane { border-radius: 3px; }

/* STEEL IS TRIM. A frame edge, a control surface, a rule between scenes.
   Never a page background and never a card fill. */
.steel {
  background-image: var(--steel);
  background-size: 200% 100%;
  /* The specular run. --sheen is written by the one rAF writer in motion.js
     from pointer position; at rest it sits where the scene's light is. */
  background-position: var(--sheen, 30%) 0;
}
.steel--rule { height: 1px; border: 0; background-image: var(--steel); }

/* --- resting states: the finished frame, in CSS -------------------------- */

/* Text choreography (pattern 7). At rest the line is simply there. motion.js
   masks and offsets it only after it has bound successfully. */
[data-lines] > .mline,
[data-words] > .mword { display: inline-block; }
.motion-ready [data-lines] > .mline,
.motion-ready [data-words] > .mword { will-change: transform; }
.motion-ready [data-lines] > .mline-mask,
.motion-ready [data-words] > .mword-mask { overflow: hidden; display: inline-block; vertical-align: bottom; }

/* Depth (pattern 3). At rest every layer is at rate 1 — the composition works
   because it was composed, not because it was offset. */
[data-depth] { will-change: auto; }
.motion-ready [data-depth] { will-change: transform; }

/* Pinned scene (pattern 2). At rest every state is stacked and readable, in
   order, which is exactly the reduced-motion and no-JS answer. */
[data-pin-state] { opacity: 1; }
.motion-ready [data-pin-scene] { position: relative; }
.motion-ready [data-pin-scene] [data-pin-state] { position: absolute; inset: 0; opacity: 0; }
.motion-ready [data-pin-scene] [data-pin-state][data-current] { opacity: 1; }

/* Handoff (pattern 10). ONE element, never two. At rest it lives in its
   destination slot, which is where it ends up anyway. */
[data-handoff] { will-change: auto; }
.motion-ready [data-handoff] { will-change: transform; }

/* Masked reveal (pattern 5). At rest the incoming scene is simply visible and
   unmasked — never display:none waiting for a mask, or a screen reader loses
   it entirely. */
.motion-ready [data-mask-from] { clip-path: inset(var(--mask-inset, 0%) round var(--mask-round, 0px)); }

/* Reveal sequence (pattern 13). Progressive means the visual weight arrives in
   order, NOT that content is withheld. Everything is in the DOM, always. */
.motion-ready [data-reveal-sequence] > * { opacity: .999; }

/* --- reduced motion ------------------------------------------------------ */

/* Not shorter animations. None. motion.js also checks this and binds nothing,
   so this block is the belt to its braces — a visitor who toggles the setting
   mid-visit gets the right answer without a reload. */
@media (prefers-reduced-motion: reduce) {
  .scene *,
  .scene *::before,
  .scene *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  .motion-ready [data-pin-scene] [data-pin-state] { position: static; opacity: 1; }
  .motion-ready [data-mask-from] { clip-path: none; }
  .motion-ready [data-lines] > .mline-mask,
  .motion-ready [data-words] > .mword-mask { overflow: visible; }
}

/* --- composition -------------------------------------------------------- */

/* Space is a material. The cheapest way to look expensive is to give one idea
   a whole screen. */
.scene__inner { max-width: var(--wrap, 1280px); margin: 0 auto; padding: clamp(64px, 10vw, 160px) var(--gutter, clamp(20px, 4vw, 56px)); }
.scene__inner--tight { padding-block: clamp(40px, 6vw, 88px); }

/* Measure. Long line length is the fastest way to look amateur; 45–75
   characters is the whole rule. */
.measure { max-width: 62ch; }
.measure--tight { max-width: 46ch; }
.display { font-family: var(--serif); font-weight: 500; line-height: 1.02; letter-spacing: -.015em; }
.display--xl { font-size: clamp(2.8rem, 8vw, 7rem); }
.display--l { font-size: clamp(2.2rem, 5.5vw, 4.4rem); }
.label { font-family: var(--mono); font-size: .7rem; letter-spacing: .11em; text-transform: uppercase; color: var(--ink-3); }

/* Focus is visible on every scene, in that scene's own ink. A focus ring that
   inherits from :root disappears the moment a scene re-lights. */
.scene :focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
