/* ============================================================================
   Stinson CRM -- Daylight: the live wallpaper, and the sleep screen
   ----------------------------------------------------------------------------
   Two surfaces over one renderer (crm/js/daylight.js), mounted by
   crm/js/daylight_boot.js.

   1. THE WALLPAPER reuses the picture wallpaper's whole machinery. When it is
      on, sas_theme.js sets `data-sas-calbg="1"` exactly as a photograph does,
      so every glass rule already written for the wallpaper -- the calendar's
      toolbar capsules, the Board's hero, chat's log pane, the Flights rails --
      fires unchanged, at the densities each of those was solved for. It also
      sets `data-sas-daylight="1"`, which is what this file keys off, and which
      is the ONLY new attribute. If you are hunting a wallpaper bug, check both.

      The scene mounts as a real element rather than as `--cal-bg-image`,
      because a canvas cannot be a background-image. It sits at z-index -2, one
      layer BELOW the `body::before` those four pages already declare, so the
      order does not depend on where in <body> the element is appended. The
      picture layer is blanked in the same rule, so the two can never stack.

      THE SCRIM IS NOT DUPLICATED. `body::after` still carries it, still at the
      strength slider's alpha, in the theme's own `--body-bg`. Daylight paints
      under exactly the same veil a photograph does, which is what keeps the
      contrast arithmetic in all four page stylesheets valid.

   2. THE SLEEP SCREEN is a full-viewport overlay on <body>. It is a
      screensaver and NOT a lock: no password, no barrier, and any input at all
      dismisses it. That is deliberate on a system carrying crew-safety data --
      see the exclusion list in daylight_boot.js for the pages it must never
      cover at all.

   Bump ASSET_VERSION in core/admin_site.py after editing this file.
   ========================================================================= */

/* ══════════════════════════════════════════════════════════════════════
   The scene itself -- shared by both surfaces
   ----------------------------------------------------------------------
   The stage is a fixed 3:2 box scaled to cover its host and centred; its
   width/height are written by daylight.js. Everything here assumes that,
   because the sky mask has to stay in register with the ridge in the
   photograph: stretching either one puts the skyline out of alignment with
   the mask it is cut by, and the sun then sets through solid rock.
   ══════════════════════════════════════════════════════════════════════ */
.sas-dl-stage {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  isolation: isolate;
  pointer-events: none;
  background: #05070a;
}
.sas-dl-stage > * {
  position: absolute;
  inset: 0;
  display: block;
}
.sas-dl-ph {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: brightness(var(--ph-b, 1)) saturate(var(--ph-s, 1)) contrast(var(--ph-c, 1));
}
/* Ground light. Multiply, so the dark forest stays dark and the mid-tone rock
   takes the colour -- which is how light actually falls off. */
.sas-dl-land {
  mix-blend-mode: multiply;
  background: var(--c-land, #fff);
}
/* The whole sky -- gradient, stars, Milky Way, meteors, moon, sun -- is one
   canvas, masked to the sky region so the ridge occludes all of it. The
   mask-image URL is set inline per instance, because it comes from
   {% static %} and this stylesheet cannot know it. */
.sas-dl-sky {
  width: 100%;
  height: 100%;
  -webkit-mask-size: 100% 100%;
  mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
}
/* Moonlight and low sun catching the snow. Land highlights only -- no
   luminance cut separates snow from overcast sky, so the sky was excluded by
   mask at build time. */
.sas-dl-spec {
  background-position: center;
  background-size: 100% 100%;
  background-repeat: no-repeat;
  mix-blend-mode: screen;
  opacity: var(--spec-a, 0);
}
.sas-dl-warm {
  background: radial-gradient(72% 62% at var(--sun-x, 50%) var(--sun-y, 100%),
    var(--c-warm, transparent) 0%, transparent 66%);
  mix-blend-mode: soft-light;
  opacity: var(--warm-a, 0);
}
.sas-dl-vig {
  background: radial-gradient(120% 96% at 50% 44%, transparent 42%, #000 128%);
  opacity: var(--vig-a, 0.12);
}

/* ══════════════════════════════════════════════════════════════════════
   1. Wallpaper
   ══════════════════════════════════════════════════════════════════════ */

/* The layer the scene mounts into. Bleeds past the viewport by twice the blur
   radius for the same reason `body::before` does: a blurred box samples
   nothing outside itself, so a flush layer fades to transparent at all four
   edges and the scrim reads as a bright border. */
.sas-dl-bg {
  position: fixed;
  inset: calc(-2 * var(--cal-bg-blur, 0px) - 4px);
  z-index: -2;
  overflow: hidden;
  pointer-events: none;
  /* The scene is a leaf as far as the page is concerned -- it has no bearing
     on anything's layout and paints nowhere else. Saying so keeps a redraw
     off the critical path of a page that may have a year-wide gantt or ten
     Console cards in it. */
  contain: layout paint;
  filter: blur(var(--cal-bg-blur, 0px));
  /* Mounted after the body is parsed, so it arrives a beat after the theme.
     A short fade makes that read as the page settling rather than a flash. */
  animation: sas-dl-in 320ms ease-out both;
}

/* Blank the picture layer. Specificity, not order: this file loads in
   base_site.html's extrastyle and the four page stylesheets load after it, so
   file order cannot win. `html[data-sas-calbg][data-sas-daylight] body::before`
   is (0,2,2) against their (0,1,2), which decides it wherever they sit. The
   body-class list is deliberately restated rather than using a bare `body`:
   these four are the only pages that declare the pseudo-elements at all. */
html[data-sas-calbg="1"][data-sas-daylight="1"] body.sas-calendar-page::before,
html[data-sas-calbg="1"][data-sas-daylight="1"] body.sas-board-page::before,
html[data-sas-calbg="1"][data-sas-daylight="1"] body.sas-chat-page::before,
html[data-sas-calbg="1"][data-sas-daylight="1"] body.sas-flights-page::before {
  background-image: none;
  animation: none;
}

/* THE SCRIM BACKS OFF AT NIGHT. --sas-dl-scrim-k is published on <html> by
   the renderer: 1 while the sun is up, ~0.34 at full night, smoothly between.

   The scrim exists to keep the interface legible over a BRIGHT photograph. At
   night the scene is already darker than the page colour it is being veiled
   with, so the veil protects nothing and only crushes what is left -- measured,
   a solar-midnight sky composites to rgb(17,20,34) against a page of
   rgb(16,16,20), which is the "black screen". Daytime is untouched: k is 1
   there and the full strength the sliders were solved against still applies.

   It is `opacity` on the scrim layer, not a recomputed colour, because
   body::after carries nothing but that flat fill -- there is no text in it to
   fade and no other property to disturb. */
html[data-sas-calbg="1"][data-sas-daylight="1"] body.sas-calendar-page::after,
html[data-sas-calbg="1"][data-sas-daylight="1"] body.sas-board-page::after,
html[data-sas-calbg="1"][data-sas-daylight="1"] body.sas-chat-page::after,
html[data-sas-calbg="1"][data-sas-daylight="1"] body.sas-flights-page::after {
  opacity: var(--sas-dl-scrim-k, 1);
}

/* ══════════════════════════════════════════════════════════════════════
   The theme cross-fades with the sky
   ----------------------------------------------------------------------
   `.sas-dl-fade` is put on <html> by sas_theme.js immediately BEFORE it
   writes the new theme attributes, and taken off once the sweep has landed.
   The order matters: a CSS transition only starts if transition-property is
   already in force when the computed value changes, so adding this after the
   theme had been applied would do nothing at all.

   Custom properties themselves do not transition. What transitions is every
   USE of them -- `background-color: var(--body-bg)` interpolates perfectly
   well when --body-bg changes underneath it -- which is why this targets the
   handful of colour properties rather than the tokens.

   SCOPED AWAY FROM THE GANTT ON PURPOSE. The crew calendar's table is a year
   wide and tens of thousands of cells; putting a 1.6s colour transition on
   every one of them is the one place this would be felt. It is excluded, and
   the table simply swaps -- it sits on an opaque card, so it is not what the
   eye is following during a sky sweep anyway.
   ══════════════════════════════════════════════════════════════════════ */
html.sas-dl-fade body,
html.sas-dl-fade body * {
  transition:
    background-color var(--sas-dl-fade-ms, 1600ms) cubic-bezier(0.4, 0, 0.2, 1),
    border-color var(--sas-dl-fade-ms, 1600ms) cubic-bezier(0.4, 0, 0.2, 1),
    color var(--sas-dl-fade-ms, 1600ms) cubic-bezier(0.4, 0, 0.2, 1),
    fill var(--sas-dl-fade-ms, 1600ms) cubic-bezier(0.4, 0, 0.2, 1),
    stroke var(--sas-dl-fade-ms, 1600ms) cubic-bezier(0.4, 0, 0.2, 1) !important;
}
/* Opted out, as a SECOND rule rather than a :not() on the one above. A
   `:not(.stinson-crew-table *)` has to be evaluated against every element on
   the page, and the page it would cost most on is exactly the one being
   excluded. Two flat rules are far cheaper to match than one clever one.

   The gantt: a year-wide table of tens of thousands of cells, and the one
   place a global colour transition would actually be felt. It sits on an
   opaque card, so it is not what the eye follows during a sky sweep anyway.

   The scene: driven frame by frame by the renderer, so a CSS transition on top
   would fight it and smear the sweep. */
html.sas-dl-fade .stinson-crew-table,
html.sas-dl-fade .stinson-crew-table *,
html.sas-dl-fade .sas-dl-stage,
html.sas-dl-fade .sas-dl-stage * {
  transition: none !important;
}
@media (prefers-reduced-motion: reduce) {
  html.sas-dl-fade body,
  html.sas-dl-fade body * {
    transition-duration: 1ms !important;
  }
}

@keyframes sas-dl-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .sas-dl-bg { animation: none; }
}

/* ══════════════════════════════════════════════════════════════════════
   2. Sleep screen
   ----------------------------------------------------------------------
   z-index is above every overlay in this admin (the palette sits at 9000, the
   chat modal at 400, Leaflet's panes below 1000) but deliberately below the
   integer ceiling, so a genuine alert can still be put over it later.
   ══════════════════════════════════════════════════════════════════════ */
.sas-dl-sleep {
  position: fixed;
  top: 0;
  left: 0;
  /* 100vw, not `right: 0`, so the screen also covers the CLASSIC scrollbar
     gutter. `inset: 0` stops at the layout viewport, which on Windows and
     Linux leaves a ~15px strip of the working page showing down the right
     edge of an otherwise full-screen photograph. (macOS overlay scrollbars
     hide the problem locally, which is exactly why it is worth stating.)

     The obvious alternative -- `overflow: hidden` on <html> while asleep --
     reflows the whole page underneath to 15px wider and back again on wake,
     which on the crew calendar means re-laying out a year-wide gantt for a
     cosmetic gain. A fixed element contributes no scrollable overflow, so
     100vw cannot introduce a horizontal scrollbar of its own. */
  width: 100vw;
  height: 100vh;
  height: 100dvh;
  z-index: 2147480000;
  overflow: hidden;
  contain: layout paint;
  background: #05070a;
  cursor: none;
  opacity: 0;
  transition: opacity var(--sas-dl-fade-in, 900ms) cubic-bezier(0.22, 1, 0.36, 1);
  /* Ink here is on a photograph, not on a themed surface, so it does NOT use
     the --sas-fg-* scale: those are solved against --sas-bg-1 and this is an
     arbitrary sky. Everything is near-white over a shadow, the same treatment
     the plate's own HUD uses. */
  color: #f2f4f7;
  font-family: var(--stinson-font, "Space Grotesk", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif);
  text-shadow: 0 1px 3px rgb(0 0 0 / 0.7), 0 0 18px rgb(0 0 0 / 0.45);
}
.sas-dl-sleep.is-in { opacity: 1; }
.sas-dl-sleep.is-out {
  opacity: 0;
  transition-duration: var(--sas-dl-fade-out, 260ms);
}
.sas-dl-sleep[hidden] { display: none !important; }

/* A quiet gradient under the readouts. The scene's own vignette darkens the
   edges, but the clock sits top-left over whatever the photograph is doing
   there, and at midday that is bright snow. */
.sas-dl-sleep-shade {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(180deg, rgb(0 0 0 / 0.34) 0%, transparent 26%),
    linear-gradient(0deg, rgb(0 0 0 / 0.44) 0%, transparent 30%);
}

.sas-dl-hud {
  position: absolute;
  inset: 0;
  pointer-events: none;
  display: grid;
  grid-template-columns: 1fr auto;
  grid-template-rows: auto 1fr auto;
  padding: clamp(20px, 4vw, 54px);
  gap: 10px;
  font-variant-numeric: tabular-nums;
}
.sas-dl-hud-tl { grid-area: 1 / 1; }
.sas-dl-hud-tr { grid-area: 1 / 2; justify-self: end; }
.sas-dl-hud-bl { grid-area: 3 / 1; align-self: end; }
.sas-dl-hud-br { grid-area: 3 / 2; align-self: end; justify-self: end; text-align: right; }

.sas-dl-clock {
  display: flex;
  align-items: baseline;
  gap: 10px;
  font-size: clamp(3rem, 11vw, 8.5rem);
  font-weight: 200;
  letter-spacing: -0.03em;
  line-height: 0.94;
}
.sas-dl-clock .sec {
  font-size: 0.24em;
  opacity: 0.6;
  letter-spacing: 0.06em;
  font-weight: 400;
}
.sas-dl-date {
  margin-top: 10px;
  font-size: clamp(0.72rem, 1.5vw, 0.92rem);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  opacity: 0.86;
}

/* "The sky is not the sky right now." Shown whenever the theme has pinned the
   scene to a day or night that is not the current one.

   Amber, not red, and for the reason the login page's staging chip is amber:
   red is the brand colour on this admin, so a red note reads as an alarm.
   This is a disclosure, not a warning -- it is telling you the picture is
   showing what you asked it to show. */
.sas-dl-pinned {
  margin-top: 10px;
  font-size: clamp(0.62rem, 1.1vw, 0.72rem);
  letter-spacing: 0.1em;
  color: #e8b465;
  display: flex;
  align-items: center;
  gap: 7px;
}
.sas-dl-pinned::before {
  content: "";
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}
.sas-dl-pinned[hidden] { display: none; }

/* The wordmark is white in this file, which is why it can sit on the plate in
   either theme -- unlike the toolbar, which swaps in the dark-ink lockup on
   the light-bar presets. Here the backdrop is always a photograph. */
.sas-dl-brand {
  height: clamp(20px, 2.4vw, 30px);
  width: auto;
  opacity: 0.8;
  filter: drop-shadow(0 1px 3px rgb(0 0 0 / 0.6));
}

.sas-dl-phase {
  font-size: clamp(0.9rem, 2.2vw, 1.35rem);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-weight: 400;
}
.sas-dl-phasesub {
  margin-top: 6px;
  font-size: clamp(0.7rem, 1.4vw, 0.86rem);
  opacity: 0.74;
  letter-spacing: 0.02em;
}

.sas-dl-almanac {
  display: grid;
  grid-template-columns: auto auto auto;
  gap: 4px 16px;
  margin: 0;
  font-size: clamp(0.66rem, 1.2vw, 0.78rem);
  justify-items: end;
}
.sas-dl-almanac dt {
  grid-column: 1;
  display: flex;
  align-items: center;
  gap: 7px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  opacity: 0.78;
}
.sas-dl-almanac dt::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
}
/* These three are not the brand accent and must not follow it. They are the
   legend for three physical things in the picture -- the sun, the moon, the
   star field -- the same call the calendar's date scaffolding makes about
   weekends and holidays. */
.sas-dl-almanac dt.sun::before { background: #e0a03c; }
.sas-dl-almanac dt.moon::before { background: #9fbede; }
.sas-dl-almanac dt.stars::before { background: #c9cfda; }
.sas-dl-almanac dd { margin: 0; }
.sas-dl-almanac dd.a { grid-column: 2; }
.sas-dl-almanac dd.b { grid-column: 3; }

.sas-dl-hint {
  grid-area: 2 / 1 / 3 / 3;
  align-self: end;
  justify-self: center;
  font-size: clamp(0.62rem, 1.1vw, 0.72rem);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  opacity: 0.5;
  padding-bottom: clamp(10px, 3vh, 34px);
  animation: sas-dl-breathe 4.2s ease-in-out infinite;
}
@keyframes sas-dl-breathe {
  0%, 100% { opacity: 0.5; }
  50% { opacity: 0.24; }
}

@media (prefers-reduced-motion: reduce) {
  .sas-dl-hint { animation: none; }
  .sas-dl-sleep { transition-duration: 1ms; }
}

/* Below this the almanac and the hint are competing for a phone-sized frame
   with a clock that wants to be the loudest thing on it. The clock, the date
   and the phase are what a glance is for; the rest goes. */
@media (max-width: 620px), (max-height: 420px) {
  .sas-dl-almanac,
  .sas-dl-brand { display: none; }
}

/* ══════════════════════════════════════════════════════════════════════
   3. Settings -> Appearance -> Wallpaper
   ----------------------------------------------------------------------
   Two rules, kept HERE rather than in admin_settings.css so that file is not
   a fifth contended one to patch. Both are inert on every other page.

   The picture tile goes away when Daylight is the source -- it is not a
   choice that means anything then. Hidden, not disabled: a greyed-out drop
   target still reads as somewhere to drop a file. The strength and blur rows
   below it stay, because they still drive the same scrim over the same four
   pages.
   ══════════════════════════════════════════════════════════════════════ */
.sas-panel.is-daylight .sas-set-row:has([data-sas-bg-drop]) { display: none; }

/* Auto's explanation of itself, and the "not the real sky" disclosure. Both
   use the page's own ink tokens -- unlike the sleep screen's marker, these sit
   on a themed panel, not on a photograph, so --sas-fg-2 is the solved value
   here and a hardcoded amber would be the one that failed a preset. */
.sas-dl-autonote {
  margin: -4px 0 0;
  font-size: 0.78rem;
  color: var(--sas-fg-2);
}
.sas-dl-pinnote {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin: 0 0 4px;
  font-size: 0.82rem;
  color: var(--sas-fg-2);
}
.sas-dl-pinnote > span { flex: 1 1 22ch; }
.sas-dl-autonote[hidden],
.sas-dl-pinnote[hidden] { display: none; }
