/* ==========================================================================
   Reusable HUD motifs — bracket corners, scanline overlay
   ========================================================================== */

/* Panel glow: soft phosphor bloom at the edge of any positioned panel.
   Override --bracket-color per state (e.g. on :hover) to brighten. */
.bracket-corners {
  --bracket-color: var(--phosphor-dim);
  position: relative;
  box-shadow: var(--glow-panel);
}

/* Visually hidden, still read aloud. The clip-rect pattern rather than
   display:none or visibility:hidden — both of those also remove the element
   from the accessibility tree, which would silence #route-announcer, the one
   thing this class currently exists for (see announceRoute in js/main.js). */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ---- focus reticle ------------------------------------------------------ */
/* Every interactive element on the site already has a :focus-visible state in
   views.css, but they all express it the same way the :hover state does — by
   brightening the phosphor. Keyboard-only, that is indistinguishable from
   "the mouse happens to be over this", and on the reversed .is-active rows it
   is nearly invisible. So the color states stay exactly as they are and this
   layers a ring on top of all of them: one unconditional, themed outline that
   says "focus is here" regardless of hue or state.
   Declared as the bare pseudo-class (specificity 0,1,0) so every existing
   .thing:focus-visible rule in views.css still wins on color/border — those
   set no `outline`, so the two never collide. The two exceptions below are
   the cases where a 3px standoff ring would land somewhere wrong. */
:focus-visible {
  outline: 2px solid var(--phosphor-hi);
  outline-offset: 3px;
}

/* An active project row is filled solid with --phosphor, and its standoff
   ring sits in the panel gutter — a --phosphor-hi ring against a --phosphor
   fill is two near-identical greens touching. Black is the row's own
   foreground color when reversed (see .project-row.is-active in views.css),
   so the ring reads as part of the targeting-lock motif rather than a
   new color. Inset as well as recolored: offset outward, a black ring lands
   on the near-black panel gutter and is invisible — drawn inside, it sits on
   the phosphor fill where it actually reads. */
.project-row.is-active:focus-visible {
  outline-color: #000;
  outline-offset: -2px;
}

/* Inset instead of offset: these five sit flush against a panel edge, a
   viewport edge, or inside a 1px grid gutter, where an outward ring is
   clipped or overlaps the neighbour rather than surrounding the control. */
.lightbox__close:focus-visible,
.lightbox__prev:focus-visible,
.lightbox__next:focus-visible,
.mdrawer-tab:focus-visible,
.cs2__tab:focus-visible {
  outline-offset: -2px;
}

/* ---- promoted headings -------------------------------------------------- */
/* Each section header's breadcrumb is a real <h1> rather than a <span>, so
   every view has a top-level heading to announce and to park focus on when it
   opens (see focusViewHeading in js/main.js). It was a <span>; these two
   declarations undo the UA stylesheet's h1 margin and bold weight so the
   promoted element renders pixel-identically to the span it replaced.
   .breadcrumb's own font-size already overrides the UA 2em, and inside
   .section-header's flex row the element was blockified either way. */
h1.breadcrumb {
  margin: 0;
  font-weight: normal;
}

/* ---- ambient video toggle ----------------------------------------------- */
/* Pause/play for the silent ambient loops (`video.mode: "autoplay-loop"` in
   js/data.js). Those deliberately render with no native controls — a looping
   background plate with a chrome control bar across it stops reading as a
   plate — which left a visitor no way at all to stop moving imagery. This is
   the one affordance: keyboard-operable, in the drawer tabs' visual language
   rather than a media player's, sitting in the corner of the slot. It is also
   how the clip gets STARTED under prefers-reduced-motion, where
   hydrateVideoSlot renders the poster frame paused instead of autoplaying.
   Positioning is against the slot, which always carries .bracket-corners and
   is therefore already position: relative. */
.video-toggle {
  position: absolute;
  right: var(--gap-sm);
  bottom: var(--gap-sm);
  z-index: 1;
  min-height: var(--mdrawer-tab-h);
  padding: 0 var(--gap-sm);
  background: var(--bg-panel);
  border: var(--border-hair);
  color: var(--phosphor-mut);
  font-family: var(--font-mono);
  font-size: 0.786rem;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  cursor: pointer;
}

.video-toggle:hover,
.video-toggle:focus-visible {
  color: var(--phosphor-hi);
}

/* Fixed scanline overlay — sits above every view, ignores pointer events */
.scanline-overlay {
  position: fixed;
  inset: 0;
  z-index: 999;
  pointer-events: none;
  background-image: repeating-linear-gradient(
    to bottom,
    var(--scanline) 0px,
    var(--scanline) 1px,
    transparent 1px,
    transparent 3px
  );
}
