/* Site developed and built by sitethreesixty.com */

/* ============================================================
   home-critical.css — System base + homepage Zone 1 (hero)
   Everything needed for first paint on this page type.
   ============================================================ */

/*
   SHARED BASE
   Byte-for-byte identical in home-critical.css and inner-critical.css.
   Generated from one source fragment — do not hand-edit either copy.
*/

/* --- Reset ---
   box-sizing only. The delivered design relies on default margins for `p`
   and on UA list padding for anything that doesn't zero it explicitly, so a
   blanket `* { margin: 0; padding: 0 }` would reflow both pages. */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background-color: var(--bg-light);
  color: var(--text-on-light);
  font-family: var(--font-body);
  font-size: var(--font-body-size);
  line-height: var(--leading-normal);
  /* ⛔ -webkit-font-smoothing: antialiased REMOVED — owner report 22 Aug, text
     rendering "faded or splotchy". It disables SUBPIXEL antialiasing and forces
     grayscale, which thins every stroke and is worst on dark-on-light body copy
     and on non-Retina screens. The browser default renders these faces properly;
     do not put it back. */
}

img,
svg,
video {
  display: block;
  max-width: 100%;
}

a {
  color: inherit;
  text-decoration: none;
}

button,
input,
textarea,
select {
  font: inherit;
}

button {
  color: inherit;
}

ul {
  list-style: none;
}

h1,
h2,
h3,
p {
  margin-top: 0;
}

/* --- Heading base ---
   h1 carries no size here: both page types set their own display size in
   their Zone 1 block, and a base size would only be overridden. h4–h6 are
   declared for completeness; neither page currently uses them. */

h1,
h2,
h3,
h4,
h5,
h6 {
  font-family: var(--font-heading);
  font-weight: var(--weight-medium);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
}

h2 {
  margin-bottom: var(--space-lg);
  font-size: var(--font-h2);
}

h3 {
  font-size: var(--font-h3);
  line-height: var(--leading-display);
  letter-spacing: var(--tracking-snug);
}

h4 { font-size: var(--font-h4); }
h5 { font-size: var(--font-h5); }
h6 { font-size: var(--font-h6); }

:focus-visible {
  outline: var(--border-thick) solid var(--brand-accent);
  outline-offset: var(--border-thick);
}

/* --- Skip link ---
   Always visible on focus, so its colours belong in critical. */

.skip-link {
  position: fixed;
  top: var(--space-sm-md);
  left: var(--space-sm-md);
  z-index: var(--z-overlay);
  padding: var(--space-sm-md) var(--space-md);
  background-color: var(--bg-dark);
  color: var(--text-on-dark);
  transform: translateY(-200%);
}

.skip-link:focus {
  transform: translateY(0);
}

/* --- Frame --- */

.frame {
  width: 100%;
  padding-inline: var(--container-pad);
}

/* --- Framework --- */

.framework {
  display: grid;
  grid-template-columns: repeat(var(--grid-columns), minmax(0, 1fr));
  /* Query container for card grids — see the "even rows" note in containers.css.
     It has to be the Framework: .zone is a subgrid, and container-type there
     applies containment that collapses it from 12 tracks to 2 (measured). */
  container-type: inline-size;
  container-name: frame;
}

/* --- Zone base (subgrid) --- */

.zone {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: subgrid;
  padding-block: var(--zone-pad);
}

/* --- Positions ---
   width: 100% on pos-content / pos-narrow is a deliberate, measured
   deviation from Build Lesson #10. Removing it lets these Containers size
   to fit-content instead of filling their column span, which moves 7.2% of
   the hosting page's pixels. Recorded in COMPLETION-DECLARATION.md. */

.pos-full    { grid-column: 1 / -1; }
.pos-wide    { grid-column: 2 / -2; }
.pos-content { grid-column: 3 / -3; justify-self: center; max-width: 90rem; width: 100%; }
.pos-narrow  { grid-column: 4 / -4; justify-self: center; max-width: 58rem; width: 100%; }
.pos-left    { grid-column: 1 / 7; }
.pos-right   { grid-column: 7 / -1; }

/* --- Fixture: Header ---
   Sticky, so its own styling and its mobile drawer's hidden state must both
   be here — a deferred sheet setting either would flash the wrong one. */

.site-header {
  position: sticky;
  top: 0;
  z-index: var(--z-header);
  border-bottom: var(--border-thin) solid color-mix(in srgb, var(--bg-dark) 12%, transparent);
  background-color: color-mix(in srgb, var(--bg-light) 94%, transparent);
  -webkit-backdrop-filter: blur(18px);
  backdrop-filter: blur(18px);
}

/* 1.65rem is a fixed-size UI strip, not a spacing decision — the permitted
   structural exception for critical files (Build Lesson #11). */
.header-compass {
  position: relative;
  display: flex;
  justify-content: space-between;
  height: 1.65rem;
  color: var(--grey-mid);
  font-family: var(--font-mono);
  font-weight: var(--weight-semibold);
  font-size: var(--font-micro);
  line-height: var(--leading-flush);
  letter-spacing: var(--tracking-caps-lg);
}

.header-compass::before {
  position: absolute;
  top: .32rem;
  right: 0;
  left: 0;
  height: var(--border-thin);
  background-color: color-mix(in srgb, var(--bg-dark) 13%, transparent);
  content: "";
}

.header-compass span {
  position: relative;
  padding-top: .78rem;
}

.header-compass span::before {
  position: absolute;
  top: .05rem;
  left: 50%;
  width: var(--border-thin);
  height: .58rem;
  background-color: color-mix(in srgb, var(--bg-dark) 34%, transparent);
  content: "";
}

.header-compass .is-active {
  color: var(--brand-primary);
}

.header-compass .is-active::before {
  height: .82rem;
  background-color: var(--brand-accent);
}

.header-grid {
  min-height: 4.6rem;
  display: grid;
  grid-template-columns: repeat(var(--grid-columns), minmax(0, 1fr));
  align-items: center;
  gap: var(--space-md);
}

.header-grid .wordmark {
  grid-column: 1 / 4;
}

.primary-nav {
  grid-column: 4 / 9;
  display: flex;
  justify-content: center;
  gap: var(--gap-2xs);
}

.header-actions {
  grid-column: 9 / 13;
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: var(--space-md-lg);
}

.nav-toggle {
  display: none;
}

/* --- Portable elements that render above the fold on every page ---
   These carry colour here rather than in elements.css for two reasons: they
   paint before the deferred sheets land, and their colour does not vary by
   Zone, so there is no Zone override to inherit. Anything Zone-dependent
   (.section-label, .btn-primary fills, .text-link) still lives in zones.css.
   Moving these out of the deferred sheet is the same fix Build Lesson #14
   describes — an above-fold class defined only in a deferred file flashes. */

.wordmark {
  font-family: var(--font-heading);
  font-size: var(--font-h6);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-tight);
}

.primary-nav,
.header-login,
.header-cta {
  font-size: var(--font-small);
  /* --weight-regular, NOT --weight-medium. These are body-font, and --weight-medium is 300
     because that is where Jakarta Round's Light is set for the headings — the nav was only
     ever riding along, and it went thin when the owner chose Light. The token cannot move:
     Jakarta Round ships 300 and 600 only, so 400 there would synthesise. The design had
     these at 500; the frozen set has no 500, and 400 and 600 sit equidistant from it, so
     400 wins on the grounds that 600 reads as bold in a nav. Owner ruling 29. */
  font-weight: var(--weight-regular);
}

/* ⛔ Hover is an UNDERLINE, never `opacity`. A8 bans the opacity property on a
   text element outright, and says so of tokens explicitly: `opacity:
   var(--opacity-half)` is exactly as banned as `opacity: .58`. Underline is
   ground-independent, so it needs no per-Zone rule and cannot drift out of
   contrast the way a dimmed colour does. Inspection finding 2, 19 Aug 2026. */
/* The nav declared no family, so it inherited --font-body — a SYSTEM stack.
   It therefore rendered in whatever face the OS supplied, beside a wordmark set
   in Jakarta Round: mismatched, and on some systems faded or patchy because the
   OS face was being synthesised at a weight it does not ship. Owner ruling
   22 Aug: the nav is Jakarta.
   ⚠️ weight 300 is deliberate — Jakarta Round ships ONLY 300 and 600. Asking for
   400 or 500 makes the browser fake it, which is exactly the splotchy rendering
   this fixes. See this repo's CLAUDE.md: "--weight-bold does not exist here." */
.primary-nav a,
.header-login {
  font-family: var(--font-heading);
  font-weight: var(--weight-medium);
  text-decoration: underline;
  text-decoration-color: transparent;
  text-underline-offset: .3em;
  text-decoration-thickness: 1px;
  transition: text-decoration-color var(--speed-fast) var(--ease-default);
}

.primary-nav a:hover,
.header-login:hover {
  text-decoration-color: currentColor;
}

/* ⚠️ font-weight is DECLARED, never inherited — owner ruling 30, 19 Aug 2026.
   This rule previously set font-family and font-size but no weight, so all 143
   eyebrows on the site took whatever the cascade happened to hand them: 136 at
   400, three at 600 and four at other values, purely by position. That is
   Lesson #21 exactly — switch the family, forget the weight, and the element
   silently inherits one. 600 is now stated, so an eyebrow reads the same
   wherever it lands.

   Size floor: --font-label is 14.08px, comfortably over the owner's stated
   13px minimum. The floor is not re-declared here because the token IS the
   floor; if it ever drops below 13, scripts/legibility.py fails first. */
/* ─── The label family ────────────────────────────────────────────────────────
 *
 * ONE definition of mono-uppercase label type. Before this existed, ~55 rules
 * across the site hand-copied the same four declarations, and ~50 of them
 * omitted font-weight and silently inherited w300 — Lesson #21, fifty times.
 *
 * ⚠️ Do NOT write `font-family: var(--font-mono)` in a new rule. Add the class
 *    and, if it needs a different size, one of the modifiers. Gate E1c fails
 *    the build on a fresh hand-copy.
 *
 * Size modifiers exist because the family genuinely spans three sizes; they
 * carry NO other difference. --font-micro is absent on purpose: it is
 * instrument chrome only and never a label (ruling 29).
 *
 * ⚠️ Shape is not the same thing as role. A rule that merely LOOKS like this
 *    (a pending-asset note, a caption) is not a label and must not take the
 *    class — .media-placeholder-label took it once and inherited a colour that
 *    measured 3.17:1. Ask what it IS, not what it looks like.
 */
.section-label {
  font-family: var(--font-mono);
  font-size: var(--font-label);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-caps-lg);
  text-transform: uppercase;
}

.section-label.is-caption { font-size: var(--font-caption); }
.section-label.is-sm      { font-size: var(--font-label-sm); }

/* The orange full stop closing most headings, plus the wordmark's and the
   watermark's. A real typeset period again, now that the font carries a round
   one — which also removes the line-breaking problem a drawn dot caused: an
   inline-block counts as U+FFFC, whose line-break class permits a break before
   it, so the dot kept getting orphaned onto its own line.

   Ground-bound: the light value is the default because the header and Zone 1 are
   light on both pages; zones.css swaps in the brighter accent on dark. */
.signal-dot {
  color: var(--brand-accent-on-light);
}

.btn-primary,
.btn-secondary {
  /* Buttons declared no family, so they inherited --font-body — a SYSTEM stack —
     and rendered in a different face from the Jakarta around them. Same root
     cause as the nav (fixed 22 Aug). Weight 600 is real in Jakarta Round; 400
     and 500 are not, and asking for them makes the browser synthesise. */
  font-family: var(--font-heading);
  font-weight: var(--weight-semibold);
  display: inline-flex;
  min-height: 3.25rem;
  padding: var(--space-sm-md) var(--space-md-plus);
  border: var(--border-thin) solid transparent;
  border-radius: var(--radius-full);
  align-items: center;
  justify-content: center;
  font-weight: var(--weight-semibold);
  line-height: var(--leading-flush);
  transition: transform var(--speed-fast) var(--ease-default),
              opacity var(--speed-fast) var(--ease-default);
}

.btn-secondary {
  background-color: transparent;
}

.btn-primary:hover,
.btn-secondary:hover {
  transform: translateY(-1px);
}

.action-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm-md);
}

/* --- Scroll-reveal initial state ---
   Hidden state is critical; the transition to visible is not. Without this
   here, revealed blocks paint visible then snap to hidden when the deferred
   sheet lands. */

.will-reveal {
  opacity: 0;
  transform: translateY(1.1rem);
}

/* --- Responsive: the single breakpoint --- */

@media (max-width: 1000px) {
  /* THE MOBILE GUTTER MOVES INSIDE THE BANDS — it is not duplicated.
     Corrected Build Lesson #13 warns against adding padding-inline to .zone while
     .frame keeps its own, because that double-pads and cost three live sites 96px.
     This hands the gutter over instead: main.frame gives its padding up in the
     same breakpoint, so the total is unchanged at one --container-pad.

     Why it is needed: below 1000px every position collapses to 1 / -1, so content
     sits flush against the Zone's edge. On a dark band that edge is visible, and
     the text appeared to touch the side of the card. Zones now run full-bleed to
     the viewport and inset their own content.

     Only safe inside this breakpoint: .zone uses subgrid, and padding on a subgrid
     container shifts its tracks out of line with the Framework. Above 1000px the
     positions do the insetting and the padding must not exist.

     .footer-zone is excluded because .footer-grid carries its own inset at every
     width — it would otherwise be padded twice. */

  main.frame {
    padding-inline: 0;
  }

  .zone:not(.footer-zone) {
    padding-inline: var(--container-pad);
  }

  .pos-full,
  .pos-wide,
  .pos-content,
  .pos-narrow,
  .pos-left,
  .pos-right {
    grid-column: 1 / -1;
    max-width: none;
  }

  .header-compass {
    display: none;
  }

  .header-grid {
    min-height: 4.4rem;
    grid-template-columns: 1fr auto;
  }

  .header-grid .wordmark {
    grid-column: 1;
  }

  /* No-JS fallback: the nav stacks and stays reachable. Only once .js proves
     a script is present does it become a toggle-driven drawer. */
  .primary-nav {
    grid-column: 1 / -1;
    flex-direction: column;
    align-items: flex-start;
  }

  /* The drawer slides rather than appearing. Owner feedback 22 Aug: it "opens
     too fast" — because it did not open at all, it switched display none→flex
     with no transition. display cannot be animated, so the drawer stays in flow
     and is moved with transform + opacity, which the compositor can animate.
     visibility keeps it out of the tab order while closed. */
  .js .primary-nav {
    position: absolute;
    top: 100%;
    right: 0;
    left: 0;
    grid-column: auto;
    display: flex;
    padding: var(--space-lg) var(--container-pad);
    border-bottom: var(--border-thin) solid var(--grey-light);
    background-color: var(--bg-light);
    opacity: 0;
    visibility: hidden;
    /* Travels its own full height so the movement is actually visible. At
       -0.75rem the drawer barely moved, which read as "it just appeared".
       --speed-slow (680ms) over that distance is a deliberate, unhurried
       reveal rather than a snap. */
    transform: translateY(-100%);
    transition:
      transform var(--speed-slow) var(--ease-default),
      opacity var(--speed-slow) var(--ease-default),
      visibility 0s linear var(--speed-slow);
  }

  .js .primary-nav.is-open {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
    transition-delay: 0s;
  }

  /* Dims the page behind the drawer and gives a tap target to close it.
     Sits under the drawer and the header, over everything else. */
  .js .nav-scrim {
    position: fixed;
    inset: 0;
    /* Below the header (--z-header: 20 carries the drawer with it) and above
       everything else. A higher value dims the drawer's own links. */
    z-index: var(--z-above);
    opacity: 0;
    visibility: hidden;
    background-color: var(--bg-dark);
    transition:
      opacity var(--speed-slow) var(--ease-default),
      visibility 0s linear var(--speed-slow);
  }

  .js .nav-scrim.is-open {
    opacity: .55;
    visibility: visible;
    transition-delay: 0s;
  }

  .js .nav-toggle {
    grid-column: 2;
    display: grid;
    min-width: 3rem;
    padding: .6rem;
    gap: .28rem;
    border: 0;
    background-color: transparent;
    color: var(--text-on-light);
    cursor: pointer;
  }

  .nav-toggle span {
    font-size: var(--font-label-sm);
    font-weight: var(--weight-semibold);
  }

  /* Centred with justify-self rather than auto side margins, which a
     Container must never use to centre itself (checklist C1b). */
  .nav-toggle i {
    display: block;
    justify-self: center;
    width: 1.5rem;
    height: var(--border-thin);
    background-color: currentColor;
  }

  .header-actions {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  /* ⚠️ `*, *::before, *::after` is the reset everyone copies, and it does NOT
     cover any other pseudo-element. `::details-content` animates the FAQ
     disclosures, and it kept animating under reduced motion until it was added
     here — measured, not assumed. `*` matches elements only; each pseudo needs
     naming. ::marker and ::backdrop are listed now so the next component that
     uses one inherits the guard instead of rediscovering this. */
  *,
  *::before,
  *::after,
  *::details-content,
  *::marker,
  *::backdrop {
    animation-duration: .01ms !important;
    animation-delay: 0ms !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/*
   END SHARED BASE
*/


/* <code> carried no styling, so it fell back to the browser's default mono —
   a different face from IBM Plex Mono used by every other mono element.
   Found on 5 pages, 12 instances (.com / .co.uk / .net and similar). */
code {
  font-family: var(--font-mono);
  font-size: 0.94em;
}

/* ============================================================
   Homepage Zone 1 — Hero
   Zone 1 colours live here, never in zones.css (Build Lesson #3).
   The 100svh floor the design carried was removed on owner ruling:
   Zone height is content-driven.
   ============================================================ */

.hero-zone {
  position: relative;
  align-items: center;
  /* 8rem before the content, 6rem after — the design's --space-10 / --space-9
     under their canonical names. Asked for as 9-then-10, but the hero is
     align-items: center, so the LARGER value has to go first to push the
     content down; 6rem is also less than the fluid pad it replaced at desktop
     (115px), which moved the h1 UP. Order swapped to meet the intent.
     Replaces --zone-pad-hero here only; the hosting hero still uses it. */
  padding-block: var(--zone-pad-hero) var(--space-xl-2xl);
  color: var(--text-on-light);
  background-image: radial-gradient(circle at 9% 7%,
                      color-mix(in srgb, var(--brand-accent) 7%, transparent),
                      transparent 28rem);
  background-color: var(--bg-light);
}

/* Vertical rule field — decoration, masked out at top and bottom. */
.hero-zone::before {
  position: absolute;
  inset: 0;
  background-image: linear-gradient(to right,
                      color-mix(in srgb, var(--bg-dark) 2.7%, transparent) 1px,
                      transparent 1px);
  background-size: min(8vw, 7.5rem) 100%;
  content: "";
  pointer-events: none;
  -webkit-mask-image: linear-gradient(to bottom, transparent, black 12%, black 88%, transparent);
  mask-image: linear-gradient(to bottom, transparent, black 12%, black 88%, transparent);
}

.hero-zone > * {
  position: relative;
  z-index: var(--z-base);
}

.hero-zone .btn-primary {
  background-color: var(--bg-accent);
  color: var(--white);
}

.hero-zone .btn-secondary {
  border-color: var(--text-on-light);
}

/* --- Hero container ---
   Deliberately asymmetric, so it collapses at the system breakpoint rather
   than reflowing with auto-fit — auto-fit would equalise the two columns and
   lose the layout. Same single breakpoint, same file. */

.hero-container-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(27rem, .82fr);
  gap: var(--gap-3xl);
  align-items: center;
}

/* --- Hero copy --- */

.hero-copy h1 {
  max-width: 10.5ch;
  margin-bottom: var(--space-lg);
  font-size: var(--font-display);
  line-height: var(--leading-solid);
}

.hero-line {
  display: block;
  opacity: 0;
  transform: translateY(.18em);
  animation: hero-rise 760ms var(--ease-default) forwards;
}

.hero-line-1 { animation-delay: 90ms; }
.hero-line-2 { animation-delay: 210ms; }

.hero-label {
  margin-bottom: var(--space-lg-xl);
  opacity: 0;
  animation: hero-fade 520ms var(--ease-default) 40ms forwards;
}

.hero-intro {
  max-width: 51ch;
  margin-bottom: var(--space-lg);
  color: var(--text-muted-light);
  font-size: var(--font-body-lg);
}

.hero-copy .action-row {
  opacity: 0;
  animation: hero-fade 520ms var(--ease-default) 420ms forwards;
}

/* Sits at the FOOT of the hero zone, spanning both columns and aligned left —
   owner ruling 22 Aug. Below the buttons it read as part of the copy column;
   across the base of the zone it reads as the hero's own footer, which is what
   a row of product routes should be. */
.hero-scope-line {
  grid-column: 1 / -1;
  justify-self: start;
  margin: var(--space-2xl) 0 0;
  color: var(--text-muted-light);
  font-family: var(--font-mono);
  font-weight: var(--weight-semibold);
  font-size: var(--font-label-sm);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
}

.hero-scope-line span {
  margin-right: var(--space-sm-md);
  color: var(--brand-primary);
}

/* The scope line carries the product routes. Owner ruling 22 Aug: the nav was
   cut to five items, so the product pages (Hosting°, Bookings°, Publishing
   Suite°, 360Dash, Compare) lost their only route — this line restores it.
   Torch ° between each, matching the mark used across the product family.
   Links inherit the line's own muted ink and only take accent on hover, so the
   line stays a quiet wayfinder rather than a second row of buttons. */
.hero-scope-line a {
  color: inherit;
  text-decoration: none;
  margin-right: var(--space-sm-md);
}

.hero-scope-line a:hover,
.hero-scope-line a:focus-visible {
  color: var(--brand-accent-on-light);
  text-decoration: underline;
}

/* --- Hero instrument ---
   The dark panel opposite the copy. An Element capping its own growth. */

.hero-instrument {
  position: relative;
  min-height: min(70svh, 46rem);
  display: grid;
  grid-template-rows: auto 1fr auto;
  padding: var(--gap-sm);
  overflow: hidden;
  border: var(--border-thin) solid var(--grey-darkest);
  border-radius: var(--radius-lg);
  color: var(--text-on-dark);
  background-color: var(--bg-dark);
  box-shadow: var(--shadow-lg);
  opacity: 0;
  transform: translateY(1rem);
  animation: instrument-settle 820ms var(--ease-default) 220ms forwards;
}

.hero-instrument::before,
.hero-instrument::after {
  position: absolute;
  content: "";
  pointer-events: none;
}

.hero-instrument::before {
  top: 50%;
  right: 0;
  left: 0;
  height: var(--border-thin);
  background-color: color-mix(in srgb, var(--bg-light) 5%, transparent);
}

.hero-instrument::after {
  top: 0;
  bottom: 0;
  left: 50%;
  width: var(--border-thin);
  background-color: color-mix(in srgb, var(--bg-light) 4%, transparent);
}

.hero-instrument-head,
.hero-instrument-foot {
  position: relative;
  z-index: var(--z-above);
  display: flex;
  justify-content: space-between;
  gap: var(--space-md);
  color: var(--text-muted-dark);
  font-family: var(--font-mono);
  font-weight: var(--weight-semibold);
  font-size: var(--font-caption);
  line-height: var(--leading-snug);
  letter-spacing: var(--tracking-caps-lg);
}

.hero-instrument-head {
  padding-bottom: var(--space-md);
  border-bottom: var(--border-thin) solid var(--grey-darkest);
}

.hero-instrument-foot {
  padding-top: var(--space-md);
  border-top: var(--border-thin) solid var(--grey-darkest);
}

.hero-instrument-head span:last-child,
.hero-instrument-foot span:last-child {
  color: var(--brand-accent);
}

/* padding-block is viewport-HEIGHT driven — the stage centres the mark in
   whatever vertical room the panel has. No vh step exists in the gap scale. */
.hero-instrument-stage {
  position: relative;
  z-index: var(--z-above);
  display: grid;
  padding-block: clamp(2.7rem, 6vh, 5rem);
  align-content: center;
}

.hero-instrument-logo {
  width: min(20rem, 75%);
  height: auto;
  border: 0;
}

.hero-instrument-signal {
  position: relative;
  width: min(18rem, 66%);
  height: var(--border-thin);
  margin: var(--gap-md) 0;
  overflow: hidden;
  background-color: var(--grey-darkest);
}

.hero-instrument-signal span {
  position: absolute;
  inset: 0 auto 0 0;
  width: 100%;
  background-color: var(--brand-accent);
  transform: translateX(-101%);
  animation: signal-pass 720ms ease-in-out 1.1s both;
}

.hero-instrument-title {
  max-width: 12ch;
  margin: 0;
  font-family: var(--font-heading);
  font-size: var(--font-h1);
  font-weight: var(--weight-medium);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
}

.hero-instrument-degrees {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 8rem), 1fr));
  gap: var(--space-sm-md);
  margin-top: var(--gap-md);
}

.hero-instrument-degrees div {
  padding-top: var(--space-md);
  border-top: var(--border-thin) solid var(--grey-darkest);
  opacity: 0;
  transform: translateY(.6rem);
  animation: degree-rise 460ms var(--ease-default) forwards;
}

.hero-instrument-degrees div:nth-child(1) { animation-delay: 1.62s; }
.hero-instrument-degrees div:nth-child(2) { animation-delay: 1.76s; }
.hero-instrument-degrees div:nth-child(3) { animation-delay: 1.9s; }

.hero-instrument-degrees span,
.hero-instrument-degrees strong {
  display: block;
}

.hero-instrument-degrees span {
  margin-bottom: var(--space-sm);
  color: var(--brand-accent);
  font-family: var(--font-mono);
  font-weight: var(--weight-semibold);
  font-size: var(--font-caption);
  line-height: var(--leading-flush);
  letter-spacing: var(--tracking-caps);
}

.hero-instrument-degrees strong {
  font-size: var(--font-label-sm);
  /* <strong> is here for emphasis semantics; its weight is a typographic decision, so
     state it. Left alone it takes the UA default 700 and renders bolder than the design,
     which set 400 through the `font:` shorthand's implicit reset (Build Lesson #21). */
  font-weight: var(--weight-semibold);
  line-height: var(--leading-snug);
}

/* --- Zone 1 keyframes ---
   Must live in the same file as the animation: that uses them, or the
   element sits at its opening frame forever (Build Lesson #8). */

@keyframes hero-rise {
  to { opacity: 1; transform: translateY(0); }
}

@keyframes hero-fade {
  to { opacity: 1; }
}

@keyframes instrument-settle {
  to { opacity: 1; transform: translateY(0); }
}

@keyframes signal-pass {
  0%   { transform: translateX(-101%); }
  48%  { transform: translateX(0); }
  100% { transform: translateX(101%); }
}

@keyframes degree-rise {
  to { opacity: 1; transform: translateY(0); }
}

@media (max-width: 1000px) {
  .hero-container-grid {
    grid-template-columns: 1fr;
  }

  .hero-copy h1 {
    max-width: 11ch;
  }

  .hero-zone::before {
    display: none;
  }

  .hero-instrument {
    width: min(44rem, 100%);
    min-height: 38rem;
    padding: clamp(1.25rem, 4vw, 2rem);
    border-radius: var(--radius-md);
  }

  .hero-instrument-head span:first-child,
  .hero-instrument-foot span:first-child {
    max-width: 18ch;
  }
}

/* 3 items — 3 or 1, never 2+1. 3 is prime, so 2+1 strands one */
.hero-instrument-degrees {
  grid-template-columns: minmax(0, 1fr);
}

@container frame (min-width: 1200px) {
  .hero-instrument-degrees {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

/* https://www.sitethreesixty.com */
