/*
 * The HD-2D layer and the content layer (tickets 930 and 973; design note §5, z/notes/console-design-*.md).
 *
 * Linked LAST in index.html, so it wins by source order and needs no !important. It changes how the
 * console is lit and layered, never what it says: text and data stay at native resolution.
 *
 * Two layers:
 *   decoration     one band, at most 160px tall, behind the top bar, the local nav row and the page head
 *                  (js/hd_band.js draws a pixel night harbor on its canvas; a masked backdrop blur gives the
 *                  tilt-shift on its top edge; a warm bloom sits behind the title). The buildings stand in
 *                  the second chrome row, clear of every link and control (ticket 001075). It scrolls away
 *                  with the page. The pointer light (js/pointer_light.js feeds --light-x/--light-y) lives only
 *                  inside it. The sign-in cove, the Home diorama, the War room harbor and the empty-state
 *                  vignette are the other places decoration may be (their own sheets).
 *   content        panels, tiles, tables, lists, forms, charts and text: flat, opaque, crisp. A plate is
 *                  `--panel` with a plain border. No blur, no gold edge, no hover lift, no bloom.
 * The control layer (the top bar, its menus, the search overlay, the phone tab bar) keeps its glass.
 *
 * The scene's light never uses the accent hue and never recolors status, severity or selection. Reduced
 * motion: the band is a still frame already (it is never animated) and the pointer light is off.
 * Reduced transparency or more contrast: every glass surface is opaque. Forced colors: system colours.
 *
 * Look rules: no web font, no CDN, no inline style, no image file (the band is drawn on a canvas).
 */

:root {
  /* The fill of the control layer's glass: the dense one of the top bar, a menu or the tab bar (the page
     text behind a menu must never read through it). */
  --hud-fill: rgba(22, 22, 26, 0.64);
  --hud-fill-2: rgba(20, 20, 24, 0.86);
  --plane-2: var(--hud-fill-2);

  /* The 1px gradient edge of a control-layer plate (also the sign-in card's). */
  --hud-edge: linear-gradient(
    135deg,
    rgba(255, 255, 255, 0.16),
    rgba(222, 199, 107, 0.22) 35%,
    rgba(255, 255, 255, 0.03) 70%
  );
  --hud-blur-2: 20px;

  /* The shadow that sets a menu, a dialog or the tab bar above the page. */
  --elev-3: 0 1px 0 rgba(255, 255, 255, 0.08) inset, 0 28px 64px -20px rgba(0, 0, 0, 0.9);

  /* Where the pointer is, in px. Off screen until the first move. */
  --light-x: -2000px;
  --light-y: -2000px;

  /* The page chrome's second row (ticket 001075): the local nav row's height (44px min-height + its 1px
     rule). A section's pages draw the local nav in it; every other signed-in page keeps the same height
     empty (the harbor stands in it), so the page head starts at the same place on every page. */
  --chrome-row-h: 45px;
}

/* ---- The band ---------------------------------------------------------------------------- */

/* Out of flow: it takes no height from the page (ticket 926), sits under the top bar, the local nav row
   and the page head (z-index -1 paints above the page colour and below all content), and scrolls away
   with the page. The bottom 40% fades into the page colour. Everything drawn here is dark enough that
   --ink-body text clears 4.5:1 over it (js/hd_band.js BAND_PALETTE). */
.hd-band {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 160px;
  z-index: -1;
  overflow: hidden;
  pointer-events: none;
  -webkit-mask-image: linear-gradient(to bottom, #000 75%, transparent);
  mask-image: linear-gradient(to bottom, #000 75%, transparent);
}

@media (max-width: 760px) {
  .hd-band {
    height: 120px;
  }
}

/* The canvas is a fixed wide strip anchored to the left: the buildings keep to a fixed place in the second
   chrome row (js/hd_band.js, ticket 001075) and a wider screen shows more sky. js/hd_band.js sets
   data-scale (3 above 760px, 2 at 760px and narrower); the CSS size is a whole multiple of the canvas, so
   the pixels stay square. The 3x picture is 147px tall. */
.hd-band__scene {
  position: absolute;
  top: 0;
  left: 0;
  display: block;
  width: 3840px;
  height: 147px;
  image-rendering: pixelated;
}

.hd-band__scene[data-scale="2"] {
  height: 120px;
}

/* Tilt-shift on the top edge: a static strip whose backdrop is the picture, blurred a little and faded
   out going down. It sits inside the masked band, so it samples the canvas and nothing else. */
.hd-band::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 56px;
  z-index: 1;
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
  -webkit-mask-image: linear-gradient(to bottom, #000, transparent);
  mask-image: linear-gradient(to bottom, #000, transparent);
}

/* A soft warm bloom behind the title area at the left: low-alpha peach, never the accent. */
.hd-band::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  width: min(60%, 720px);
  z-index: 1;
  background: radial-gradient(ellipse at 18% 70%, rgba(255, 168, 112, 0.12), transparent 70%);
}

/* The sign-in cove is its own scene; the War room harbor and the Present board fill the screen. */
body.signed-out .hd-band,
body.is-kiosk .hd-band,
body.is-board .hd-band {
  display: none;
}

/* The local nav row sits fully over the band and the page head starts inside its fade, so neither has a
   fill of its own; the row's text is --ink-body or --ink, which clear 4.5:1 over any band pixel. */
.local-nav {
  background: none;
}

.local-nav__link {
  color: var(--ink-body);
}

.local-nav__link:hover,
.local-nav__link.is-current {
  color: var(--ink);
}

/* ---- The pointer light ------------------------------------------------------------------- */

/* One empty element inside the band (index.html) holds one moon-white glow. The glow is painted once and
   only moved, by `transform`, to where js/pointer_light.js says the pointer is; the band clips it. The
   blend is on the overlay, not on the glow: a blend mode only reaches what is inside its own stacking
   context (the band's). No `background-attachment: fixed`: it repaints on scroll and iOS ignores it. */
.depth-light {
  position: absolute;
  inset: 0;
  z-index: 2;
  overflow: hidden;
  pointer-events: none;
  contain: strict;
  mix-blend-mode: screen;
}

.depth-light::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 640px;
  height: 640px;
  background: radial-gradient(circle, rgba(190, 205, 255, 0.08), transparent 45%);
  transform: translate3d(calc(var(--light-x) - 320px), calc(var(--light-y) - 320px), 0);
  will-change: transform;
}

/* No pointer to follow on a touch screen. */
@media (hover: none) {
  .depth-light {
    display: none;
  }
}

/* ---- The content layer: flat, opaque, crisp ------------------------------------------------- */

.card,
.stat-tile,
.table-scroll,
.glass,
.home-number {
  background: var(--panel);
  border: 1px solid var(--border);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  box-shadow: none;
}

/* The page head (js/page_head.js, tickets 931 and 972) has no plate and no hairline: the title sits on
   the foot of the band. z-index 1 lifts the head's menus (the Reports "Present" menu) over the panels drawn
   after it. The strip it carries from index.html (#evidence-summary) is hidden at its home on the pages
   that move it into the head, so the page does not jump up when the head draws it (ticket 926); the
   Overview board keeps it at home. */
.workspace-head {
  position: relative;
  z-index: 1;
  padding: var(--space-4) 0 var(--space-3);
}

/* One page head on every page (ticket 001075, audit SC3). The title sits at one height: a page with no local
   nav row (Dashboard, Fleet, Settings, the War room and the rest) keeps that row's height empty above its
   head, where the harbor stands, so its title starts where a section page's does (148px from the top at
   1512px). The Dashboard's and Settings' own top margins (home.css, settings.css) are taken back, so the
   head, and the Settings sidebar beside it, start at the same place. The phone keeps its tab bar and no
   empty row. */
@media (min-width: 761px) {
  body:not(.signed-out):not(.is-kiosk):not(.is-board) .local-nav[hidden] ~ .view-root {
    padding-top: calc(var(--space-5) + var(--chrome-row-h));
  }

  .view-root .home,
  .view-root .settings-layout {
    margin-top: 0;
  }
}

/* The page head's rows: the title block and the page's controls (window picker, buttons) start at one
   height. A head with a second line under its title (Meeting Sites: "Current Legend: ...") used to centre
   the controls on both lines and so lowered them by about 14px; the controls now centre on the title's
   own row (2.3rem, the title's line box) and stay there. */
.workspace-head {
  align-items: flex-start;
}

.workspace-head__action {
  min-height: 2.3rem;
}

/* The way back from a detail page (js/page_head.js backLink, and the Case File's own link): a block with
   one fixed gap (--space-4) to the title under it, whether the title is the head's (which then drops its
   own top padding) or stands alone. */
.operation-back,
.investigation-back {
  display: block;
  width: fit-content;
  margin: 0 0 var(--space-4);
}

.operation-back + .workspace-head {
  padding-top: 0;
}

/* The Case File's header is a flex column with its own 0.5rem gap: take it out of the link's margin, so the
   gap to the title is the same --space-4 there too. */
.investigation-header > .investigation-back,
.operation-header > .operation-back {
  margin-bottom: calc(var(--space-4) - 0.5rem);
}

body[data-route="investigate"] #evidence-summary:not(.is-in-head),
body[data-route="meeting-sites"] #evidence-summary:not(.is-in-head),
body[data-route="reports"] #evidence-summary:not(.is-in-head),
body[data-route="war-room"] #evidence-summary:not(.is-in-head),
body[data-route="overview"]:not(.is-board) #evidence-summary:not(.is-in-head) {
  display: none;
}

/* A home tile whose value is text ("Oct 21, 17:46 UTC") takes one step down and one line, cut with
   an ellipsis if the column is ever too narrow; the full text rides on its title. */
.home-number__value--text {
  font-size: var(--fs-lg);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-family: var(--font-mono);
}

/* The Filters dialog and the request detail drawer hold forms, tables and text, so they are opaque; a
   shadow alone sets them above the page. The overlay itself stays the dark scrim it is. */
.capture-settings {
  background: var(--panel);
  border: 1px solid var(--border-strong);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  box-shadow: var(--elev-3);
}

.detail-panel {
  background: var(--panel);
  border-left: 1px solid var(--border-strong);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  box-shadow: var(--elev-3);
}

/* ---- The control layer: menus and the top bar -------------------------------------------- */

.nav-panel,
.global-search__results {
  background:
    linear-gradient(var(--plane-2), var(--plane-2)) padding-box,
    var(--hud-edge) border-box;
  border: 1px solid transparent;
  -webkit-backdrop-filter: blur(var(--hud-blur-2)) saturate(140%);
  backdrop-filter: blur(var(--hud-blur-2)) saturate(140%);
  box-shadow: var(--elev-3);
}

/* The top bar is glass over the band, with a neutral hairline under it. The glass is on ::before, not on
   the navbar itself: an element with a backdrop-filter is a backdrop root, which would make the menus
   inside it blur only the navbar and not the page behind them. This replaces console-simple.css's solid
   #111 navbar on purpose. */
.navbar {
  background: none;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  border-bottom: 1px solid transparent;
  box-shadow: 0 10px 28px -20px rgba(0, 0, 0, 0.85);
}

.navbar::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: linear-gradient(var(--plane-2), var(--plane-2));
  -webkit-backdrop-filter: blur(var(--hud-blur-2)) saturate(140%);
  backdrop-filter: blur(var(--hud-blur-2)) saturate(140%);
}

.navbar::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 1px;
  pointer-events: none;
  background: rgba(255, 255, 255, 0.08);
}

/* ---- The empty-state vignette (js/pixel_vignette.js) ---------------------------------------- */

/* A 64x44 picture at 3x, above the one line of fact in an empty state or on the not-found page. */
.pixel-vignette {
  display: block;
  width: 192px;
  height: 132px;
  image-rendering: pixelated;
}

/* ---- Fallbacks -------------------------------------------------------------------------- */

/* No backdrop-filter: a glass fill would show the page text through it, so the control layer goes solid
   and the band has no tilt-shift. */
@supports not (backdrop-filter: blur(1px)) {
  :root {
    --hud-fill: var(--panel);
    --hud-fill-2: var(--panel);
  }

  .hd-band::before {
    display: none;
  }
}

/* Reduced transparency: every remaining glass surface is opaque (the top bar, its menus, the search
   overlay and the tab bar read --plane-2) and the band has no blur layer. */
@media (prefers-reduced-transparency: reduce) {
  :root {
    --hud-fill: var(--panel);
    --hud-fill-2: var(--panel);
  }

  .nav-panel,
  .global-search__results,
  .navbar::before,
  .hd-band::before {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }

  .hd-band::before,
  .depth-light {
    display: none;
  }
}

/* More contrast: every panel is opaque and the picture goes. */
@media (prefers-contrast: more) {
  :root {
    --hud-fill: var(--panel);
    --hud-fill-2: var(--panel);
  }

  .nav-panel,
  .global-search__results,
  .navbar::before,
  .view-root:has(> .login-brand) > .login-panel {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }

  .hd-band {
    display: none;
  }
}

/* Forced colors: the system palette rules. No glass, picture, light or bloom; panels keep a plain system
   border. */
@media (forced-colors: active) {
  .card,
  .stat-tile,
  .table-scroll,
  .glass,
  .home-number,
  .nav-panel,
  .global-search__results,
  .capture-settings {
    background: Canvas;
    border: 1px solid CanvasText;
    box-shadow: none;
  }

  .detail-panel {
    background: Canvas;
    border-left: 1px solid CanvasText;
    box-shadow: none;
  }

  .navbar {
    background: Canvas;
    box-shadow: none;
    border-bottom: 1px solid CanvasText;
  }

  .navbar::before,
  .navbar::after,
  .hd-band,
  .pixel-vignette {
    display: none;
  }
}

/* Reduced motion: no light follows the pointer. The band is never animated, so it is already still. */
@media (prefers-reduced-motion: reduce) {
  .depth-light {
    display: none;
  }
}

/* On a phone the Investigations list is a stack of row cards and its wrapper is deliberately flat
   (investigations.css, 640px and narrower), so the wrapper is not a panel there. Last in the file so it
   also wins over the forced-colors border above. */
@media (max-width: 640px) {
  .investigations-scroll {
    background: none;
    border: 0;
    box-shadow: none;
  }
}

/* A printed page is flat and white: no picture, no light, no vignette. */
@media print {
  .hd-band,
  .navbar::before,
  .navbar::after,
  .pixel-vignette {
    display: none;
  }

  .workspace-head {
    padding-inline: 0;
  }
}
