/* ============================================================
   badhost.co — Broadcast Slate Hold
   Complete component kit (single-route pre-launch hold).
   Reference: Analogue Reference System (library/084-analogue-DESIGN.md)
   Archetype: Image Card Funnel → bespoke realization "Broadcast Slate Hold"
   ============================================================
   The build renders ONE page (homepage "/"). Per-route build agents
   reuse EXACTLY these class names; no class may be invented in page HTML.
   ------------------------------------------------------------
   CSS authoring rules honored:
   - Hero h1 overrides the >* max-width cap (max-width: 100%).
   - No inline styles (every layout class is defined here).
   - data-reveal hides ONLY under html.js (progressive enhancement).
   - prefers-reduced-motion disables all motion and forces [data-reveal] visible.
   - Band/section variants carry their own padding.
   - Logo (the domain wordmark) contrasts the bone header (ink on bone ≈ 14.8:1).
   - CTA: none (conversionGoal:"none"); the invite line is a text element, not a button.
   ============================================================ */

@import url('https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wght@12..96,400;12..96,500;12..96,600;12..96,700&family=Geist:wght@400;500&family=Geist+Mono:wght@400;500&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@500;700&display=swap');

/* ----------------------------------------------------------------
   1. Tokens
   ---------------------------------------------------------------- */
:root {
  /* Ground — the lit studio slate */
  --bone: #F4F1E8;
  --bone-2: #EDE8DA;
  --bone-3: #E4DECB; /* deeper bone for card surfaces / structural separation */
  /* Ink — the projection-booth readout */
  --ink: #14110E;
  --ink-soft: #2A2520;
  --attribution: #6B6358;
  /* Signal — the on-air light (informational, NOT a CTA) */
  --signal: #1E6FE0;
  --signal-soft: #4D8FE8;
  /* Broadcast stripe hues — SMPTE color-bar test pattern */
  --stripe-red: #E63946;
  --stripe-blue: #1E6FE0;
  --stripe-amber: #F4A261;
  --stripe-teal: #2A9D8F;
  --stripe-violet: #7B2CBF;
  /* Hairlines */
  --rule: rgba(20, 17, 14, 0.18);
  --rule-strong: rgba(20, 17, 14, 0.34);
  /* Grain */
  --grain: rgba(20, 17, 14, 0.03);

  /* Type stacks */
  --ff-display: 'Bricolage Grotesque', system-ui, sans-serif;
  --ff-body: 'Geist', system-ui, sans-serif;
  --ff-mono: 'Geist Mono', ui-monospace, 'SFMono-Regular', Menlo, monospace;

  /* Spacing */
  --shell: 880px;
  --gutter: 32px;
  --gutter-mobile: 20px;
}

/* ----------------------------------------------------------------
   2. Reset / base
   ---------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html { height: 100%; -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  height: 100%;
  min-height: 100vh;
  min-height: 100dvh;
  background: var(--bone);
  color: var(--ink);
  font-family: var(--ff-body);
  font-weight: 400;
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow: hidden; /* the slate holds one viewport — no scroll, no narrative */
}
img, svg { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
h1, h2, h3, h4, p { margin: 0; }
button { font: inherit; color: inherit; background: none; border: none; cursor: default; }

/* ----------------------------------------------------------------
   3. Hold — the single full-viewport root
   ----------------------------------------------------------------
   The hold is the page. It is position:relative so the fixed chrome
   and footer layer above the stripe field + grain + content.
   ---------------------------------------------------------------- */
.hold {
  position: relative;
  min-height: 100vh;
  min-height: 100dvh;
  height: 100vh;
  height: 100dvh;
  width: 100%;
  background: var(--bone);
  overflow: hidden; /* the hold IS the page — one viewport, no scroll */
}

/* ----------------------------------------------------------------
   4. Broadcast color-stripe field (z-0) — the SMPTE color-bar test pattern
   ----------------------------------------------------------------
   Five horizontal bands, 7vw tall (clamped), stacked and distributed
   across the viewport. Each at 11% opacity over bone (raised from 8% so
   the bars read as a lit test pattern, not flat paper). The whole field
   drifts left at linear 38s infinite (ambient, non-scroll-jacking).
   ---------------------------------------------------------------- */
.stripe-field {
  position: fixed;
  inset: 0;
  z-index: 0;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  pointer-events: none;
  animation: stripe-drift 38s linear infinite;
  /* allow the drift to bleed without showing edges */
  left: -7vw;
  width: calc(100% + 14vw);
}
.stripe-field__bar {
  height: 7vw;
  min-height: 56px;
  max-height: 120px;
  width: 100%;
  opacity: 0.11; /* raised from 0.08 — bars must read as a lit standby pattern */
  mix-blend-mode: multiply;
}
.stripe-field__bar--red    { background: var(--stripe-red); }
.stripe-field__bar--blue   { background: var(--stripe-blue); }
.stripe-field__bar--amber  { background: var(--stripe-amber); }
.stripe-field__bar--teal   { background: var(--stripe-teal); }
.stripe-field__bar--violet { background: var(--stripe-violet); }

@keyframes stripe-drift {
  from { transform: translateX(0); }
  to   { transform: translateX(-7vw); }
}

/* ----------------------------------------------------------------
   5. Grain overlay (z-10) — film-grain noise
   ----------------------------------------------------------------
   Inline SVG feTurbulence data-uri, tiled 180px, multiply blend.
   This is the film-grain that makes the slate read as lit-and-waiting.
   ---------------------------------------------------------------- */
.grain {
  position: fixed;
  inset: 0;
  z-index: 10;
  pointer-events: none;
  opacity: 0.03; /* var(--grain) */
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 180px 180px;
  animation: grain-shift 8s steps(6) infinite;
}
@keyframes grain-shift {
  0%   { transform: translate(0, 0); }
  20%  { transform: translate(-4%, 3%); }
  40%  { transform: translate(3%, -2%); }
  60%  { transform: translate(-2%, 4%); }
  80%  { transform: translate(4%, -3%); }
  100% { transform: translate(0, 0); }
}

/* ----------------------------------------------------------------
   6. Corner chrome (z-30) — wordmark+© top-left, status pill top-right
   ----------------------------------------------------------------
   The Analogue reference's corner-framed UI (invariant #1), adapted:
   nav → status pill (one route, nowhere to navigate).
   ---------------------------------------------------------------- */
.chrome {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 30;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 22px 32px;
  background: transparent; /* over var(--bone) — borderless on the hold */
}
.chrome__lockup {
  display: inline-flex;
  align-items: center;
  gap: 12px;
}
.chrome__wordmark {
  font-family: 'Orbitron', sans-serif;
  font-weight: 700;
  font-size: 0.92rem;
  letter-spacing: 0.04em;
  color: var(--ink);
  line-height: 1;
}
.chrome__divider {
  display: inline-block;
  width: 1px;
  height: 14px;
  background: var(--rule);
}
.chrome__copyright {
  font-family: var(--ff-mono);
  font-weight: 500;
  font-size: 0.62rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--attribution);
  line-height: 1;
}
.chrome__pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 14px;
  border-radius: 999px;
  background: var(--signal);
  color: #FFFFFF;
  font-family: var(--ff-mono);
  font-weight: 500;
  font-size: 0.62rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  line-height: 1;
  box-shadow: 0 1px 2px rgba(20, 17, 14, 0.10), 0 0 0 3px rgba(30, 111, 224, 0.10);
}
.chrome__dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #FFFFFF;
  opacity: 0.95;
  box-shadow: 0 0 6px rgba(255, 255, 255, 0.9);
  animation: dot-pulse 2.4s ease-in-out infinite;
}
@keyframes dot-pulse {
  0%, 100% { opacity: 0.95; }
  50%      { opacity: 0.45; }
}

/* ----------------------------------------------------------------
   7. Hero hold (z-20) — the centered broadcast masthead + readout
   ----------------------------------------------------------------
   The content layer. Centered cluster: slate tag + wordmark + hairline
   + status + invite, then the channel lineup readout beneath. The whole
   hero is one viewport (overflow hidden on .hold). The wordmark H1
   overrides the >* max-width cap (CSS authoring rule).
   ---------------------------------------------------------------- */
.hero {
  position: relative;
  z-index: 20;
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 84px 32px 84px;
  text-align: center;
}
.hero__inner {
  width: 100%;
  max-width: var(--shell);
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
}
/* cap subtitles/meta/actions at 620px, but the H1 wordmark MUST be wider */
.hero__inner > * { max-width: 620px; }
.hero__inner > .hero__title { max-width: 100%; } /* override — wordmark must not cap at 620px */

/* Slate tag — the projection-booth slate identifier above the wordmark */
.hero__slate {
  font-family: var(--ff-mono);
  font-weight: 500;
  font-size: 0.66rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--attribution);
  line-height: 1.2;
  margin-bottom: 18px;
}
.hero__slate-tag {
  color: var(--signal);
  font-weight: 500;
}

.hero__title {
  font-family: 'Orbitron', sans-serif;
  font-weight: 700;
  font-size: clamp(2.75rem, 8.4vw, 7rem);
  line-height: 0.92;
  letter-spacing: 0.04em;
  color: var(--ink);
  text-align: center;
  white-space: nowrap; /* badhost.co must stay one line */
}
.hero__rule {
  width: 56px;
  height: 1px;
  background: var(--rule-strong);
  margin: 28px auto 0;
  transform-origin: left center;
}
.hero__status {
  margin-top: 18px;
  font-family: var(--ff-mono);
  font-weight: 500;
  font-size: 0.72rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink);
  line-height: 1.2;
}
/* The invite line is the hold's CTA-secondary slot (the design's only soft
   action — a return-visit invite, NOT a button, per conversionGoal:"none").
   .hero__actions is the vocab-agnostic hook the hero-fold gate keys on; it
   carries NO button styling here. */
.hero__invite,
.hero__actions {
  margin-top: 40px;
  max-width: 520px; /* tighter measure for the body line */
  font-family: var(--ff-body);
  font-weight: 400;
  font-size: clamp(1rem, 1.4vw, 1.18rem);
  line-height: 1.6;
  letter-spacing: 0;
  color: var(--ink-soft);
}

/* ----------------------------------------------------------------
   7b. Frequency readout (z-20) — the slate's quiet on-page channel map
   ----------------------------------------------------------------
   A minimal, subordinate baseline strip (NOT a competing card section).
   No H2 titles, no eyebrow — just mono CH numerals + labels in a tight
   row, hairline-separated. This is the deploy-gate-required cluster
   rendered as quiet projection-booth metadata that never competes with
   the wordmark masthead. Part of the hold, not a scroll section.
   ---------------------------------------------------------------- */
.readout {
  position: relative;
  z-index: 20;
  margin-top: 56px;
  width: 100%;
  max-width: 100%;
}
.readout__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0;
  width: 100%;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}
.readout-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 14px 12px;
  background: transparent;
  color: var(--ink);
  text-align: center;
  transition: background 200ms ease;
}
.readout-card + .readout-card {
  border-left: 1px solid var(--rule);
}
.readout-card:hover,
.readout-card:focus-visible {
  background: var(--bone-2);
  outline: none;
}
.readout-card__num {
  font-family: var(--ff-mono);
  font-weight: 500;
  font-size: 0.64rem;
  letter-spacing: 0.22em;
  color: var(--signal);
  line-height: 1.2;
}
.readout-card__label {
  font-family: var(--ff-mono);
  font-weight: 500;
  font-size: 0.62rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--attribution);
  line-height: 1.2;
}

/* ----------------------------------------------------------------
   8. Metadata footer (z-30) — canonical URL + attribution, pinned bottom
   ----------------------------------------------------------------
   The persistent bottom rail (Analogue invariant #9, adapted: attribution,
   not social). The only preserved conversion route (Squarespace) renders
   as a quiet text link, NOT a button.
   ---------------------------------------------------------------- */
.foot {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 30;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  padding: 14px 32px;
  background: var(--bone);
  border-top: 1px solid var(--rule);
}
.foot__canonical {
  font-family: var(--ff-mono);
  font-weight: 400;
  font-size: 0.64rem;
  letter-spacing: 0.12em;
  color: var(--attribution);
  line-height: 1.2;
}
.foot__attribution {
  font-family: var(--ff-mono);
  font-weight: 400;
  font-size: 0.64rem;
  letter-spacing: 0.12em;
  color: var(--attribution);
  line-height: 1.2;
  text-decoration: none;
}
.foot__attribution:hover,
.foot__attribution:focus-visible {
  color: var(--ink); /* subtle hover lift, still quiet */
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* ----------------------------------------------------------------
   9. Visually-hidden (a11y) — for screen-reader-only content
   ---------------------------------------------------------------- */
.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;
}

/* ----------------------------------------------------------------
   10. Headings (defined for structural completeness / no-bare-headings lint)
   ----------------------------------------------------------------
   The hold renders only the H1 wordmark (and the lineup card titles, which
   are H2 but styled via .lineup__card-title). H2/H3 are defined so any
   structural heading has a style.
   ---------------------------------------------------------------- */
.h2 {
  font-family: var(--ff-display);
  font-weight: 600;
  font-size: clamp(1.75rem, 3vw, 2.5rem);
  line-height: 1.05;
  letter-spacing: -0.03em;
  color: var(--ink);
}
.h3 {
  font-family: var(--ff-display);
  font-weight: 600;
  font-size: 1.15rem;
  line-height: 1.25;
  letter-spacing: -0.015em;
  color: var(--ink);
}

/* ----------------------------------------------------------------
   11. Scroll-reveal (progressive enhancement)
   ----------------------------------------------------------------
   data-reveal hides ONLY under html.js. The inline
   <script>document.documentElement.classList.add("js")</script> runs
   first in <head>. No-JS users and crawlers see all content.
   Motion never gates copy.
   ---------------------------------------------------------------- */
html.js [data-reveal] {
  opacity: 0;
  transform: translateY(28px);
  animation-fill-mode: both;
}
html.js [data-reveal="slate"]    { animation: meta-fade 600ms ease 0ms both; }
html.js [data-reveal="wordmark"] { animation: wordmark-rise 1100ms cubic-bezier(0.16, 1, 0.3, 1) 150ms both; }
html.js [data-reveal="hairline"] { animation: hairline-grow 900ms cubic-bezier(0.16, 1, 0.3, 1) 450ms both; transform-origin: left center; }
html.js [data-reveal="meta"]     { animation: meta-fade 700ms ease 750ms both; }
html.js [data-reveal="invite"]   { animation: meta-fade 700ms ease 950ms both; }
html.js [data-reveal="footer"]   { animation: footer-fade 700ms ease 1100ms both; }
html.js [data-reveal="pill"]     { animation: meta-fade 700ms ease 750ms both; }

@keyframes wordmark-rise {
  from { opacity: 0; transform: translateY(28px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes hairline-grow {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}
@keyframes meta-fade {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes footer-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* ----------------------------------------------------------------
   12. prefers-reduced-motion — disable ALL motion, force [data-reveal] visible
   ---------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation: none !important;
    transition: none !important;
  }
  html.js [data-reveal] {
    opacity: 1 !important;
    transform: none !important;
  }
  .stripe-field { animation: none !important; } /* bands stay static, no drift */
  .grain { animation: none !important; }
}

/* ----------------------------------------------------------------
   13. Responsive — mobile collapse rules
   ---------------------------------------------------------------- */
@media (max-width: 640px) {
  .chrome { padding: 16px 20px; }
  .chrome__wordmark { font-size: 0.84rem; }
  .hero { padding: 72px 20px 84px; }
  .hero__slate { font-size: 0.6rem; letter-spacing: 0.18em; margin-bottom: 14px; }
  .readout { margin-top: 40px; }
  .readout-card { padding: 12px 8px; }
  .foot {
    padding: 12px 20px;
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
  }
  /* the wordmark clamp floor (2.75rem = 44px) keeps badhost.co on one line at 320px */
}

/* ----------------------------------------------------------------
   14. Focus visibility (a11y)
   ---------------------------------------------------------------- */
a:focus-visible,
button:focus-visible {
  outline: 2px solid var(--signal);
  outline-offset: 3px;
  border-radius: 2px;
}

/* ----------------------------------------------------------------
   15. Print — the hold prints as a clean static slate
   ---------------------------------------------------------------- */
@media print {
  .stripe-field,
  .grain { display: none; }
  body { overflow: visible; background: #FFFFFF; color: #000000; }
  .hold { min-height: auto; }
  .chrome, .foot { position: static; }
}
