/* ==========================================================================
   Howfast Heartbeat — styles.css (full, detailed, quality-ratings ready)
   --------------------------------------------------------------------------
   • Smooth glass aesthetic, light and dark themes
   • Fullscreen canvas with overlays, axis titles, legend
   • Metrics grid for: Final average, Idle Latency, Download Latency, Jitter
   • Environment grid
   • Quality Ratings grid with 5-star indicators and (i) tooltips
   • Robust mobile behaviour and accessibility
   ========================================================================== */


/* ---------- THEME TOKENS ---------- */
:root{
  /* Surfaces & text */
  --bg: radial-gradient(120% 120% at 50% 0%, #f6fbff 0%, #eef5ff 55%, #eaf0ff 100%);
  --panel: rgba(255,255,255,.76);
  --card: rgba(255,255,255,.85);
  --ink: #0b1020;
  --muted: #4d5a78;
  --border: #d8e4ff;
  --shadow: 0 16px 44px rgba(16,38,84,.18);
  --glass: blur(10px);

  /* Accents */
  --accent: #00c2a8;    /* throughput line and primary CTA */
  --accent-2: #7c63ff;  /* EMA line and jitter bars */
  --ok: #18c37a;
  --warn: #ffb600;
  --bad: #ff5d72;

  /* Axis tint */
  --axis: #a9b9d8;

  /* Stars */
  --star-empty: #d7e0f5;
  --star-full:  #00c2a8;
  --star-warn:  #ffb600;
  --star-bad:   #ff5d72;
}

html[data-theme="dark"]{
  --bg: radial-gradient(120% 120% at 50% 0%, #151a2b 0%, #0f1426 55%, #0a0f20 100%);
  --panel: rgba(20,26,44,.78);
  --card: rgba(16,22,40,.84);
  --ink: #eaf2ff;
  --muted: #9cadcf;
  --border: #2a3560;
  --shadow: 0 18px 56px rgba(0,0,0,.5);
  --glass: blur(12px);

  --accent: #79ffe3;
  --accent-2: #b0a0ff;

  --ok: #7af1a8;
  --warn: #ffe08a;
  --bad: #ff8ca3;

  --axis: #4e5c7d;

  --star-empty: #3b476a;
  --star-full:  #79ffe3;
  --star-warn:  #ffe08a;
  --star-bad:   #ff8ca3;
}


/* ---------- BASE ---------- */
*{ box-sizing: border-box; }
html,body{ height:100%; }
body{
  margin:0;
  font: 16px/1.46 system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif;
  color: var(--ink);
  background: var(--bg);
  min-height: 100dvh;
  display:flex;
}
.app{ display:flex; flex-direction:column; flex:1; }
.muted{ color: var(--muted); }
:focus-visible{ outline:2px solid var(--accent-2); outline-offset:3px; border-radius:8px; }

@media (prefers-reduced-motion: reduce){
  *{ animation-duration:.001ms !important; animation-iteration-count:1 !important; transition-duration:.001ms !important; }
}


/* ---------- HEADER ---------- */
header{
  display:flex; align-items:center; justify-content:space-between;
  padding: 12px clamp(12px, 2vw, 18px);
}
.brand{ display:flex; align-items:center; gap:10px; }
.logo{
  width:36px; height:36px; border-radius:12px; position:relative; box-shadow: var(--shadow);
  background: conic-gradient(from 0deg,#78ffe6,#7db1ff,#c19aff,#78ffe6);
  animation: spin 4s linear infinite;
}
.logo::after{ content:""; position:absolute; inset:4px; border-radius:9px; background:#fff2; }
.title{ font-weight:850; letter-spacing:.35px; }
.subtitle{ font-size:12px; color:var(--muted); }

.actions{ display:flex; gap:10px; flex-wrap:wrap; align-items:center; }

/* Buttons */
button{
  appearance:none; cursor:pointer; border-radius:12px;
  border:1px solid var(--border); background: var(--panel); color: var(--ink);
  padding:10px 14px; font-weight:800; box-shadow:var(--shadow); backdrop-filter: var(--glass);
  transition: transform .18s ease, background .18s ease, color .18s ease, opacity .18s ease;
}
button:disabled{ opacity:.6; cursor:not-allowed; }
button:not(:disabled):hover{ transform: translateY(-1px); }
button.primary{ background: linear-gradient(135deg, var(--accent), var(--accent-2)); border:0; color:#0d1020; }

/* Throb animation while idle */
.throb{ animation: throb 1.2s ease-in-out infinite; }
@keyframes spin{ to{ transform: rotate(360deg); } }
@keyframes throb{ 0%{transform:scale(1)} 50%{transform:scale(1.05)} 100%{transform:scale(1)} }


/* Mode selector */
#modeSel{
  appearance:none;
  border-radius:12px; border:1px solid var(--border);
  background: var(--panel); color: var(--ink);
  box-shadow: var(--shadow); backdrop-filter: var(--glass);
  font-weight:800; padding:10px 14px; cursor:pointer;
}
#modeSel:disabled{ opacity:.6; cursor:not-allowed; }


/* ---------- STAGE (canvas + overlays) ---------- */
.stage{
  flex:1; min-height:0; display:grid; grid-template-rows: 1fr auto; gap:10px;
  padding: 8px clamp(10px,2vw,16px) 12px;
}

/* Graph container */
.canvasWrap{
  position:relative; overflow:hidden;
  border-radius:18px; border:1px solid var(--border);
  background: var(--card); backdrop-filter: var(--glass);
  box-shadow: var(--shadow);
  min-height: 360px;
}
@media (max-width: 400px){
  .canvasWrap{ min-height: 320px; }
}
canvas{ display:block; width:100%; height:100%; }

/* Soft grid tint over canvas */
.canvasWrap::after{
  content:""; position:absolute; inset:0; pointer-events:none;
  background: repeating-linear-gradient(
    to bottom,
    transparent 0,
    transparent calc(25% - 1px),
    rgba(0,0,0,.04) calc(25% - 1px),
    rgba(0,0,0,.04) 25%
  );
  mix-blend-mode: soft-light;
  opacity:.08;
}

/* Overlay host */
.overlay{ position:absolute; inset:0; }

/* Status chip (top-left) */
.statusChip{
  position:absolute; top:10px; left:12px;
  display:flex; align-items:center; gap:8px;
  background: var(--panel); border: 1px solid var(--border); border-radius: 10px;
  padding:6px 10px; font-size:13px; z-index:5; box-shadow: var(--shadow); backdrop-filter: var(--glass);
}
.statusIcon{ width:16px; height:16px; display:inline-flex; align-items:center; justify-content:center; }
.smallSpinner{
  width:14px; height:14px; border-radius:50%;
  background: conic-gradient(#0000 10%, var(--accent));
  -webkit-mask: radial-gradient(farthest-side, #0000 55%, #000 56%);
          mask: radial-gradient(farthest-side, #0000 55%, #000 56%);
  animation: spin 1s linear infinite;
}
.tick{
  width:16px; height:16px; border-radius:50%;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  position:relative;
}
.tick::after{
  content:""; position:absolute; left:4px; top:3px; width:8px; height:5px;
  border:2px solid var(--ink); border-top:none; border-right:none; transform: rotate(-45deg);
}

/* Center overlays */
.center{
  position:absolute; inset:0; display:grid; place-items:center;
  transition: opacity .35s ease, transform .35s ease; pointer-events:none;
}
.startWrap,.warm{
  display:grid; place-items:center; gap:14px; text-align:center;
  min-width: min(92%, 460px);
  background: var(--panel); border:1px solid var(--border); border-radius:16px;
  padding: 26px 22px; box-shadow: var(--shadow); backdrop-filter: var(--glass);
}
.startBtn{
  pointer-events:auto; border:0; border-radius:14px;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  color:#0b0f16; font-weight:900; font-size:20px; padding:18px 28px; box-shadow: var(--shadow);
}
.ringSpinner{
  width:64px; height:64px; border-radius:50%;
  background: conic-gradient(#0000 10%, var(--accent));
  -webkit-mask: radial-gradient(farthest-side,#0000 52%,#000 54%);
          mask: radial-gradient(farthest-side,#0000 52%,#000 54%);
  animation: spin 1s linear infinite;
}

/* Big live number */
.big{
  text-align:center; line-height:1; letter-spacing:.6px;
  text-shadow: 0 8px 30px rgba(0,0,0,.14), 0 0 40px rgba(123,107,255,.25);
  pointer-events:none;
}
.big .value{ font-weight:900; font-size: clamp(56px, 16vw, 210px); }
.big .unit { font-size: clamp(18px, 3vw, 36px); opacity:.9; margin-left:.25em; }
.beat{ animation: beat .9s ease-in-out infinite; }
@keyframes beat{ 0%,100%{transform:scale(1)} 50%{transform:scale(1.06)} }

/* Tip */
.hint{
  position:absolute; left:50%; transform:translateX(-50%);
  bottom:40px; font-size:13px; padding:6px 10px; border-radius:10px;
  border:1px solid var(--border); background: var(--panel);
  box-shadow: var(--shadow); backdrop-filter: var(--glass); z-index:4;
}


/* ---------- LEGEND ---------- */
.legend{
  position:absolute; top:10px; right:12px; z-index:5;
  display:flex; gap:10px; flex-wrap:wrap;
  background: var(--panel); border:1px solid var(--border);
  padding:6px 10px; border-radius:10px; box-shadow: var(--shadow); backdrop-filter: var(--glass);
  font-size:12px;
}
.legend .item{ display:flex; align-items:center; gap:6px; white-space:nowrap; }
.legend .sw{ width:10px; height:10px; border-radius:2px; box-shadow: inset 0 0 0 1px rgba(0,0,0,.12); }
.legend .sw.teal{   background: var(--accent); }
.legend .sw.purple{ background: var(--accent-2); } /* jitter bars and EMA are purple */


/* ---------- AXIS TITLES (overlay, interactive i) ---------- */
.axisTitleL,
.axisTitleR,
.axisTitleB{
  z-index:6;
}
.axisTitleL .info,
.axisTitleR .info,
.axisTitleB .info{ pointer-events:auto; }


/* ---------- METRICS GRID ---------- */
.bar{
  display:grid; gap:10px; margin-top:10px;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}
.metric{
  background: var(--panel); border:1px solid var(--border); border-radius:12px;
  padding:12px 14px; min-height:68px;
  display:flex; flex-direction:column; justify-content:center;
  box-shadow: var(--shadow); backdrop-filter: var(--glass);
}
.metric h4{
  margin:0 0 4px 0; font-size:11px; letter-spacing:.6px; text-transform:uppercase;
  color: var(--muted); display:flex; align-items:center; gap:.35rem;
}
.metric p{ margin:0; font-size:18px; font-weight:850; }
.ghost{ opacity:.58; }
.ok{ color: var(--ok); }
.warn{ color: var(--warn); }
.bad{ color: var(--bad); }


/* ---------- QUALITY RATINGS GRID ---------- */
.qualities{
  margin-top:12px;
  display:grid; gap:10px;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}
.quality{
  background: var(--panel); border:1px solid var(--border); border-radius:12px;
  padding:12px 14px; display:flex; flex-direction:column; gap:6px;
  box-shadow: var(--shadow); backdrop-filter: var(--glass);
}
.quality .title{
  margin:0; font-size:12px; letter-spacing:.5px; text-transform:uppercase;
  color: var(--muted); display:flex; align-items:center; gap:.35rem; font-weight:700;
}
.quality .scoreRow{
  display:flex; align-items:center; justify-content:space-between; gap:10px;
}
.quality .verdict{
  font-weight:900; font-size:16px; color: var(--ink);
}

/* Star bar
   - Use CSS variable --val from 0 to 5 to control fill width
   - Add .warn or .bad to recolour when needed
*/
.stars{
  --val: 0; /* 0..5 */
  --w: 110px; --h: 20px;
  width: var(--w); height: var(--h); position:relative; display:inline-block;
  background:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='110' height='20' viewBox='0 0 110 20'><g fill='%23d7e0f5'><path d='M10 1.5l2.7 5.4 5.9.9-4.3 4.2 1 5.9L10 15.6 4.7 18l1-5.9L1.4 7.8l5.9-.9z'/><use x='22' y='0' href='%23s'/><use x='44' y='0' href='%23s'/><use x='66' y='0' href='%23s'/><use x='88' y='0' href='%23s'/></g><defs><path id='s' d='M10 1.5l2.7 5.4 5.9.9-4.3 4.2 1 5.9L10 15.6 4.7 18l1-5.9L1.4 7.8l5.9-.9z'/></defs></svg>")
    left center / var(--w) var(--h) no-repeat;
  border-radius:6px;
}
.stars::after{
  content:"";
  position:absolute; inset:0; width: calc((var(--val) / 5) * 100%);
  background:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='110' height='20' viewBox='0 0 110 20'><g fill='%2300c2a8'><path d='M10 1.5l2.7 5.4 5.9.9-4.3 4.2 1 5.9L10 15.6 4.7 18l1-5.9L1.4 7.8l5.9-.9z'/><use x='22' y='0' href='%23s'/><use x='44' y='0' href='%23s'/><use x='66' y='0' href='%23s'/><use x='88' y='0' href='%23s'/></g><defs><path id='s' d='M10 1.5l2.7 5.4 5.9.9-4.3 4.2 1 5.9L10 15.6 4.7 18l1-5.9L1.4 7.8l5.9-.9z'/></defs></svg>")
    left center / var(--w) var(--h) no-repeat;
  border-radius:6px;
}
.stars.warn::after{
  background:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='110' height='20' viewBox='0 0 110 20'><g fill='%23ffb600'><path d='M10 1.5l2.7 5.4 5.9.9-4.3 4.2 1 5.9L10 15.6 4.7 18l1-5.9L1.4 7.8l5.9-.9z'/><use x='22' y='0' href='%23s'/><use x='44' y='0' href='%23s'/><use x='66' y='0' href='%23s'/><use x='88' y='0' href='%23s'/></g><defs><path id='s' d='M10 1.5l2.7 5.4 5.9.9-4.3 4.2 1 5.9L10 15.6 4.7 18l1-5.9L1.4 7.8l5.9-.9z'/></defs></svg>")
    left center / var(--w) var(--h) no-repeat;
}
.stars.bad::after{
  background:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='110' height='20' viewBox='0 0 110 20'><g fill='%23ff5d72'><path d='M10 1.5l2.7 5.4 5.9.9-4.3 4.2 1 5.9L10 15.6 4.7 18l1-5.9L1.4 7.8l5.9-.9z'/><use x='22' y='0' href='%23s'/><use x='44' y='0' href='%23s'/><use x='66' y='0' href='%23s'/><use x='88' y='0' href='%23s'/></g><defs><path id='s' d='M10 1.5l2.7 5.4 5.9.9-4.3 4.2 1 5.9L10 15.6 4.7 18l1-5.9L1.4 7.8l5.9-.9z'/></defs></svg>")
    left center / var(--w) var(--h) no-repeat;
}


/* ---------- (i) INFO TOOLTIPS ---------- */
/* CSS fallback; JS upgrades to floating #hf-tooltip that clamps in viewport */
.info{
  display:inline-flex; align-items:center; justify-content:center;
  width:1.15em; height:1.15em; border-radius:50%;
  border:1.5px solid var(--muted); color:var(--muted);
  font-size:.85em; font-weight:900; cursor:help; position:relative; line-height:1;
  user-select:none;
}
.info:hover, .info:focus-visible{ border-color: var(--ink); color: var(--ink); }
.info::after{
  content: attr(data-tip);
  position:absolute; bottom:155%; left:50%; transform:translateX(-50%);
  background: var(--panel); color: var(--ink); border:1px solid var(--border);
  padding:.55rem .65rem; border-radius:8px; width: min(300px, 80vw);
  box-shadow: var(--shadow); white-space: normal; line-height:1.35;
  opacity:0; pointer-events:none; transition: opacity .15s ease;
  z-index:50;
}
.info::before{
  content:""; position:absolute; bottom: calc(155% - 4px); left:50%; transform: translateX(-50%) rotate(45deg);
  width:10px; height:10px; background: var(--panel);
  border-left:1px solid var(--border); border-bottom:1px solid var(--border);
  opacity:0; transition: opacity .15s ease; z-index:49;
}
.info:hover::after, .info:focus::after, .info:focus-visible::after,
.info:hover::before, .info:focus::before, .info:focus-visible::before{ opacity:1; }

/* JS sets data-no-css-tip on .info while showing #hf-tooltip. Hide pseudo tips. */
.info[data-no-css-tip]::after,
.info[data-no-css-tip]::before{ display:none !important; }

/* Floating tooltip element created by JS */
#hf-tooltip{
  position:fixed; z-index:9999; max-width:320px;
  background: var(--panel); color: var(--ink); border:1px solid var(--border);
  padding:8px 10px; border-radius:8px; box-shadow: var(--shadow);
  line-height:1.35; display:none; pointer-events:none;
  transition: opacity .12s ease, transform .12s ease;
}


/* ---------- FOOTER ---------- */
footer{ text-align:center; font-size:.86rem; color: var(--muted); padding: 8px 12px 16px; }


/* ---------- RESPONSIVE ---------- */
@media (max-width: 1024px){
  .bar, .qualities{ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
}
@media (max-width: 860px){
  .subtitle{ display:none; }
  .legend{ font-size:11px; }
}
@media (max-width: 640px){
  header{ padding: 10px 12px; }
  .startWrap,.warm{ min-width:min(96%, 420px); padding:22px 18px; }
  .metric p{ font-size:17px; }
}

/* iOS safe areas */
@supports (padding: max(0px)){
  header{ padding-left:max(12px, env(safe-area-inset-left)); padding-right:max(12px, env(safe-area-inset-right)); }
  .stage{  padding-left:max(10px, env(safe-area-inset-left)); padding-right:max(10px, env(safe-area-inset-right)); }
  footer{  padding-left:max(12px, env(safe-area-inset-left)); padding-right:max(12px, env(safe-area-inset-right)); }
}

/* ===== Mobile enhancements (non-destructive) ===== */

/* Compact header and controls on narrow screens */
@media (max-width: 480px){
  header{ padding: 8px 10px; gap: 6px; }
  .actions{ gap: 6px; }
  button, #modeSel{ padding: 8px 10px; font-weight: 800; }
  .title{ font-size: 16px; }
  .subtitle{ display:none; }
}

/* Stage and canvas: more room for the graph, softer padding */
@media (max-width: 480px){
  .stage{
    grid-template-rows: 1fr auto;
    gap: 8px;
    padding: 6px 8px 10px;
  }
  .canvasWrap{
    min-height: 280px;               /* was 360; JS will also adapt height */
    border-radius: 14px;
  }
  .legend{
    font-size: 10px;
    top: 8px; right: 8px;
    padding: 4px 6px;
    gap: 6px;
  }
  .axisTitleL,.axisTitleR,.axisTitleB{
    font-size: 10px;
  }
  .hint{ bottom: 16px; font-size: 12px; padding: 5px 8px; }
}

/* Metric cards: stack to one column for true mobile, two columns for phablets */
@media (max-width: 480px){
  .bar{
    grid-template-columns: 1fr;
    gap: 8px;
    margin-top: 8px;
  }
  .metric{
    padding: 10px 12px;
    min-height: 56px;
  }
  .metric h4{ font-size: 10px; }
  .metric p{ font-size: 17px; }
}
@media (min-width: 481px) and (max-width: 768px){
  .bar{ grid-template-columns: repeat(2, minmax(0,1fr)); }
}

/* Quality ratings: make a horizontal snap carousel on small screens */
@media (max-width: 640px){
  .qualities{
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 85%;
    overflow-x: auto;
    gap: 10px;
    padding-bottom: 2px;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
  }
  .quality{
    scroll-snap-align: start;
    min-width: 0;                    /* prevent overflow jitter */
  }
}

/* Make tooltips never clash with the bottom hint on tiny screens */
@media (max-width: 480px){
  .axisTitleB{ z-index: 7; }
  .hint{ z-index: 6; }
}

/* Slightly softer canvas overlay grid on mobile */
@media (max-width: 480px){
  .canvasWrap::after{ opacity: .05; }   /* was .08 */
}

/* ===== Footer visibility fix ===== */

/* Ensure layout gives the footer some space to breathe */
.stage{
  overflow: visible;                 /* let content flow past, not clip */
  padding-bottom: clamp(16px, 4vh, 36px);
}

/* Add a little gap after the last card grid before the footer */
.bar:last-of-type{
  margin-bottom: clamp(12px, 3vh, 32px);
}

/* Keep the footer above neighbouring shadows/backdrop-filter layers */
footer{
  position: relative;
  z-index: 10;                       /* higher than cards and overlays */
  margin-top: 6px;
}

/* On very small screens give it a touch more space */
@media (max-width: 480px){
  .stage{ padding-bottom: clamp(20px, 6vh, 48px); }
  .bar:last-of-type{ margin-bottom: clamp(16px, 5vh, 40px); }
}

/* ===== Footer placement hardening ===== */

/* Make the page a true column layout: content grows, footer sits after it */
.app{
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}
.stage{
  flex: 1;                 /* stage grows to fill, keeps footer beneath */
  overflow: visible;
}

/* Ensure the last grid leaves breathing room before the footer */
.bar:last-of-type{
  margin-bottom: clamp(16px, 5vh, 56px);
}
.bar:last-of-type::after{
  content: "";
  display: block;
  height: clamp(16px, 4vh, 48px);   /* spacer to defeat any shadow overlap */
}

/* Footer sits in normal flow (not layered), and clears any floats */
footer{
  position: static !important;
  z-index: auto !important;
  clear: both;
  margin-top: clamp(12px, 3vh, 36px);
  padding-top: 8px;
}

/* On very small screens give a touch more space */
@media (max-width: 480px){
  .bar:last-of-type{ margin-bottom: clamp(20px, 6vh, 64px); }
  .bar:last-of-type::after{ height: clamp(20px, 6vh, 64px); }
}
