/* ==========================================================================
   MAR. Analytics — dashboard layer.
   Sits on top of mar.css and only adds what a dashboard needs. Every colour,
   type step, space and easing below reads from the tokens defined there, so a
   change to the brand propagates here without edits.
   Mobile-first throughout: single column by default, grids only past 720px.
   ========================================================================== */

/* --- 1. State colours ---------------------------------------------------
   The palette has one accent and one alarm; a dashboard needs a four-step
   scale. These are tuned to sit beside oxblood without turning the page into a
   traffic light — desaturated, editorial, and contrast-checked on both grounds. */

:root,
:root[data-theme="light"] {
  --good:      #2F6D4F;
  --good-soft: color-mix(in srgb, #2F6D4F 12%, transparent);
  --warn:      #9A6B12;
  --warn-soft: color-mix(in srgb, #9A6B12 13%, transparent);
  --bad:       var(--oxblood);
  --bad-soft:  color-mix(in srgb, var(--oxblood) 12%, transparent);
  --crit:      var(--signal);
  --crit-soft: color-mix(in srgb, var(--signal) 13%, transparent);
}

:root[data-theme="dark"] {
  --good:      #6BC79A;
  --good-soft: color-mix(in srgb, #6BC79A 16%, transparent);
  --warn:      #E0B252;
  --warn-soft: color-mix(in srgb, #E0B252 16%, transparent);
  --bad:       var(--rose);
  --bad-soft:  color-mix(in srgb, var(--rose) 16%, transparent);
  --crit:      #FF6B6B;
  --crit-soft: color-mix(in srgb, #FF6B6B 16%, transparent);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --good:      #6BC79A;
    --good-soft: color-mix(in srgb, #6BC79A 16%, transparent);
    --warn:      #E0B252;
    --warn-soft: color-mix(in srgb, #E0B252 16%, transparent);
    --bad:       var(--rose);
    --bad-soft:  color-mix(in srgb, var(--rose) 16%, transparent);
    --crit:      #FF6B6B;
    --crit-soft: color-mix(in srgb, #FF6B6B 16%, transparent);
  }
}

.is-good     { --state: var(--good); --state-soft: var(--good-soft); }
.is-warn     { --state: var(--warn); --state-soft: var(--warn-soft); }
.is-bad      { --state: var(--bad);  --state-soft: var(--bad-soft);  }
.is-critical { --state: var(--crit); --state-soft: var(--crit-soft); }

/* --- 1b. Reveal marker --------------------------------------------------
   mar.css drives its reveal system off the .reveal class. This app marks
   dynamically rendered nodes with [data-reveal] instead, so that mar.js's
   load-time pass ignores them and motion.js owns them — but the visual result
   must be identical, so the attribute gets the same states here. */

.anim [data-reveal] {
  opacity: 0;
  transform: translate3d(0, 18px, 0);
  transition:
    opacity var(--t-4) var(--e-out) var(--reveal-delay, 0ms),
    transform var(--t-4) var(--e-out) var(--reveal-delay, 0ms);
}
.anim [data-reveal].is-in { opacity: 1; transform: none; }

/* The chart primitives in mar.css key their draw-on off `.reveal.is-in`.
   Give the attribute the same reach so gauges and bars actually fill. */
.anim [data-reveal].is-in .gauge-fill { stroke-dashoffset: var(--offset); }
.anim [data-reveal].is-in .gauge-marker { opacity: 1; transform: scale(1); }
.anim [data-reveal].is-in .spark i,
.anim [data-reveal].is-in .bars i { transform: scaleY(1); }

/* --- 2. App chrome ------------------------------------------------------ */

/* The viewport is viewport-fit=cover, so on a notched device the layout runs
   edge to edge. Every fixed top surface has to pay the inset back, or its first
   row sits under the status bar where it cannot be tapped. Resolves to 0 where
   there is no inset, so this is safe everywhere. */
:root { --top-inset: env(safe-area-inset-top, 0px); }

.app-header { --header-pad: var(--s-3); padding-top: var(--top-inset); }
.app-header .nav { gap: var(--s-3); align-items: center; }
.app-header .brand { flex: 0 0 auto; }
.app-header .brand img { width: 78px; height: auto; }

.client-chip {
  flex: 1 1 auto;
  min-width: 0;
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fg-muted);
  padding-left: var(--s-3);
  border-left: 1px solid var(--rule);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.app-header .nav-actions { flex: 0 0 auto; gap: var(--s-2); }

.ghost-link {
  display: inline-flex; align-items: center; gap: var(--s-2);
  font-size: var(--step--2); letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--fg-muted); text-decoration: none;
  transition: color var(--t-1) var(--e-out);
}
.ghost-link:hover { color: var(--accent); }
@media (max-width: 599px) { .ghost-link span { display: none; } }

/* Section tabs. A horizontal scroller, not a burger: on a dashboard the
   sections ARE the navigation, and burying them costs a tap every single time. */
.tabnav {
  border-top: 1px solid var(--rule);
  background: var(--header-veil);
  backdrop-filter: saturate(140%) blur(12px);
}
.tabnav-track {
  display: flex; gap: var(--s-5);
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  scroll-snap-type: x proximity;
}
.tabnav-track::-webkit-scrollbar { display: none; }

/* A hard clip reads as a layout bug; a fade reads as "there is more here".
   Masking the track fades the content itself, so it works on any ground —
   a painted gradient would show as a stray rectangle over the bone. */
.tabnav-track {
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 40px), transparent);
  mask-image: linear-gradient(to right, #000 calc(100% - 40px), transparent);
}
@media (min-width: 720px) {
  .tabnav-track { -webkit-mask-image: none; mask-image: none; }
}

.tab {
  position: relative;
  flex: 0 0 auto;
  scroll-snap-align: center;
  padding: var(--s-3) 0;
  font-size: var(--step--2);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--fg-faint);
  text-decoration: none;
  white-space: nowrap;
  transition: color var(--t-2) var(--e-out);
}
.tab::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 2px;
  background: var(--accent);
  transform: scaleX(0); transform-origin: left;
  transition: transform var(--t-2) var(--e-out);
}
.tab.is-active { color: var(--fg); }
.tab.is-active::after { transform: scaleX(1); }

/* --- 3. Page rhythm ----------------------------------------------------- */

/* The header and tab bar are sticky, so an anchor jump would otherwise land
   the section title underneath them. */
#resumen, #vfactor, #videos, #competencia, #duracion {
  scroll-margin-top: clamp(112px, 26vw, 168px);
}

.dash-hero {
  position: relative;
  /* Clears the brand row plus the section-tab row. Both are sticky, so this is
     a fixed offset rather than a margin that would collapse under the header. */
  padding-top: calc(clamp(150px, 34vw, 210px) + var(--top-inset));
  padding-bottom: var(--s-6);
}
.dash-hero.is-admin { padding-top: calc(clamp(112px, 26vw, 170px) + var(--top-inset)); }

/* Under reduced motion the header grows by the opt-in banner; reserve exactly
   the height it reports (motion.js publishes --banner-h). */
@media (prefers-reduced-motion: reduce) {
  .dash-hero { padding-top: calc(clamp(150px, 34vw, 210px) + var(--banner-h, 38px) + var(--top-inset)); }
  .dash-hero.is-admin { padding-top: calc(clamp(112px, 26vw, 170px) + var(--banner-h, 38px) + var(--top-inset)); }
  .login { padding-top: calc(clamp(110px, 24vw, 180px) + var(--banner-h, 38px) + var(--top-inset)); }
  #resumen, #vfactor, #videos, #competencia, #duracion {
    scroll-margin-top: calc(clamp(112px, 26vw, 168px) + var(--banner-h, 38px) + var(--top-inset));
  }
}

.hero-title { margin-block: var(--s-4) var(--s-5); max-width: 16ch; }

.hero-facts {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--s-4) var(--s-5);
  padding-top: var(--s-5);
  border-top: 1px solid var(--rule);
}
.hero-facts dt {
  font-size: var(--step--2); letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--fg-faint);
  margin-bottom: 2px;
}
.hero-facts dd {
  margin: 0;
  font-size: var(--step-2); font-weight: 600;
  letter-spacing: -0.02em; font-variant-numeric: tabular-nums;
}
@media (min-width: 720px) {
  .hero-facts { grid-template-columns: repeat(4, 1fr); gap: var(--s-5); }
}
.hero-facts .is-up { color: var(--good); }
.hero-facts .is-down { color: var(--bad); }

.section { padding-block: clamp(48px, 9vw, 96px); }

/* The alternating dark band, matching the main site's section rhythm. */
.band {
  padding-block: clamp(48px, 9vw, 96px);
  background: var(--ink);
  color: var(--bone);
  --fg: var(--bone);
  --fg-muted: #B7B0A6;
  --fg-faint: #8E877D;
  --surface: var(--ink-raise);
  --accent: var(--rose);
  --rule: rgba(243, 238, 231, 0.14);
  --rule-strong: rgba(243, 238, 231, 0.26);
  --good: #6BC79A; --good-soft: rgba(107, 199, 154, 0.16);
  --warn: #E0B252; --warn-soft: rgba(224, 178, 82, 0.16);
  --bad:  #C9707A; --bad-soft:  rgba(201, 112, 122, 0.16);
  --crit: #FF6B6B; --crit-soft: rgba(255, 107, 107, 0.16);
}
.band .metric span, .band .metric small { color: var(--fg-muted); }

/* Section headings in the Didone, body text in Inter.
   The hero H1 deliberately stays Inter with a Didone accent word — that
   contrast is the site's signature, and setting the whole line in serif kills
   the accent it depends on. Serif is for the section titles below it. */
.section-title {
  max-width: 20ch;
  font-family: var(--font-display);
  font-weight: 500;
  font-variation-settings: "opsz" 40;
  letter-spacing: -0.012em;
  line-height: 1.08;
}
.section-title.sm {
  font-size: var(--step-2);
  font-variation-settings: "opsz" 22;
  margin-bottom: var(--s-4);
}
.ir-body h2, .viz-head h3 {
  font-family: var(--font-display);
  font-weight: 500;
  font-variation-settings: "opsz" 22;
  letter-spacing: -0.01em;
}

.section-lead {
  max-width: var(--measure);
  color: var(--fg-muted);
  margin-bottom: var(--s-6);
}
.section-note {
  margin-top: var(--s-4);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.06em;
  color: var(--fg-faint);
}

.section-head { margin-bottom: var(--s-6); grid-template-columns: minmax(0, 1fr); }
@media (min-width: 720px) {
  .section-head {
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: end;
  }
}

/* Nothing may widen the document. A horizontal scroller must scroll INSIDE its
   own box — min-width:0 is what actually allows that in a grid or flex child. */
.shell { overflow-x: clip; }
.switch, .tabnav-track, .hbars, .viz, .comp, .stackbar { min-width: 0; }

/* --- 4. Interest Ratio card --------------------------------------------- */

.ir-card { margin-bottom: var(--s-6); }
@media (min-width: 860px) {
  .ir-card { grid-template-columns: minmax(240px, 320px) 1fr; align-items: center; gap: var(--s-7); }
}

.ir-gauge { display: grid; justify-items: center; gap: var(--s-3); }
.ir-gauge .gauge { width: 100%; max-width: 300px; }
.gauge.is-good, .gauge.is-warn, .gauge.is-bad, .gauge.is-critical { --accent: var(--state); }
.gauge-unit { font-size: 20px; fill: var(--fg-faint); }

.ir-state {
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--state, var(--accent));
}

.ir-body h2 { font-size: var(--step-3); margin-bottom: var(--s-3); }
.ir-explain { color: var(--fg-muted); max-width: 46ch; margin-bottom: var(--s-5); }

.ir-legend { list-style: none; margin: 0; padding: 0; display: grid; gap: 1px; background: var(--rule); }
.ir-legend li {
  display: grid;
  grid-template-columns: 10px 5.5em 1fr;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-2);
  background: var(--surface);
  font-size: var(--step--1);
  color: var(--fg-muted);
  transition: background var(--t-2) var(--e-out);
}
.ir-legend li i { width: 10px; height: 10px; background: var(--state); }
.ir-legend li b { font-family: var(--font-mono); font-weight: 500; font-variant-numeric: tabular-nums; color: var(--fg); }
.ir-legend li.is-current { background: var(--state-soft); }
.ir-legend li.is-current span { color: var(--fg); }

/* --- 5. Metric grid ----------------------------------------------------- */

.metric-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1px;
  background: var(--rule);
  border-block: 1px solid var(--rule);
}
.metric-grid .metric {
  background: var(--bg);
  padding: var(--s-4) var(--s-4) var(--s-5);
  gap: var(--s-1);
}
.band .metric-grid .metric { background: var(--ink); }
@media (min-width: 720px) { .metric-grid { grid-template-columns: repeat(4, 1fr); } }

/* --- 6. V-Factor chart -------------------------------------------------- */

.vchart { margin-top: var(--s-7); }
.vchart-plot {
  border-bottom: 1px solid var(--rule-strong);
}
/* The bars box is the measuring frame: the average line is positioned inside
   it, so a percentage means the same pixels for the line and for every bar. */
.vchart-bars {
  position: relative;
  display: flex; align-items: flex-end; gap: 4px;
  height: clamp(180px, 34vw, 280px);
}

.vbar {
  position: relative;
  flex: 1 1 0;
  min-width: 6px;
  height: 100%;
  display: flex; align-items: flex-end;
  text-decoration: none;
}
.vbar i {
  display: block; width: 100%;
  height: var(--h, 20%);
  background: color-mix(in srgb, var(--fg) 26%, transparent);
  transform-origin: bottom center;
  transition: transform 820ms var(--e-out) var(--d, 0ms), background var(--t-2) var(--e-out);
}
.anim .vbar i { transform: scaleY(0); }
.anim .vchart.is-in .vbar i { transform: scaleY(1); }
.vbar.is-hit i { background: linear-gradient(to top, color-mix(in srgb, var(--good) 40%, transparent), var(--good)); }
.vbar:hover i, .vbar:focus-visible i { background: var(--accent); }
.vbar.is-hit:hover i { background: var(--good); }

.vbar b {
  position: absolute; left: 50%; bottom: calc(var(--h, 20%) + 6px);
  transform: translateX(-50%);
  font-family: var(--font-mono); font-size: 0.58rem; font-weight: 500;
  letter-spacing: 0.02em; white-space: nowrap;
  color: var(--fg-faint);
  opacity: 0; transition: opacity var(--t-1) var(--e-out);
  pointer-events: none;
}
.vbar:hover b, .vbar:focus-visible b { opacity: 1; }
@media (min-width: 900px) { .vbar b { opacity: 0.55; } }

/* The average line. Drawn over the bars, labelled at the left so it reads as a
   threshold rather than as another series. */
.vchart-line {
  position: absolute; left: 0; right: 0; bottom: var(--y, 50%);
  height: 0;
  z-index: 2;
  border-top: 1px dashed var(--accent);
  pointer-events: none;
  transform: scaleX(0); transform-origin: left;
  transition: transform 900ms var(--e-out) 300ms;
}
.anim .vchart.is-in .vchart-line { transform: scaleX(1); }
.vchart-line span {
  position: absolute; left: 0; bottom: 4px;
  font-family: var(--font-mono); font-size: 0.58rem;
  letter-spacing: 0.14em; color: var(--accent);
  background: var(--bg); padding-right: var(--s-2);
}
.band .vchart-line span { background: var(--ink); }

.vchart-axis {
  display: flex; justify-content: space-between;
  margin-top: var(--s-3);
  font-family: var(--font-mono); font-size: 0.6rem;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--fg-faint);
}

/* --- 7. Video cards ----------------------------------------------------- */

.vgrid { display: grid; gap: 1px; background: var(--rule); border-block: 1px solid var(--rule); }
@media (min-width: 640px) { .vgrid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1040px) { .vgrid { grid-template-columns: repeat(3, 1fr); } }

.vlist { display: grid; gap: 1px; background: var(--rule); border-block: 1px solid var(--rule); }

.vcard {
  position: relative;
  display: grid; gap: var(--s-3);
  align-content: start;
  padding: var(--s-4);
  background: var(--bg);
  text-decoration: none;
  color: inherit;
  transition: background var(--t-2) var(--e-out), transform var(--t-2) var(--e-out);
}
.band .vcard { background: var(--ink); }
.vcard::before {
  content: ""; position: absolute; inset: 0 auto 0 0; width: 2px;
  background: var(--accent);
  transform: scaleY(0); transform-origin: bottom;
  transition: transform var(--t-2) var(--e-out);
}
.vcard.is-hit::before { background: var(--good); }
.vcard:hover, .vcard:focus-visible { background: var(--surface); }
.vcard:hover::before, .vcard:focus-visible::before { transform: scaleY(1); }
.vcard:hover .arrow { transform: translate(2px, -2px); }
.vcard .arrow { transition: transform var(--t-1) var(--e-out); }

.vcard-thumb {
  display: block; aspect-ratio: 9 / 16; max-height: 220px;
  overflow: hidden; background: var(--surface);
}
.vcard-thumb img { width: 100%; height: 100%; object-fit: cover; }

.vcard-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); }
.vcard-date {
  font-family: var(--font-mono); font-size: 0.62rem;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--fg-faint);
}

.vcard-caption {
  display: block;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: var(--step-0);
  line-height: 1.35;
  letter-spacing: -0.005em;
  max-width: 34ch;
}

.vcard-stats {
  display: grid; grid-template-columns: repeat(4, 1fr);
  gap: var(--s-2);
  padding-top: var(--s-3);
  border-top: 1px solid var(--rule);
}
.vcard-stats > span { display: grid; gap: 1px; }
.vcard-stats b {
  font-size: var(--step-0); font-weight: 600;
  letter-spacing: -0.02em; font-variant-numeric: tabular-nums;
}
.vcard-stats small {
  font-family: var(--font-mono); font-size: 0.55rem;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--fg-faint);
}

.vcard-foot {
  display: flex; align-items: center; gap: var(--s-3);
  font-family: var(--font-mono); font-size: 0.6rem;
  letter-spacing: 0.08em; color: var(--fg-faint);
}
.vcard-foot .arrow { margin-left: auto; }

/* --- 8. Flags ----------------------------------------------------------- */

.flag {
  flex: 0 0 auto;
  font-family: var(--font-mono); font-size: 0.55rem; font-weight: 500;
  letter-spacing: 0.14em; text-transform: uppercase;
  padding: 3px 7px;
  white-space: nowrap;
}
.flag-good     { color: var(--good); background: var(--good-soft); }
.flag-warn     { color: var(--warn); background: var(--warn-soft); }
.flag-bad      { color: var(--bad);  background: var(--bad-soft);  }
.flag-direct   { color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent); }
.flag-indirect { color: var(--fg-muted); background: color-mix(in srgb, var(--fg) 8%, transparent); }

/* --- 9. Switches (account + sort) --------------------------------------- */

.switch {
  display: flex; gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
  width: fit-content;
  max-width: 100%;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
  mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
}
@media (min-width: 720px) {
  .switch { -webkit-mask-image: none; mask-image: none; }
}
.switch::-webkit-scrollbar { display: none; }
.switch-btn {
  flex: 0 0 auto;
  appearance: none; border: 0; cursor: pointer;
  background: var(--bg);
  color: var(--fg-muted);
  font-family: var(--font-mono); font-size: var(--step--2);
  letter-spacing: 0.12em; text-transform: uppercase;
  padding: var(--s-2) var(--s-4);
  transition: background var(--t-1) var(--e-out), color var(--t-1) var(--e-out);
}
.switch-btn:hover { color: var(--fg); }
.switch-btn.is-on { background: var(--fg); color: var(--bg); }
.band .switch-btn { background: var(--ink-raise); }
.band .switch-btn.is-on { background: var(--bone); color: var(--ink); }

/* --- 10. Horizontal bars ------------------------------------------------ */

.hbars { display: grid; gap: var(--s-3); }
.hbar {
  display: grid;
  grid-template-columns: minmax(0, 8.5em) 1fr auto;
  align-items: center;
  gap: var(--s-3);
  font-size: var(--step--1);
}
.hbar-key {
  color: var(--fg-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.hbar-track { display: block; height: 8px; background: color-mix(in srgb, var(--fg) 8%, transparent); }
.hbar-track i {
  display: block; height: 100%; width: var(--w, 10%);
  background: color-mix(in srgb, var(--fg) 30%, transparent);
  transform: scaleX(0); transform-origin: left;
  transition: transform 760ms var(--e-out) var(--d, 0ms);
}
.anim .hbar-track i { transform: scaleX(0); }
.anim .is-in .hbar-track i,
.anim [data-reveal].is-in .hbar-track i { transform: scaleX(1); }
.hbar.is-accent i { background: var(--accent); }
.hbar-val {
  font-family: var(--font-mono); font-size: var(--step--2);
  font-variant-numeric: tabular-nums; color: var(--fg);
}
@media (max-width: 479px) {
  .hbar { grid-template-columns: 1fr auto; row-gap: var(--s-1); }
  .hbar-track { grid-column: 1 / -1; }
}

/* --- 11. Competitors ---------------------------------------------------- */

.sov { margin-bottom: var(--s-7); padding: var(--s-5); background: var(--surface); box-shadow: inset 0 0 0 1px var(--rule); }
.sov-label, .comp-label {
  font-family: var(--font-mono); font-size: var(--step--2);
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--fg-faint);
  margin-bottom: var(--s-4);
}
.sov-value { margin-top: var(--s-4); color: var(--fg-muted); font-size: var(--step--1); }
.sov-value b { color: var(--accent); font-variant-numeric: tabular-nums; }

.comp-grid { display: grid; gap: var(--s-5); }
@media (min-width: 900px) { .comp-grid { grid-template-columns: repeat(2, 1fr); } }

.comp {
  display: grid; gap: var(--s-4);
  align-content: start;
  padding: var(--s-5);
  background: var(--surface);
  box-shadow: inset 0 0 0 1px var(--rule);
}
.comp-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s-3); }
.comp-head b { display: block; font-size: var(--step-1); letter-spacing: -0.01em; }
.comp-head small { display: block; font-size: var(--step--2); color: var(--fg-faint); margin-top: 2px; }

.comp-metrics {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--s-3);
  padding-block: var(--s-3);
  border-block: 1px solid var(--rule);
}
.comp-metrics .metric strong { font-size: var(--step-1); }

.comp-delta { font-size: var(--step--1); color: var(--fg-muted); }
.comp-delta b { font-variant-numeric: tabular-nums; }
.comp-delta.is-up b { color: var(--bad); }      /* they are ahead of you */
.comp-delta.is-down b { color: var(--good); }   /* you are ahead */

.comp-ideas { list-style: none; margin: 0; padding: 0; display: grid; gap: 1px; background: var(--rule); }
.comp-ideas a {
  display: grid; gap: var(--s-2);
  padding: var(--s-3) 0 var(--s-4);
  background: var(--surface);
  text-decoration: none; color: inherit;
  transition: opacity var(--t-1) var(--e-out);
}
.comp-ideas a:hover { opacity: 0.72; }
.comp-ideas a:hover .arrow { transform: translate(2px, -2px); }
.idea-caption { font-family: var(--font-body); font-weight: 500; font-size: var(--step--1); line-height: 1.4; }
.idea-stats {
  display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap;
  font-family: var(--font-mono); font-size: 0.6rem;
  letter-spacing: 0.08em; color: var(--fg-faint);
}
.idea-stats b { color: var(--fg); }
.idea-stats .arrow { transition: transform var(--t-1) var(--e-out); }

/* --- 12. Split section -------------------------------------------------- */

.split-cols { display: grid; gap: var(--s-7); }
@media (min-width: 900px) { .split-cols { grid-template-columns: 1fr 1fr; gap: var(--s-8); } }

/* --- 13. Login ---------------------------------------------------------- */

.login {
  min-height: 100svh;
  display: grid; place-items: center;
  padding: calc(clamp(110px, 24vw, 180px) + var(--top-inset)) var(--pad-x) var(--s-8);
}
.login-inner { width: 100%; max-width: 400px; }
.login-title { font-size: var(--step-4); margin-block: var(--s-4) var(--s-4); max-width: 12ch; }
.login-sub { color: var(--fg-muted); margin-bottom: var(--s-7); max-width: 34ch; }

.login-form { display: grid; gap: var(--s-4); }
.field { display: grid; gap: var(--s-2); }
.field > span {
  font-family: var(--font-mono); font-size: var(--step--2);
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--fg-faint);
}
.field input {
  width: 100%;
  font-family: var(--font-body);
  font-size: var(--step-0);          /* 16px+ — anything smaller zooms on iOS */
  color: var(--fg);
  background: transparent;
  border: 0; border-bottom: 1px solid var(--rule-strong);
  border-radius: 0;                  /* iOS rounds inputs by default */
  padding: var(--s-3) 0;
  transition: border-color var(--t-2) var(--e-out);
}
.field input::placeholder { color: var(--fg-faint); opacity: 0.6; }
.field input:focus { outline: none; border-bottom-color: var(--accent); }

.btn-block { width: 100%; justify-content: center; margin-top: var(--s-3); position: relative; }
.btn-spinner {
  position: absolute; inset: 0; margin: auto;
  width: 15px; height: 15px;
  border: 1.5px solid currentColor; border-top-color: transparent;
  border-radius: 50%;
  opacity: 0;
}
.is-busy .btn-label { opacity: 0; }
.is-busy .btn-spinner { opacity: 1; animation: mar-spin 720ms linear infinite; }
@keyframes mar-spin { to { transform: rotate(360deg); } }

.form-error {
  font-size: var(--step--1);
  color: var(--crit);
  padding: var(--s-3);
  background: var(--crit-soft);
}
.login-help { margin-top: var(--s-6); font-size: var(--step--1); color: var(--fg-faint); }

/* --- 14. Admin table ---------------------------------------------------- */

.ctable { display: grid; gap: 1px; background: var(--rule); border-block: 1px solid var(--rule); }
.crow { display: grid; gap: var(--s-4); padding: var(--s-5) 0; background: var(--bg); }
.crow-main { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); }
.crow-name { text-decoration: none; color: inherit; }
.crow-name b { display: block; font-family: var(--font-display); font-weight: 500; font-size: var(--step-2); }
.crow-name small { display: block; font-family: var(--font-mono); font-size: 0.6rem; letter-spacing: 0.06em; color: var(--fg-faint); margin-top: 2px; }
.crow-name:hover b { color: var(--accent); }

.crow-meta { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--s-3) var(--s-5); }
@media (min-width: 720px) { .crow-meta { grid-template-columns: repeat(4, 1fr); } }
.crow-meta dt { font-family: var(--font-mono); font-size: 0.58rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--fg-faint); }
.crow-meta dd { margin: 0; font-size: var(--step--1); }

.crow-actions { display: flex; align-items: center; gap: var(--s-4); flex-wrap: wrap; }

.btn-danger, .btn-quiet {
  appearance: none; cursor: pointer;
  font-family: var(--font-mono); font-size: var(--step--2);
  letter-spacing: 0.12em; text-transform: uppercase;
  padding: var(--s-2) var(--s-4);
  transition: background var(--t-1) var(--e-out), color var(--t-1) var(--e-out);
}
.btn-danger { border: 1px solid var(--crit); background: transparent; color: var(--crit); }
.btn-danger:hover:not(:disabled) { background: var(--crit); color: var(--bone); }
.btn-quiet { border: 1px solid var(--rule-strong); background: transparent; color: var(--fg-muted); }
.btn-quiet:hover:not(:disabled) { background: var(--fg); color: var(--bg); }
.btn-danger:disabled, .btn-quiet:disabled { opacity: 0.5; cursor: wait; }

/* --- 15. Loading + empty ------------------------------------------------ */

.loading {
  min-height: 62svh;
  display: grid; place-content: center; justify-items: center;
  gap: var(--s-4);
  padding: clamp(120px, 26vw, 190px) var(--pad-x) var(--s-8);
  text-align: center;
}
.loading-mark { opacity: 0.85; animation: mar-pulse 1600ms var(--e-inout) infinite; }
@keyframes mar-pulse { 0%, 100% { opacity: 0.35; } 50% { opacity: 1; } }

/* An indeterminate rule rather than a spinner — it matches the site's hairline
   vocabulary and reads as "a measurement is happening". */
.loading-bar { display: block; width: 148px; height: 1px; background: var(--rule-strong); overflow: hidden; }
.loading-bar i { display: block; width: 40%; height: 100%; background: var(--accent); animation: mar-sweep 1250ms var(--e-inout) infinite; }
@keyframes mar-sweep { 0% { transform: translateX(-100%); } 100% { transform: translateX(350%); } }
.loading p { font-family: var(--font-mono); font-size: var(--step--2); letter-spacing: 0.18em; text-transform: uppercase; color: var(--fg-faint); }

.empty { padding: clamp(130px, 28vw, 200px) 0 var(--s-9); }
.muted { color: var(--fg-muted); }

/* --- 16. View transition ------------------------------------------------ */

#main { transition: opacity 180ms var(--e-out); }
#main.is-leaving, #main.is-entering { opacity: 0; }

/* --- 17. Footer --------------------------------------------------------- */

.app-footer {
  padding-block: var(--s-7) calc(var(--s-7) + env(safe-area-inset-bottom));
  border-top: 1px solid var(--rule);
  color: var(--fg-muted);
}
.foot-meta {
  display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-5);
  font-family: var(--font-mono); font-size: 0.6rem;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--fg-faint);
  margin-bottom: var(--s-4);
}
.foot-legal { font-size: var(--step--1); margin-bottom: var(--s-3); }
.foot-legal a { color: inherit; text-decoration: none; border-bottom: 1px solid var(--rule-strong); }
.foot-legal a:hover { color: var(--accent); }
.foot-note { font-size: var(--step--2); color: var(--fg-faint); max-width: 58ch; }

/* --- 18. Reduced motion ------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  :root:not([data-motion="full"]) .vbar i,
  :root:not([data-motion="full"]) .hbar-track i { transform: none !important; transition: none; }
  :root:not([data-motion="full"]) .loading-bar i,
  :root:not([data-motion="full"]) .loading-mark,
  :root:not([data-motion="full"]) .btn-spinner { animation-duration: 2400ms; }
  :root:not([data-motion="full"]) #main { transition: none; }
}

/* ==========================================================================
   19. Chart components
   Added so metrics read as shapes first and figures second — these dashboards
   are read at a glance by people who don't work in analytics.
   ========================================================================== */

/* --- Chart cards -------------------------------------------------------- */

.viz-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1px;
  background: var(--rule);
  border-block: 1px solid var(--rule);
  margin-top: var(--s-6);
}
@media (min-width: 640px) { .viz-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1100px) { .viz-grid { grid-template-columns: repeat(4, 1fr); } }

.viz {
  display: grid;
  grid-template-rows: auto 1fr auto;
  gap: var(--s-4);
  padding: var(--s-5) var(--s-4);
  background: var(--bg);
}
.band .viz { background: var(--ink); }

.viz-head { display: grid; gap: var(--s-1); }
.viz-head h3 {
  font-size: var(--step-1);
  letter-spacing: 0;
}
.viz-figure {
  font-family: var(--font-body);
  font-size: var(--step-3);
  font-weight: 650;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.viz-caption {
  margin-top: var(--s-2);
  font-size: var(--step--1);
  line-height: 1.45;
  color: var(--fg-muted);
}
.viz-label {
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--fg-faint);
}
.viz-body { display: grid; align-content: center; }
.viz-note {
  font-size: var(--step--2);
  color: var(--fg-faint);
  line-height: 1.4;
}

/* --- Donut -------------------------------------------------------------- */

.donut { width: 100%; max-width: 172px; margin-inline: auto; }
.sov .donut { max-width: 156px; }
.donut svg { width: 100%; height: auto; overflow: visible; }

.donut-track { fill: none; stroke: var(--rule-strong); stroke-width: 9; }
.donut-fill {
  fill: none;
  stroke: var(--state, var(--accent));
  stroke-width: 9;
  stroke-linecap: butt;
  stroke-dasharray: var(--dash);
  stroke-dashoffset: var(--dash);
  transition: stroke-dashoffset 1400ms var(--e-out) 180ms;
}
.anim [data-reveal].is-in .donut-fill { stroke-dashoffset: var(--offset); }
.donut.is-accent { --state: var(--accent); }

.donut-value {
  font-family: var(--font-body);
  font-size: 30px;
  font-weight: 650;
  letter-spacing: -0.03em;
  fill: var(--fg);
  text-anchor: middle;
  font-variant-numeric: tabular-nums;
}
.donut-sub {
  margin-top: var(--s-3);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.1em;
  color: var(--fg-faint);
  text-align: center;
}

/* --- Paired bars -------------------------------------------------------- */

.pairbars { display: grid; gap: var(--s-4); align-content: center; }
.pairbar { display: grid; gap: var(--s-2); }
.pairbar-top {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-3);
}
.pairbar-top b {
  font-size: var(--step-1); font-weight: 600;
  letter-spacing: -0.02em; font-variant-numeric: tabular-nums;
}
.pairbar-top span {
  font-family: var(--font-mono); font-size: 0.6rem;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--fg-faint);
}
.pairbar-track { display: block; height: 10px; background: color-mix(in srgb, var(--fg) 8%, transparent); }
.pairbar-track i {
  display: block; height: 100%; width: var(--w, 10%);
  background: color-mix(in srgb, var(--fg) 26%, transparent);
  transform: scaleX(0); transform-origin: left;
  transition: transform 820ms var(--e-out) var(--d, 0ms);
}
.pairbar.is-accent .pairbar-track i { background: var(--accent); }
.anim [data-reveal].is-in .pairbar-track i { transform: scaleX(1); }

/* --- Stacked composition bar -------------------------------------------- */

.stackbar { display: grid; gap: var(--s-4); align-content: center; }
.stackbar-track { display: flex; height: 14px; gap: 1px; overflow: hidden; }
.stackbar-track i {
  display: block; width: var(--w, 33%); height: 100%;
  transform: scaleX(0); transform-origin: left;
  transition: transform 760ms var(--e-out) var(--d, 0ms);
}
.anim [data-reveal].is-in .stackbar-track i { transform: scaleX(1); }
.stackbar-track .is-neutral { background: color-mix(in srgb, var(--fg) 24%, transparent); }
.stackbar-track .is-warn { background: var(--warn); }
.stackbar-track .is-good { background: var(--good); }

.stackbar-key { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-2); }
.stackbar-key li {
  display: grid; grid-template-columns: 8px auto 1fr; align-items: center; gap: var(--s-2);
  font-size: var(--step--2);
}
.stackbar-key i { width: 8px; height: 8px; }
.stackbar-key .is-neutral i { background: color-mix(in srgb, var(--fg) 24%, transparent); }
.stackbar-key .is-warn i { background: var(--warn); }
.stackbar-key .is-good i { background: var(--good); }
.stackbar-key b { font-variant-numeric: tabular-nums; font-weight: 600; }
.stackbar-key span { color: var(--fg-faint); }

/* --- Distribution dot plot ---------------------------------------------- */

.subsection { margin-top: var(--s-8); padding-top: var(--s-7); border-top: 1px solid var(--rule); }

.dotplot { margin-top: var(--s-5); }
.dotplot-plot { position: relative; height: 118px; }

/* Geometry, so the two reference marks never collide: the axis sits 46px off
   the bottom; the AVERAGE upright rises above it with its label on top, the
   MEDIAN upright drops below with its label underneath. They can share the same
   x to the pixel and still both read. */
.dotplot-axis {
  position: absolute; left: 0; right: 0; bottom: 46px; height: 1px;
  background: var(--rule-strong);
}

.dot {
  position: absolute; bottom: 40px; left: var(--x, 0%);
  width: 13px; height: 13px;
  margin-left: -6.5px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--fg) 30%, transparent);
  opacity: 0; transform: translateY(6px) scale(0.6);
  transition: opacity 420ms var(--e-out) var(--d, 0ms),
              transform 520ms var(--e-out) var(--d, 0ms),
              background var(--t-1) var(--e-out);
}
.anim [data-reveal].is-in .dot { opacity: 0.9; transform: none; }
.dot.is-hit { background: var(--good); }
.dot:hover, .dot:focus-visible { background: var(--accent); opacity: 1; }

.dotplot-mark {
  position: absolute; left: var(--x, 50%);
  width: 1px;
  transform: scaleY(0);
  transition: transform 700ms var(--e-out) 400ms;
}
.anim [data-reveal].is-in .dotplot-mark { transform: scaleY(1); }

.dotplot-mark.is-avg {
  bottom: 46px; height: 44px;
  transform-origin: bottom;
  background: var(--accent);
}
.dotplot-mark.is-median {
  bottom: 22px; height: 25px;
  transform-origin: top;
  background: var(--rule-strong);
}

.dotplot-mark b {
  position: absolute; left: 0;
  transform: translateX(-50%);
  font-family: var(--font-mono); font-size: 0.55rem; font-weight: 500;
  letter-spacing: 0.12em; text-transform: uppercase; white-space: nowrap;
}
.dotplot-mark.is-avg b { top: -14px; color: var(--accent); }
.dotplot-mark.is-median b { bottom: -15px; color: var(--fg-faint); }

.dotplot-scale {
  display: flex; justify-content: space-between;
  margin-top: var(--s-2);
  font-family: var(--font-mono); font-size: 0.6rem;
  letter-spacing: 0.14em; color: var(--fg-faint);
}

/* --- Competitor comparison panel ---------------------------------------- */

.compare-panel {
  padding: var(--s-5);
  background: var(--surface);
  box-shadow: inset 0 0 0 1px var(--rule);
  margin-bottom: var(--s-5);
}
.compare-panel { overflow: hidden; }
.compare-note { margin-top: var(--s-4); padding-top: var(--s-4); border-top: 1px solid var(--rule); }
.compare-top {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--s-3);
  margin-bottom: var(--s-5);
}
@media (min-width: 720px) {
  .compare-top { grid-template-columns: minmax(0, 1fr) auto; align-items: center; }
  .compare-top .sov-label { margin-bottom: 0; }
}

/* --- Share of voice ----------------------------------------------------- */

.sov {
  display: grid; gap: var(--s-4); justify-items: center; text-align: center;
  margin-bottom: var(--s-7);
  padding: var(--s-5);
  background: var(--surface);
  box-shadow: inset 0 0 0 1px var(--rule);
}
@media (min-width: 720px) {
  .sov { grid-template-columns: auto minmax(0, 1fr); text-align: left; justify-items: start; align-items: center; gap: var(--s-6); }
  .sov .donut-sub { text-align: center; }
}
.sov-copy { color: var(--fg-muted); font-size: var(--step--1); max-width: 40ch; }

/* --- Rate row ----------------------------------------------------------- */

.rate-row {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: var(--s-4);
  margin-top: var(--s-6);
  padding-top: var(--s-5);
  border-top: 1px solid var(--rule);
}
.rate-row .metric strong { font-size: var(--step-1); }
/* mar.css sets .metric small in the mono face — right for a label, wrong for a
   full sentence. These captions are prose, so they read in the body face. */
.rate-row .metric small {
  font-family: var(--font-body);
  font-size: var(--step--2);
  line-height: 1.45;
  letter-spacing: 0;
  text-transform: none;
  color: var(--fg-muted);
}
@media (max-width: 479px) {
  .rate-row { grid-template-columns: 1fr; gap: var(--s-3); }
  .rate-row .metric { display: grid; grid-template-columns: 5.5em 1fr; align-items: baseline; gap: var(--s-3); }
  .rate-row .metric small { grid-column: 2; }
}

/* The banner sits above everything, so its button must clear the 44px touch
   minimum — it was previously inheriting a desktop-sized target. */
.motion-banner { position: relative; z-index: 1; }
.motion-toggle { min-height: 32px; padding-inline: var(--s-3); }

.comp-flag {
  font-size: var(--step--2);
  color: var(--fg-faint);
  padding-top: var(--s-2);
  border-top: 1px dashed var(--rule);
}

/* A metric the platform does not publish reads as absent, not as zero. */
.metric.is-na strong {
  font-family: var(--font-mono);
  font-size: var(--step--1);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--fg-faint);
}

/* --- Language switch ---------------------------------------------------- */

.app-header .lang-switch {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 36px; height: 36px;
  border: 1px solid var(--rule-strong);
  background: transparent;
  color: var(--fg-muted);
  font-family: var(--font-mono); font-size: var(--step--2);
  letter-spacing: 0.08em;
  cursor: pointer;
  transition: color var(--t-1) var(--e-out), border-color var(--t-1) var(--e-out);
}
.app-header .lang-switch:hover { color: var(--fg); border-color: var(--fg); }
