/* HYPER RED — layout
   The application shell: atmospheric background, header, primary nav,
   main content grid, and footer. */

/* ---- Atmosphere ----
   A layered background system rather than one flat color: tonal depth,
   one large soft red light + one faint neutral light (both drifting a
   few px over ~20s — alive, never "animated"), one architectural red
   plane mostly off-canvas, a two-line editorial grid, a soft horizon
   band, and film grain. Per-viewport that's exactly: 1 atmospheric
   light pairing, 1 geometric form, 1 texture, a couple of lines —
   deliberately not more. Everything here is transform/opacity only, so
   it stays cheap, and the global reduced-motion rules in base.css
   already zero out every animation-duration below with no extra work. */
.hr-atmosphere {
  position: fixed;
  inset: 0;
  z-index: -1;
  overflow: hidden;
  /* Tonal depth lives directly on the element's own background so it
     paints FIRST — everything else here is a real child element after
     it in the DOM, so lights/plane/grid/horizon correctly paint on
     top of it instead of a ::after (which paints last) covering them. */
  background:
    radial-gradient(140% 90% at 50% 108%, rgba(0, 0, 0, 0.55), transparent 55%),
    linear-gradient(165deg, #070707 0%, var(--bg-0) 45%, #020202 100%);
}

.hr-atm-light {
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
  will-change: transform;
}

/* The one major atmospheric effect: reflected red light bleeding in
   from the top-right, not a visible shape. */
.hr-atm-light-red {
  top: -20%;
  right: -14%;
  width: min(1400px, 115vw);
  height: min(1400px, 115vw);
  /* Peak alpha trimmed ~15% (0.2 -> 0.17) as part of the general
     "fewer/lighter simultaneous effects" pass (Section 7, item 15) —
     the hero's own imagery/scrim carry the drama, this ambient light no
     longer needs to compete at full strength underneath it. */
  background: radial-gradient(circle, rgba(255, 42, 50, 0.17) 0%, rgba(227, 35, 43, 0.075) 30%, rgba(227, 35, 43, 0.025) 52%, transparent 68%);
  animation: hrLightDriftRed 19s ease-in-out infinite alternate;
}

/* A near-imperceptible neutral counter-light from the opposite corner,
   for dimensional separation rather than a second "effect". */
.hr-atm-light-white {
  top: -12%;
  left: -16%;
  width: min(900px, 80vw);
  height: min(900px, 80vw);
  background: radial-gradient(circle, rgba(255, 255, 255, 0.032) 0%, rgba(255, 255, 255, 0.01) 40%, transparent 65%);
  animation: hrLightDriftWhite 24s ease-in-out infinite alternate;
}

@keyframes hrLightDriftRed {
  from { transform: translate(0, 0); }
  to { transform: translate(-18px, 14px); }
}

@keyframes hrLightDriftWhite {
  from { transform: translate(0, 0); }
  to { transform: translate(14px, -10px); }
}

/* The one geometric element: an architectural red plane, mostly
   outside the viewport, echoing the intro's red half. Its edge is
   softened with a mask rather than a hard color stop. */
.hr-atm-plane {
  position: absolute;
  top: -15vh;
  right: -25vw;
  width: 45vw;
  height: 130vh;
  transform: skewX(-6deg);
  background: linear-gradient(200deg, #240000 0%, #7a0d12 45%, var(--hr-red) 85%);
  /* 0.18 -> 0.14 (~22% down) — one fewer competing decorative system at
     full strength (Section 7, item 15). */
  opacity: 0.14;
  -webkit-mask-image: linear-gradient(90deg, transparent, black 42%);
  mask-image: linear-gradient(90deg, transparent, black 42%);
}

/* A soft horizontal band in the lower third — the feeling of standing
   in a dark studio with one controlled light, not a visible stripe. */
.hr-atmosphere-horizon {
  position: absolute;
  left: 0;
  right: 0;
  top: 60%;
  height: 260px;
  background: linear-gradient(180deg, transparent, rgba(255, 255, 255, 0.02), transparent);
}

.hr-grain {
  position: fixed;
  inset: 0;
  z-index: -1;
  /* 0.028 -> 0.022 (~21% down), part of the same effects-reduction pass. */
  opacity: 0.022;
  mix-blend-mode: overlay;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='140'%20height='140'%3E%3Cfilter%20id='n'%3E%3CfeTurbulence%20type='fractalNoise'%20baseFrequency='0.85'%20numOctaves='2'%20stitchTiles='stitch'/%3E%3C/filter%3E%3Crect%20width='100%25'%20height='100%25'%20filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 140px 140px;
}

/* Editorial grid — two verticals aligned to the content column, not a
   tiled graph-paper pattern. Faded top and bottom so the lines never
   read as a hard-edged overlay. --grid-alpha is a real CSS custom
   property (not an invalid opacity>1 multiplier — see the per-section
   overrides below) so a section can ask for a visibly stronger grid line
   without ever going outside the 0–1 range opacity actually supports. */
.hr-atmosphere-grid {
  --grid-alpha: 0.032;
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(90deg, transparent calc(50% - (var(--app-max-width-wide) / 2)), rgba(255, 255, 255, var(--grid-alpha)) calc(50% - (var(--app-max-width-wide) / 2)), rgba(255, 255, 255, var(--grid-alpha)) calc(50% - (var(--app-max-width-wide) / 2) + 1px), transparent calc(50% - (var(--app-max-width-wide) / 2) + 1px)),
    linear-gradient(90deg, transparent calc(50% + (var(--app-max-width-wide) / 2) - 1px), rgba(255, 255, 255, var(--grid-alpha)) calc(50% + (var(--app-max-width-wide) / 2) - 1px), rgba(255, 255, 255, var(--grid-alpha)) calc(50% + (var(--app-max-width-wide) / 2)), transparent calc(50% + (var(--app-max-width-wide) / 2)));
  -webkit-mask-image: linear-gradient(180deg, transparent, black 10%, black 85%, transparent);
  mask-image: linear-gradient(180deg, transparent, black 10%, black 85%, transparent);
}

/* Corner coordinate brackets — a restrained nod to track-map/telemetry
   framing. Lives on its own dedicated element (not sharing ::before/
   ::after with .hr-atmosphere, which already uses both for the map
   image and vignette) so it can't collide with or override them.
   Purely decorative, hidden from assistive tech, and dropped on narrow
   viewports where it would just compete with content. */
.hr-corner-marks::before,
.hr-corner-marks::after {
  content: "";
  position: fixed;
  top: 84px;
  width: 22px;
  height: 22px;
  border-top: 1px solid var(--border-subtle);
  /* 0.5 -> 0.4, same reduction pass — a restrained nod, not a HUD frame. */
  opacity: 0.4;
  pointer-events: none;
  z-index: 1;
}
.hr-corner-marks::before { left: 18px; border-left: 1px solid var(--border-subtle); }
.hr-corner-marks::after { right: 18px; border-right: 1px solid var(--border-subtle); }

@media (max-width: 900px) {
  .hr-corner-marks::before,
  .hr-corner-marks::after { display: none; }
}

/* ---- Per-section atmosphere ----
   The same layered system above, re-balanced per active tab via
   body[data-section] (set alongside the tablist in main.js). Opacity
   only — never adds/removes elements or changes layout — so it can
   transition smoothly and costs nothing extra to compute. Signup is
   the baseline (already tuned above); these are relative adjustments. */
.hr-atm-light-red,
.hr-atm-light-white,
.hr-atmosphere-grid,
.hr-atmosphere-horizon {
  transition: opacity 700ms var(--ease-standard);
}

/* Roster: darker, more technical — dial the red glow back and let the
   editorial grid read a little stronger as a control-room cue. Capped at
   1 (opacity above 1 is invalid CSS and was silently clamped to 1 by the
   browser — Section 7, item 20); the intended "stronger grid" effect is
   now expressed through --grid-alpha driving the gradient's own alpha
   instead of an out-of-range opacity multiplier. */
body[data-section="roster"] .hr-atm-light-red { opacity: 0.5; }
body[data-section="roster"] .hr-atmosphere-grid { opacity: 1; --grid-alpha: 0.05; }
body[data-section="roster"] .hr-atmosphere-horizon { opacity: 0.45; }

/* Calendar: more open, slightly brighter centre — ease off both lights
   a touch so the season list itself carries the page. Same opacity-cap
   fix as Roster above. */
body[data-section="calendar"] .hr-atm-light-red { opacity: 0.6; }
body[data-section="calendar"] .hr-atm-light-white { opacity: 1; }
body[data-section="calendar"] .hr-atmosphere-horizon { opacity: 1; }

/* ---- Header ---- */
.hr-header {
  position: sticky;
  top: 0;
  z-index: 40;
  height: var(--header-height);
  display: flex;
  align-items: center;
  background: rgba(8, 8, 9, 0.6);
  backdrop-filter: blur(10px) saturate(1.1);
  border-bottom: 1px solid transparent;
  transition: background var(--dur-slow) var(--ease-standard), border-color var(--dur-slow) var(--ease-standard);
}

/* Solidifies once the page has scrolled past the very top of the hero —
   .hr-header starts more transparent so the cinematic hero can read
   as full-bleed, then reads as a firm operational bar once content is
   underway. Toggled by a single rAF-batched scroll listener in main.js. */
.hr-header.is-scrolled {
  background: rgba(8, 8, 9, 0.92);
  border-bottom-color: var(--border-subtle);
}

/* Thin race-control accent riding the very top edge of the viewport —
   a single deliberate red line rather than a colored header background. */
.hr-header::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: linear-gradient(90deg, transparent, var(--hr-red) 15%, var(--hr-red) 85%, transparent);
  opacity: 0.85;
}

.hr-header-inner {
  width: 100%;
  max-width: var(--app-max-width-wide);
  margin: 0 auto;
  padding: 0 var(--sp-5);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
}

.hr-brand {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-width: 0;
  text-decoration: none;
}

.hr-brand-mark {
  width: 32px;
  height: 32px;
  flex-shrink: 0;
  object-fit: contain;
}

.hr-brand-text {
  display: flex;
  flex-direction: column;
  line-height: 1.1;
  min-width: 0;
}

.hr-brand-word {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 17px;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--text-primary);
  white-space: nowrap;
}

.hr-brand-word em {
  font-style: normal;
  color: var(--hr-red-bright);
}

.hr-brand-sub {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-faint);
  white-space: nowrap;
}

/* Visual grouping between the brand block and the operational nav rail —
   same border-left language as .hr-header-right, so the header reads as
   three deliberate zones (brand / nav / status) rather than one row of
   evenly-spaced items. */
@media (min-width: 720px) {
  .hr-nav {
    padding-left: var(--sp-4);
    border-left: 1px solid var(--border-subtle);
    margin-right: auto;
  }
}

/* ---- Primary nav (tabs) ----
   A compact operational rail rather than a pill-tab component: each item
   carries its own bottom indicator so the active area reads as "current
   operational area", not a generic selected-tab chip. */
.hr-nav {
  display: flex;
  align-items: stretch;
  gap: var(--sp-1);
  height: 100%;
  padding: 0;
}

.hr-nav-btn {
  position: relative;
  display: flex;
  align-items: center;
  gap: 7px;
  border: none;
  background: transparent;
  color: var(--text-faint);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 12.5px;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  padding: 0 14px;
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease-standard);
  min-height: var(--touch-target);
}

.hr-nav-btn::after {
  content: "";
  position: absolute;
  left: 14px;
  right: 14px;
  bottom: 0;
  height: 2px;
  background: var(--hr-red);
  transform: scaleX(0);
  transform-origin: center;
  transition: transform var(--dur-base) var(--ease-spring);
}

.hr-nav-btn svg {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  opacity: 0.85;
}

.hr-nav-btn:hover {
  color: var(--text-secondary);
}

.hr-nav-btn[aria-selected="true"] {
  color: var(--text-primary);
}

.hr-nav-btn[aria-selected="true"]::after {
  transform: scaleX(1);
}

/* ---- Header status + admin entry point ---- */
.hr-header-right {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  padding-left: var(--sp-4);
  border-left: 1px solid var(--border-subtle);
  height: 100%;
}

.hr-status-chip {
  display: none;
  align-items: center;
  gap: 7px;
  font-family: var(--font-display);
  font-size: var(--font-size-micro);
  font-weight: 700;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-faint);
}

.hr-status-dot {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--status-success);
  box-shadow: 0 0 0 3px rgba(53, 196, 106, 0.16);
}

/* Tiny "still live" pulse — a ring that briefly expands and fades once
   every ~2s, restrained (kept to the ring, not the dot itself, and never
   more than a few px) and only while genuinely online. Automatically
   frozen by the global reduced-motion override like every other
   animation in the app. */
.hr-status-chip[data-state="online"] .hr-status-dot {
  position: relative;
}
.hr-status-chip[data-state="online"] .hr-status-dot::after {
  content: "";
  position: absolute;
  inset: -3px;
  border-radius: 50%;
  border: 1px solid var(--status-success);
  opacity: 0;
  animation: hrStatusPulse 2.2s ease-out infinite;
}

@keyframes hrStatusPulse {
  0% { opacity: 0.55; transform: scale(0.6); }
  70% { opacity: 0; transform: scale(1.9); }
  100% { opacity: 0; transform: scale(1.9); }
}

.hr-status-chip[data-state="offline"] .hr-status-dot {
  background: var(--status-error);
  box-shadow: 0 0 0 3px rgba(255, 90, 95, 0.16);
}

@media (min-width: 720px) {
  .hr-status-chip { display: inline-flex; }
}

.hr-admin-entry {
  display: inline-flex;
  align-items: center;
  height: var(--touch-target);
  border: none;
  background: transparent;
  color: var(--text-faint);
  font-family: var(--font-display);
  font-size: var(--font-size-micro);
  font-weight: 700;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  cursor: pointer;
  transition: color var(--dur-fast);
}

.hr-admin-entry:hover {
  color: var(--text-secondary);
}

.hr-admin-entry[data-active="true"] {
  color: var(--hr-red-bright);
}

.hr-admin-entry[data-active="true"]::before {
  content: "";
  display: inline-block;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--hr-red-bright);
  margin-right: 6px;
}

/* ---- Mobile nav ---- */
.hr-nav-mobile-toggle {
  display: none;
}

@media (max-width: 719px) {
  .hr-nav { display: none; }

  .hr-nav-mobile-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--touch-target);
    height: var(--touch-target);
    background: var(--bg-2);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    color: var(--text-primary);
  }

  .hr-nav.mobile-open {
    display: flex;
    position: fixed;
    top: var(--header-height);
    left: 0;
    right: 0;
    flex-direction: column;
    background: var(--bg-1);
    border: none;
    border-bottom: 1px solid var(--border-subtle);
    padding: var(--sp-2);
    gap: 2px;
    z-index: 39;
    height: auto;
  }

  .hr-nav.mobile-open .hr-nav-btn {
    justify-content: flex-start;
    width: 100%;
    padding: 13px 14px;
    min-height: var(--touch-target);
    border-left: 2px solid transparent;
  }

  .hr-nav.mobile-open .hr-nav-btn::after { display: none; }

  .hr-nav.mobile-open .hr-nav-btn[aria-selected="true"] {
    background: rgba(227, 35, 43, 0.08);
    border-left-color: var(--hr-red);
  }
}

/* ---- Main content ---- */
.hr-main {
  width: 100%;
  max-width: var(--app-max-width-wide);
  margin: 0 auto;
  padding: var(--sp-6) var(--sp-5) var(--sp-16);
}

.hr-panel-wrap {
  display: none;
}

.hr-panel-wrap.active {
  display: block;
  animation: hr-panel-in var(--dur-base) var(--ease-standard);
}

@keyframes hr-panel-in {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: translateY(0); }
}

/* ---- Footer ---- */
.hr-footer {
  border-top: 1px solid var(--border-subtle);
  padding: var(--sp-8) var(--sp-5);
  text-align: center;
}

.hr-footer-text {
  font-size: 12px;
  color: var(--text-faint);
}

/* ---- Section width helpers ---- */
.hr-section-narrow {
  max-width: 620px;
  margin: 0 auto;
}

.hr-section-wide {
  width: 100%;
}

/* Backend-aware connection states */
.hr-status-chip[data-state="live"] .hr-status-dot { background:var(--status-success); box-shadow:0 0 0 3px rgba(53,196,106,.16); position:relative; }
.hr-status-chip[data-state="live"] .hr-status-dot::after { content:""; position:absolute; inset:-3px; border-radius:50%; border:1px solid var(--status-success); animation:hrStatusPulse 2.2s ease-out infinite; }
.hr-status-chip[data-state="reconnecting"] .hr-status-dot { background:#e6b94a; box-shadow:0 0 0 3px rgba(230,185,74,.14); }
.hr-status-chip[data-state="cached"] .hr-status-dot { background:#80a7c7; box-shadow:0 0 0 3px rgba(128,167,199,.14); }
