/* ────────────────────────────────────────────────────────────────────────────
 * styles.css — non-Tailwind component CSS + body-level chrome.
 *
 * Most v1.0 styles migrated to css/tailwind-source.css (component layer).
 * This file holds:
 *   - body background gradient + base layout (was inline style on <body>)
 *   - grain overlay positioning (was inline style on the <div>)
 *   - SVG-defs container hide rule
 *
 * NOTE on CSP: the project's strict policy is `style-src 'self'`. That does
 * NOT forbid inline `style="..."` attributes (those are governed by the
 * separate `style-src-attr` directive, which we are NOT setting — so the CSS3
 * fallback rule applies and inline style attrs remain allowed). Element-set
 * inline styles via JS (`el.style.transform = ...`) are likewise unaffected.
 * What `style-src 'self'` blocks is the `<style>` element with no src — i.e.,
 * Tailwind CDN runtime JIT and any hand-written `<style>` block in HTML. We
 * eliminated both in this Phase 6 refactor.
 * ──────────────────────────────────────────────────────────────────────────── */

/* ─── Body chrome — was inline style="" on <body> in v1.0 ─── */
body {
  margin: 0;
  padding: 0;
  min-height: 100vh;
  /* Ntiva navy → ocean → teal diagonal gradient.
   * v3.1: switched from fixed to scroll so the gradient extends with page
   * content. The mobile launcher scrolls past one viewport (especially in
   * single-column grid view); fixed left a hard transition where the
   * gradient ended. On desktop the visual difference is negligible. */
  background: linear-gradient(135deg, #0f172a 0%, #0c4a6e 60%, #0e7490 100%);
  background-attachment: scroll;
  font-family: 'Inter', sans-serif;
}

/* ─── Hidden SVG defs container (grain filter) — was inline style="" ─── */
.svg-defs {
  display: none;
  position: absolute;
  width: 0;
  height: 0;
}

/* ─── Edit banner default visibility — was inline style="display:none" ─── */
#edit-banner { display: none; }

/* ─── Edit toolbar default visibility — was inline style="display:none" ─── */
#edit-toolbar { display: none; }

/* ─── Grain overlay — full-viewport sibling of header + main ─── */
.grain-overlay {
  position: fixed;
  inset: 0;
  pointer-events: none;
  filter: url(#grain);
  opacity: 0.07;
  mix-blend-mode: overlay;
  z-index: 1;
}

/* ─── Header padding — was inline on <header> ─── */
.site-header {
  padding: 1rem 1.5rem;
}

/* ─── Vertical separator between Ntiva mark + OneSpot wordmark ─── */
.brand-separator {
  width: 1px;
  height: 32px;
  background: rgba(255, 255, 255, 0.25);
}

/* ─── Ntiva logo — mix-blend-mode multiply removes white background ─── */
.brand-logo {
  height: 40px;
  width: auto;
  mix-blend-mode: multiply;
}

/* ─── OneSpot wordmark + subtitle ─── */
.brand-wordmark {
  font-size: 1.2rem;
  letter-spacing: -0.03em;
  line-height: 1.2;
}
.brand-subtitle {
  font-size: 0.72rem;
  color: rgba(255, 255, 255, 0.70);
}

/* ─── Main content layout — was inline on <main> ─── */
.site-main {
  min-height: calc(100vh - 80px);
  display: flex;
  flex-direction: column;
}

/* ─── Hero section — was inline on the intro <section> ─── */
.hero-section {
  padding: 3rem 1.5rem 1.5rem;
  text-align: center;
}
.hero-heading {
  font-size: clamp(2rem, 5vw, 3.5rem);
  letter-spacing: -0.03em;
  line-height: 1.1;
  margin: 0;
}
.hero-tagline {
  font-size: 1rem;
  line-height: 1.7;
  color: rgba(255, 255, 255, 0.70);
  margin: 0.75rem auto 0;
  max-width: 48rem;
}

/* ─── Ring stage perspective — was inline on the ring <section> ─── */
.ring-stage {
  perspective: 1100px;
  margin-top: auto;
}

/* ─── Edit toolbar inner layout (the “Editing tiles” label + buttons row) ─── */
.edit-toolbar-label {
  color: #f97316;
}
.edit-toolbar-actions {
  display: flex;
  gap: 0.75rem;
  align-items: center;
}

/* ─── tile-grid base layout — was inline on the #tile-grid div ─── */
#tile-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 1.5rem;
  max-width: 1100px;
  margin: 0 auto;
  padding: 1.5rem;
}

/* ─── MSAL boot gate: anti-flash + sign-in screen ───
 * While body.auth-pending, hide the app shell so an unauthenticated/denied
 * user never sees the launcher flash. auth-gate.js removes .auth-pending only
 * after MSAL confirms a OneSpot role. The splash also hosts the interactive
 * "Sign in with Microsoft" screen (no SWA auto-redirect anymore). */
body.auth-pending .site-header,
body.auth-pending .site-main {
  visibility: hidden;
}

.auth-splash {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 1.5rem;
  background: linear-gradient(135deg, #0f172a 0%, #0c4a6e 60%, #0e7490 100%);
  color: rgba(255, 255, 255, 0.85);
  font-family: 'Sora', system-ui, sans-serif;
  font-size: 0.95rem;
  letter-spacing: 0.01em;
}

/* Splash is only present/visible during the pending phase. */
body:not(.auth-pending) .auth-splash {
  display: none;
}

/* Three states, toggled by auth-gate.js via the data-state attribute. */
.auth-splash > div { display: none; }
.auth-splash[data-state="checking"] .auth-splash-checking { display: block; }
.auth-splash[data-state="signin"]   .auth-splash-signin   { display: block; }
.auth-splash[data-state="denied"]   .auth-splash-denied   { display: block; }

.auth-splash-title {
  font-family: 'Sora', system-ui, sans-serif;
  font-weight: 700;
  font-size: 1.5rem;
  letter-spacing: -0.02em;
  color: #fff;
  margin: 0 0 0.5rem;
}
.auth-splash-sub {
  margin: 0 0 1.5rem;
  color: rgba(255, 255, 255, 0.7);
  font-size: 0.9rem;
}
.auth-splash #auth-signin-btn[disabled] {
  opacity: 0.6;
  pointer-events: none;
}
.auth-splash-error {
  margin: 1rem auto 0;
  max-width: 32rem;
  color: #fca5a5;
  font-size: 0.8rem;
  line-height: 1.5;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  word-break: break-word;
}
.auth-splash-error[hidden] { display: none; }

/* Role gating: view-only users get no Edit-mode affordance. */
#btn-edit-mode[hidden] {
  display: none !important;
}

/* Audit footer inside the edit-tile modal — appears below the form fields
 * when editing an existing tile, hidden when adding new. */
.form-audit-info {
  margin: 0.5rem 0 0;
  font-size: 0.75rem;
  color: rgba(255, 255, 255, 0.45);
  line-height: 1.5;
}

/* ─── v3.0 Tile health status dot ──────────────────────────────────────────
 * Small dot in the top-right corner of every tile-card. data-status drives
 * color: green = reachable, red = unreachable, muted = skipped (no URL /
 * mixed content / unsupported scheme), pale = checking (initial state).
 *
 * Updated by js/tile-health.js via the [data-tile-status-dot="<id>"] hook.
 * Hidden in edit mode where the trash/pencil controls live in the same
 * corner — see .tile-card[style*="cursor:pointer"] selector below (the
 * inline style is how ring.js marks edit-mode cards).
 * ────────────────────────────────────────────────────────────────────────── */

/* Anchor the absolutely-positioned dot to the tile-card without affecting
 * the existing visual layout. The base .tile-card rule (tailwind-source.css)
 * doesn't set position, so we add it here non-destructively. */
.tile-card { position: relative; }

.tile-status-dot {
  position: absolute;
  top: 0.625rem;
  right: 0.625rem;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.22);
  transition: background-color 200ms ease, box-shadow 200ms ease;
  pointer-events: auto;
  z-index: 1;
}
.tile-status-dot[data-status="up"] {
  background: #22c55e;
  box-shadow: 0 0 6px rgba(34, 197, 94, 0.55);
}
.tile-status-dot[data-status="down"] {
  background: #ef4444;
  box-shadow: 0 0 6px rgba(239, 68, 68, 0.6);
}
.tile-status-dot[data-status="skipped"] {
  background: rgba(255, 255, 255, 0.18);
}
.tile-status-dot[data-status="checking"] {
  background: rgba(255, 255, 255, 0.28);
  animation: tile-status-pulse 1.4s ease-in-out infinite;
}
@keyframes tile-status-pulse {
  0%, 100% { opacity: 0.6; }
  50%      { opacity: 1; }
}

/* Hide the dot in edit mode so it doesn't collide with the pencil/trash
 * controls in the same corner. .tile-edit-controls is only rendered when
 * editMode=true (ring.js renderTiles). */
.tile-card:has(.tile-edit-controls) .tile-status-dot { display: none; }

/* ─── v3.1 Mobile responsive pass ─────────────────────────────────────────
 * The 3D ring carousel was designed for desktop viewports — at <768px the
 * side tiles clip off the edge, the focused tile is undersized, and the
 * carousel arrows are too small for a touch target. Below the tablet
 * breakpoint we force grid view (which was already responsive at any
 * viewport via repeat(auto-fit, minmax(280px, 1fr))) and hide the ring
 * view-toggle button so the user can't opt back into the broken state.
 * ────────────────────────────────────────────────────────────────────── */

/* Header layout — single flex row that wraps cleanly on narrow viewports. */
.site-header__row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}
.site-header__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 0.75rem;
}

/* Tablet and below: ring view replaced with grid */
@media (max-width: 767px) {
  /* Hide ring + arrows + the Ring/Grid toggle — grid is the only option. */
  #ring-stage { min-height: 0 !important; height: auto !important; }
  #ring-container,
  .ring-arrow,
  #btn-view-toggle { display: none !important; }
  /* Force grid visible. */
  #tile-grid { display: grid !important; }

  /* Single column on phones; the auto-fit grid-template handles two
   * columns once the viewport can fit two minmax(280px,1fr) tracks. */
  #tile-grid { grid-template-columns: 1fr; padding: 1rem; gap: 1rem; }

  /* Hero block tightens to give the grid more vertical real estate. */
  .hero-section { padding-left: 1rem; padding-right: 1rem; }
  .hero-heading { font-size: clamp(1.8rem, 7vw, 2.6rem); }
  .hero-tagline { font-size: 0.95rem; }

  /* Tile-card touch targets — bump the icon-ghost (edit/delete) buttons
   * inside edit-mode controls to 44x44 minimum. */
  .btn-icon-ghost { width: 2.75rem; height: 2.75rem; }
  .btn-icon-ghost.btn-sm { width: 2.5rem; height: 2.5rem; }
}

/* All viewports: bump the ring arrows to 44x44 minimum touch target. */
.ring-arrow.btn-icon-ghost { width: 2.75rem; height: 2.75rem; }
