/* =============================================================================
   One Source Property Management & Maintenance

   THESIS: This is a chart, not a brochure. The site refuses the category default
   — a photo hero over eight identical service cards — and instead hands a board
   member the one instrument they already navigate by: the Gulf Coast maintenance
   year, with a needle on today.
   OWN-WORLD: Ruled navigation chart. Navy owns whole bands; hairlines carry all
   structure; radii near zero; gold degree ticks; red reserved for the request
   action and the "now" needle. The company's own compass rose is the material,
   not an ornament.
   STORY: A manager arrives with a broken thing. They see what this month asks of
   a Sarasota property, see one vendor covering all eight bearings, and request.
   FIRST VIEWPORT: Left, the headline at full condensed scale with the red request
   action under it. Right, the compass with eight trades set on its bearings —
   the whole coverage argument in one object. The year band starts at the fold.
   FORM: The maintenance year — candidate 4 of the grounded list, seed 263a2c64.
   ========================================================================== */

/* ---------- Tokens ---------- */
:root {
  --navy: #17497f;
  --navy-deep: #0d2a4a;
  --navy-ink: #082138;
  --navy-wash: #eaf0f7;
  --red: #d2232a;
  --red-deep: #b01e26;
  --gold: #f4b223;

  --ink: #101b26;
  --ink-soft: #41586e;
  /* Gold reads as gold at 4.5:1 only when it is darkened for text use. */
  --gold-ink: #7a5200;
  --rule: #c3d0dc;
  --rule-soft: #dee6ee;
  --paper: #ffffff;

  --on-navy: #ffffff;
  --on-navy-soft: rgba(214, 229, 245, 0.82);
  --on-navy-rule: rgba(146, 178, 214, 0.34);

  --display: "Barlow Condensed", "Arial Narrow", Arial, sans-serif;
  --body: "Barlow", "Helvetica Neue", Arial, sans-serif;

  --container: min(1180px, 100% - 2.5rem);
  --reading: min(720px, 100% - 2.5rem);

  --lift: 0 12px 28px -12px rgba(8, 33, 56, 0.32);
  --lift-sm: 0 4px 12px -6px rgba(8, 33, 56, 0.35);

  --ease: cubic-bezier(0.16, 1, 0.3, 1);
}

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

html {
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--body);
  font-size: 1.0625rem;
  line-height: 1.65;
  font-weight: 400;
}

/* height:auto is load-bearing: without it the width/height attributes stay in
   force as presentational hints and any CSS width distorts the image. */
img {
  display: block;
  max-width: 100%;
  height: auto;
}

a {
  color: var(--navy);
  text-underline-offset: 0.18em;
  text-decoration-thickness: 1px;
}

a:hover {
  color: var(--navy-deep);
}

h1,
h2,
h3,
h4 {
  font-family: var(--display);
  font-weight: 700;
  text-transform: uppercase;
  line-height: 0.9;
  letter-spacing: 0.002em;
  text-wrap: balance;
  margin: 0;
}

/* Measure ceiling for every run of prose, so no container can stretch a
   paragraph past a comfortable line. Narrower caps override this locally. */
p {
  margin: 0;
  max-width: 68ch;
}

dd {
  max-width: 60ch;
}

:focus-visible {
  outline: 2px solid var(--navy);
  outline-offset: 2px;
  border-radius: 1px;
}

.container {
  width: var(--container);
  margin-inline: auto;
}

.reading {
  width: var(--reading);
  margin-inline: auto;
}

.skip-link {
  position: absolute;
  left: 1rem;
  top: -5rem;
  z-index: 100;
  background: var(--navy-deep);
  color: #fff;
  padding: 0.75rem 1.25rem;
  font-weight: 600;
  transition: top 150ms var(--ease);
}

/* The global a:hover colour must not win here — it would paint navy on navy. */
.skip-link:focus,
.skip-link:hover {
  top: 1rem;
  color: #fff;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---------- Chart legend label ----------
   The one tracked-uppercase device on the site. It is a chart legend, and it
   appears only where the page is behaving like an instrument. */
.legend {
  font-family: var(--display);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.075em;
  font-size: 0.8125rem;
  color: var(--navy);
  display: flex;
  align-items: center;
  gap: 0.625rem;
}

.legend::before {
  content: "";
  width: 1.75rem;
  height: 2px;
  background: var(--gold);
  flex: none;
}

.legend-light {
  color: var(--gold);
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: 3rem;
  padding: 0.75rem 1.5rem;
  border: 1px solid transparent;
  border-radius: 2px;
  font-family: var(--display);
  font-size: 1.125rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  text-decoration: none;
  cursor: pointer;
  transition:
    background-color 150ms var(--ease),
    border-color 150ms var(--ease),
    color 150ms var(--ease);
}

/* Red is reserved: the request action, and nothing else. */
.btn-request {
  background: var(--red);
  border-color: var(--red);
  color: #fff;
}

.btn-request:hover {
  background: var(--red-deep);
  border-color: var(--red-deep);
  color: #fff;
}

.btn-line {
  background: transparent;
  border-color: var(--rule);
  color: var(--navy-deep);
}

.btn-line:hover {
  border-color: var(--navy);
  background: var(--navy-wash);
  color: var(--navy-deep);
}

.btn-line-light {
  background: transparent;
  border-color: var(--on-navy-rule);
  color: #fff;
}

.btn-line-light:hover {
  border-color: rgba(255, 255, 255, 0.75);
  background: rgba(255, 255, 255, 0.08);
  color: #fff;
}

.btn-solid-light {
  background: #fff;
  border-color: #fff;
  color: var(--navy-deep);
}

.btn-solid-light:hover {
  background: var(--navy-wash);
  border-color: var(--navy-wash);
  color: var(--navy-deep);
}

.btn-block {
  width: 100%;
}

/* ---------- Header ---------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 40;
  background: var(--paper);
  border-bottom: 1px solid var(--rule);
}

/* The header is sticky, so anything jumped to must clear it rather than land
   underneath it. */
section[id],
h1[id],
h2[id] {
  scroll-margin-top: 6rem;
}

.header-inner {
  position: relative;
  display: flex;
  align-items: center;
  gap: 1.5rem;
  min-height: 96px;
}

.brand {
  display: block;
  flex: none;
  text-decoration: none;
}

/* Sized by HEIGHT, not width. The bar's height is the design constant, so the
   lockup is fitted to it — a replacement asset with a different aspect ratio
   then still clears the rule instead of silently resizing the header. The
   supplied artwork is trimmed to its ink, so the breathing room is the
   difference between this and .header-inner's min-height, not padding baked
   into the file. */
.brand img {
  height: 80px;
  width: auto;
}

.site-nav {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 0.25rem;
}

.nav-link {
  position: relative;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 0.875rem;
  font-family: var(--display);
  font-size: 1.0625rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ink);
  text-decoration: none;
  transition: color 150ms var(--ease);
}

.nav-link::after {
  content: "";
  position: absolute;
  left: 0.875rem;
  right: 0.875rem;
  bottom: 0.5rem;
  height: 2px;
  background: var(--navy);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 180ms var(--ease);
}

.nav-link:hover {
  color: var(--navy);
}

/* One underline rule for all three kinds of "you are here": the current page,
   the current section of the current page (aria-current="location", written by
   the scroll spy), and the trade group a service page belongs to. */
.nav-link:hover::after,
.nav-link[aria-current]::after {
  transform: scaleX(1);
}

.nav-link[aria-current] {
  color: var(--navy);
}

/* ---------- Services disclosure menu ---------- */
.nav-group {
  position: relative;
  display: flex;
}

/* A button inherits none of the page's type, so the nav face is restated here
   rather than left to .nav-link — this rule sits after it and would otherwise
   win. `font: inherit` is the wrong fix: it pulls in the body face, and Barlow
   beside Barlow Condensed reads as a wider, larger word. */
.nav-disclosure {
  border: 0;
  background: none;
  cursor: pointer;
  font-family: var(--display);
  font-size: 1.0625rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink);
}

/* inline-block is load-bearing: width and height do nothing on an inline box,
   and the caret collapses to a stray corner without it. */
.nav-caret {
  display: inline-block;
  width: 0.4rem;
  height: 0.4rem;
  margin-left: 0.45rem;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: translateY(-0.1rem) rotate(45deg);
  transition: transform 150ms var(--ease);
}

.nav-disclosure[aria-expanded="true"] {
  color: var(--navy);
}

.nav-disclosure[aria-expanded="true"] .nav-caret {
  transform: translateY(0.05rem) rotate(225deg);
}

/* The panel commits to an edge rather than an elevation, like the form panel. */
.nav-menu {
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 50;
  min-width: 17rem;
  margin: 0;
  padding: 0.375rem 0;
  list-style: none;
  background: var(--paper);
  border: 1px solid var(--navy-deep);
}

.nav-menu[hidden] {
  display: none;
}

.nav-menu a {
  display: flex;
  align-items: center;
  min-height: 44px;
  padding: 0.5rem 1rem;
  font-family: var(--display);
  font-size: 1rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--ink);
  text-decoration: none;
  transition: background-color 150ms var(--ease);
}

/* The bearing stays with the trade here too — the menu is the dial, listed. */
.nav-menu a b {
  flex: none;
  width: 2.25rem;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.09em;
  color: var(--gold-ink);
}

.nav-menu a:hover,
.nav-menu a:focus-visible {
  background: var(--navy-wash);
  color: var(--navy);
}

.nav-menu a[aria-current="page"] {
  color: var(--navy);
}

.nav-menu-foot {
  border-top: 1px solid var(--rule-soft);
  margin-top: 0.375rem;
  padding-top: 0.375rem;
}

.nav-menu-foot a {
  font-size: 0.875rem;
  letter-spacing: 0.075em;
  color: var(--ink-soft);
}

.nav-menu-foot a b {
  display: none;
}

.nav-phone {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 0.875rem;
  margin-left: 0.5rem;
  font-family: var(--display);
  font-size: 1.125rem;
  font-weight: 700;
  letter-spacing: 0.01em;
  color: var(--navy-deep);
  text-decoration: none;
  border-left: 1px solid var(--rule);
}

.nav-phone:hover {
  color: var(--navy);
}

.site-nav .btn {
  min-height: 44px;
  padding: 0 1.125rem;
  font-size: 1rem;
  margin-left: 0.5rem;
}

.nav-toggle {
  display: none;
  margin-left: auto;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid var(--rule);
  border-radius: 2px;
  background: transparent;
  cursor: pointer;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 5px;
}

.nav-toggle span {
  display: block;
  width: 20px;
  height: 2px;
  background: var(--navy-deep);
  transition:
    transform 180ms var(--ease),
    opacity 120ms linear;
}

.nav-toggle[aria-expanded="true"] span:nth-child(1) {
  transform: translateY(7px) rotate(45deg);
}

.nav-toggle[aria-expanded="true"] span:nth-child(2) {
  opacity: 0;
}

.nav-toggle[aria-expanded="true"] span:nth-child(3) {
  transform: translateY(-7px) rotate(-45deg);
}

/* ---------- Hero ---------- */
.hero {
  background: var(--navy-wash);
  border-bottom: 1px solid var(--rule);
  padding: clamp(3rem, 6vw, 5.5rem) 0 clamp(3rem, 6vw, 5rem);
}

.hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.92fr);
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: center;
}

.hero h1 {
  font-size: clamp(2.75rem, 6.4vw, 5.5rem);
  line-height: 0.88;
  margin: 0;
}

.hero h1 em {
  font-style: normal;
  color: var(--navy);
}

.hero-lead {
  max-width: 36ch;
  margin-top: 1.5rem;
  font-size: 1.1875rem;
  line-height: 1.6;
  color: var(--ink-soft);
}

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: 2rem;
}

.hero-note {
  margin-top: 1.25rem;
  font-size: 0.9375rem;
  color: var(--ink-soft);
  max-width: 52ch;
}

.hero-note strong {
  color: var(--navy-deep);
  font-weight: 600;
}

/* ---------- Compass dial: eight trades on eight bearings ---------- */
.dial {
  position: relative;
  aspect-ratio: 1;
  width: 100%;
  max-width: 540px;
  margin-inline: auto;
}

.dial-ring {
  position: absolute;
  inset: 15%;
  border: 1px dashed var(--rule);
  border-radius: 50%;
}

.dial-ring::after {
  content: "";
  position: absolute;
  inset: 13%;
  border: 1px solid var(--rule-soft);
  border-radius: 50%;
}

/* The compass is the brand mark. It stays circular at every size, no matter
   what the container does. */
.dial-mark {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 34%;
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
}

.dial-caption {
  position: absolute;
  left: 50%;
  bottom: -0.5rem;
  transform: translateX(-50%);
  font-family: var(--display);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.075em;
  font-size: 0.75rem;
  color: var(--ink-soft);
  white-space: nowrap;
}

/* Bearings on the ring. Kept in CSS rather than inline styles so the mobile
   block can override a position — an inline style would win over any rule. */
.dial-item[data-bearing="n"]  { --x: 0%;       --y: -34%; }
.dial-item[data-bearing="ne"] { --x: 24.04%;   --y: -24.04%; }
.dial-item[data-bearing="e"]  { --x: 34%;      --y: 0%; }
.dial-item[data-bearing="se"] { --x: 24.04%;   --y: 24.04%; }
.dial-item[data-bearing="s"]  { --x: 0%;       --y: 34%; }
.dial-item[data-bearing="sw"] { --x: -24.04%;  --y: 24.04%; }
.dial-item[data-bearing="w"]  { --x: -34%;     --y: 0%; }
.dial-item[data-bearing="nw"] { --x: -24.04%;  --y: -24.04%; }

.dial-item {
  position: absolute;
  top: calc(50% + var(--y));
  left: calc(50% + var(--x));
  transform: translate(-50%, -50%);
  width: 8.75rem;
  padding: 0.25rem 0.5rem;
  background: var(--navy-wash);
  font-family: var(--display);
  font-weight: 600;
  font-size: 1.0625rem;
  line-height: 1.05;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  text-align: center;
  color: var(--navy-deep);
}

.dial-item b {
  display: block;
  font-family: var(--body);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  color: var(--gold-ink);
  margin-bottom: 0.125rem;
}

/* ---------- The year band ---------- */
.year {
  background: var(--navy-deep);
  color: var(--on-navy);
  padding: clamp(3rem, 5vw, 4.5rem) 0 clamp(2.5rem, 4vw, 3.5rem);
  position: relative;
  /* impeccable-disable-line clipped-overflow-container -- the only positioned
     child this clips is the decorative compass watermark; the needle lives
     inside .year-scroll and is never cut. */
  overflow: hidden;
}

.year::before {
  content: "";
  position: absolute;
  right: -6rem;
  top: -6rem;
  width: 26rem;
  height: 26rem;
  background: url("assets/compass-mark.webp") center / contain no-repeat;
  opacity: 0.07;
  pointer-events: none;
}

.year-head {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.85fr);
  gap: 2rem clamp(2rem, 5vw, 4rem);
  align-items: end;
  margin-bottom: clamp(2rem, 4vw, 3rem);
}

.year-head h2 {
  font-size: clamp(2rem, 3.6vw, 3.125rem);
  margin-top: 1rem;
}

.year-head p {
  color: var(--on-navy-soft);
  max-width: 48ch;
}

/* The chart runs the full width of the viewport, not the text container —
   twelve columns need the room, and a chart wants its own edges. */
.year-scroll {
  position: relative;
  overflow-x: auto;
  overflow-y: hidden;
  padding: 2.75rem 1.25rem 0;
  scrollbar-width: thin;
  scrollbar-color: var(--on-navy-rule) transparent;
}

.year-plot {
  position: relative;
  min-width: 940px;
}

.year-track {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  border-top: 2px solid var(--gold);
  list-style: none;
  margin: 0;
  padding: 0;
}

.month {
  position: relative;
  padding: 1rem 0.875rem 1.375rem 0.75rem;
  border-right: 1px solid var(--on-navy-rule);
  min-height: 8.5rem;
}

.month:first-child {
  border-left: 1px solid var(--on-navy-rule);
}

/* gold degree tick at the head of every month */
.month::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 1px;
  height: 0.625rem;
  background: var(--gold);
}

.month-name {
  font-family: var(--display);
  font-weight: 700;
  font-size: 1.375rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--on-navy-soft);
  transition: color 200ms var(--ease);
}

.month-note {
  margin-top: 0.625rem;
  font-size: 0.875rem;
  line-height: 1.45;
  color: var(--on-navy-soft);
  transition: color 200ms var(--ease);
}

.month[data-current] {
  background: rgba(255, 255, 255, 0.08);
}

.month[data-current] .month-name,
.month[data-current] .month-note {
  color: #fff;
}

/* The needle. Parked at January until script.js sweeps it to the real month. */
.needle {
  position: absolute;
  top: -2.75rem;
  /* Stops just inside the cell — a needle points at the month, it does not
     draw a line through the month's own text. */
  height: 4.25rem;
  left: calc((var(--month, 0) + 0.5) * (100% / 12));
  width: 2px;
  margin-left: -1px;
  background: var(--red);
  transition: left 900ms var(--ease);
  pointer-events: none;
}

.needle::before {
  content: "";
  position: absolute;
  top: 2.5rem;
  left: 50%;
  transform: translateX(-50%);
  border-left: 6px solid transparent;
  border-right: 6px solid transparent;
  border-top: 8px solid var(--red);
}

.needle-label {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  background: var(--red);
  color: #fff;
  padding: 0.25rem 0.625rem;
  font-family: var(--display);
  font-weight: 700;
  font-size: 0.8125rem;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  white-space: nowrap;
  box-shadow: var(--lift-sm);
}

/* The needle month gets a real sentence; the chart itself stays label-only. */
.year-now {
  position: relative;
  margin-top: 2rem;
  padding: 1.5rem clamp(1.25rem, 2.5vw, 2rem);
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--on-navy-rule);
  max-width: 46rem;
}

.year-now-head {
  font-family: var(--display);
  font-weight: 600;
  font-size: 0.8125rem;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--gold);
}

.year-now-detail {
  margin-top: 0.5rem;
  font-size: 1.25rem;
  line-height: 1.45;
  color: #fff;
  max-width: 44ch;
}

.year-now .btn {
  margin-top: 1.5rem;
}

.year-foot {
  position: relative;
  margin-top: 1.5rem;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem 1.5rem;
  font-size: 0.9375rem;
  color: var(--on-navy-soft);
  max-width: 62ch;
}

.year-foot a {
  color: #fff;
  font-weight: 600;
}

/* ---------- Coverage ledger ----------
   A ruled index, not a stack of cards: the trade name sits BESIDE its
   description, so heading-rhythm's above/below model does not apply here. */
/* impeccable-disable heading-rhythm -- ledger rows set headings beside their
   content, not above it */
.coverage {
  padding: clamp(3.5rem, 6vw, 6rem) 0;
}

.section-head {
  max-width: 62ch;
  margin-bottom: clamp(2rem, 4vw, 3rem);
}

.section-head h2 {
  font-size: clamp(2rem, 3.6vw, 3.125rem);
  margin-top: 1rem;
}

.section-head > :first-child,
.year-head > div > :first-child,
.band-grid > div > :first-child,
.convert > :first-child {
  margin-top: 0;
}

.section-head p {
  margin-top: 1.25rem;
  color: var(--ink-soft);
  max-width: 58ch;
}

.ledger {
  border-top: 2px solid var(--navy-deep);
}

.ledger-row {
  display: grid;
  grid-template-columns: minmax(11rem, 0.9fr) minmax(0, 1.6fr) minmax(0, 1fr);
  gap: 0.5rem clamp(1.5rem, 3vw, 3rem);
  align-items: baseline;
  padding: 1.75rem 0.75rem 1.5rem;
  border-bottom: 1px solid var(--rule-soft);
  transition: background-color 150ms var(--ease);
}

.ledger-row:hover {
  background: var(--navy-wash);
}

.ledger-row h3 {
  font-size: 1.4375rem;
  letter-spacing: 0.015em;
  color: var(--navy-deep);
}

/* On the home page every trade name is the door to its own page. Hover tinting
   is not an affordance on a phone, and most of this audience is on one, so the
   link carries the link colour and a standing bearing arrow. */
.ledger-row h3 a,
.bearing-row .bearing-name {
  color: var(--navy);
  text-decoration: none;
}

.ledger-row h3 a::after,
.bearing-row .bearing-name::after {
  content: "→";
  display: inline-block;
  margin-left: 0.5rem;
  color: var(--gold-ink);
  transition: transform 150ms var(--ease);
}

.ledger-row:hover h3 a::after,
.ledger-row h3 a:focus-visible::after,
.bearing-row:hover .bearing-name::after,
.bearing-row:focus-visible .bearing-name::after {
  transform: translateX(3px);
}

.ledger-row h3 a:hover,
.ledger-row h3 a:focus-visible {
  text-decoration: underline;
  text-underline-offset: 0.16em;
}

.ledger-row > p {
  color: var(--ink-soft);
  font-size: 1rem;
}

.ledger-calls {
  font-size: 0.875rem;
  line-height: 1.5;
  color: var(--ink-soft);
}

.ledger-calls b {
  display: block;
  font-family: var(--display);
  font-weight: 600;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--navy);
  margin-bottom: 0.25rem;
}

.coverage-foot {
  margin-top: 2.25rem;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem 1.5rem;
  color: var(--ink-soft);
  max-width: 62ch;
}

/* ---------- Navy content band ---------- */
.band {
  background: var(--navy-deep);
  color: var(--on-navy);
  padding: clamp(3.5rem, 6vw, 5.5rem) 0;
  position: relative;
  overflow: hidden;
}

.band-ink {
  background: var(--navy-ink);
}

.band::before {
  content: "";
  position: absolute;
  left: -8rem;
  bottom: -10rem;
  width: 30rem;
  height: 30rem;
  background: url("assets/compass-mark.webp") center / contain no-repeat;
  opacity: 0.06;
  pointer-events: none;
}

/* Suppress the compass mark when a band follows another band that already
   carries it — two marks this close read as a repeat, not a motif. */
.band-nomark::before {
  content: none;
}

.band-grid {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
  gap: clamp(2rem, 5vw, 4rem);
  align-items: start;
}

.band h2 {
  font-size: clamp(2rem, 3.6vw, 3.125rem);
  margin-top: 1rem;
}

.band p {
  margin-top: 1.25rem;
  color: var(--on-navy-soft);
  max-width: 56ch;
}

.band .btn {
  margin-top: 2rem;
}

.facts {
  margin: 0;
  border-top: 1px solid var(--on-navy-rule);
}

.facts > div {
  display: grid;
  grid-template-columns: 8.5rem minmax(0, 1fr);
  gap: 1rem;
  padding: 0.875rem 0;
  border-bottom: 1px solid var(--on-navy-rule);
  font-size: 0.9375rem;
}

.facts dt {
  font-family: var(--display);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.075em;
  font-size: 0.8125rem;
  color: var(--gold);
  padding-top: 0.15rem;
}

.facts dd {
  margin: 0;
  color: #fff;
}

.facts a {
  color: #fff;
  font-weight: 600;
  white-space: nowrap;
}

/* ---------- Closing call to action ---------- */
.close-cta {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 2rem clamp(2rem, 5vw, 4rem);
  align-items: center;
}

.close-cta h2 {
  font-size: clamp(2.25rem, 4.4vw, 3.75rem);
}

.close-cta p {
  margin-top: 1rem;
  color: var(--on-navy-soft);
}

.close-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
}

/* ---------- Footer ---------- */
.site-footer {
  background: var(--navy-ink);
  color: var(--on-navy-soft);
  padding: clamp(3rem, 5vw, 4rem) 0 2rem;
  font-size: 0.9375rem;
}

.footer-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.3fr) repeat(3, minmax(0, 1fr));
  gap: 2.5rem clamp(1.5rem, 3vw, 3rem);
}

.footer-brand img {
  width: 3.25rem;
  height: auto;
}

.footer-brand strong {
  display: block;
  font-family: var(--display);
  font-weight: 700;
  font-size: 1.25rem;
  line-height: 1.1;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: #fff;
  margin-top: 1rem;
}

.footer-brand p {
  margin-top: 0.75rem;
  max-width: 32ch;
}

.site-footer h2 {
  font-size: 0.8125rem;
  letter-spacing: 0.1em;
  font-weight: 600;
  color: var(--gold);
  margin-bottom: 1rem;
}

.site-footer ul {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 0.625rem;
}

.site-footer a {
  color: #fff;
  text-decoration: none;
}

.site-footer a:hover {
  color: var(--gold);
  text-decoration: underline;
}

.footer-legal {
  margin-top: clamp(2.5rem, 4vw, 3.5rem);
  padding-top: 1.5rem;
  border-top: 1px solid var(--on-navy-rule);
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.5rem;
  font-size: 0.875rem;
}

/* Studio credit sits opposite the copyright, and stays quieter than the
   footer's navigation links — it is an attribution, not a destination. */
.footer-credit {
  margin-left: auto;
}

.site-footer .footer-credit a {
  color: inherit;
  text-decoration: none;
}

.site-footer .footer-credit a:hover {
  color: var(--gold);
  text-decoration: underline;
}

/* ---------- Page header (blog + contact) ---------- */
.page-head {
  position: relative;
  overflow: hidden;
  background: var(--navy-wash);
  border-bottom: 1px solid var(--rule);
  padding: clamp(2.5rem, 5vw, 4rem) 0 clamp(2.5rem, 4vw, 3.5rem);
}

.page-head::before {
  content: "";
  position: absolute;
  right: -5rem;
  top: 50%;
  transform: translateY(-50%);
  width: 24rem;
  height: 24rem;
  background: url("assets/compass-mark.webp") center / contain no-repeat;
  opacity: 0.09;
  pointer-events: none;
}

.page-head > * {
  position: relative;
}

.page-head h1 {
  font-size: clamp(2.25rem, 4.6vw, 3.75rem);
  margin-top: 0;
  max-width: 22ch;
}

.page-head .lead {
  margin-top: 1.25rem;
  max-width: 58ch;
  font-size: 1.125rem;
  color: var(--ink-soft);
}

.crumbs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  padding: 0;
  margin: 0 0 1.5rem;
  list-style: none;
  font-size: 0.875rem;
  color: var(--ink-soft);
}

.crumbs li + li::before {
  content: "/";
  margin-right: 0.5rem;
  color: var(--rule);
}

.byline {
  margin-top: 1.75rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--rule);
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.5rem;
  font-size: 0.875rem;
  color: var(--ink-soft);
}

.byline strong {
  color: var(--navy-deep);
  font-weight: 600;
}

/* ---------- Article ---------- */
.article {
  padding: clamp(2.5rem, 5vw, 4rem) 0 clamp(3.5rem, 6vw, 5.5rem);
}

.article p {
  margin-top: 1.5rem;
  font-size: 1.125rem;
  line-height: 1.7;
  max-width: 68ch;
}

.article .intro {
  font-size: 1.25rem;
  line-height: 1.6;
  color: var(--navy-deep);
  margin-top: 0;
}

.article h2 {
  font-size: clamp(1.625rem, 2.6vw, 2.125rem);
  margin-top: 3.25rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--rule-soft);
  color: var(--navy-deep);
}

.article ul {
  margin-top: 1.5rem;
  padding-left: 0;
  list-style: none;
  max-width: 68ch;
  border-top: 1px solid var(--rule-soft);
}

.article ul li {
  position: relative;
  padding: 0.75rem 0 0.75rem 1.75rem;
  border-bottom: 1px solid var(--rule-soft);
}

.article ul li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 1.4rem;
  width: 0.5rem;
  height: 0.5rem;
  background: var(--gold);
}

/* The article's lead figure is a strip of the year with this article's month
   marked — the blog inherits the chart instead of needing photography. */
.strip-figure {
  margin: 0 0 3rem;
}

.strip {
  border-top: 2px solid var(--navy-deep);
  border-bottom: 1px solid var(--rule);
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
}

.strip span {
  position: relative;
  padding: 1.5rem 0 0.5rem;
  text-align: center;
  font-family: var(--display);
  font-weight: 600;
  font-size: 0.8125rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--ink-soft);
  border-right: 1px solid var(--rule-soft);
}

.strip span:last-child {
  border-right: 0;
}

.strip span::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 1px;
  height: 0.5rem;
  background: var(--rule);
}

.strip span[data-mark] {
  background: var(--navy-wash);
  color: var(--navy-deep);
  font-weight: 700;
}

.strip span[data-mark]::after {
  content: "";
  position: absolute;
  top: -2px;
  left: 0;
  right: 0;
  height: 3px;
  background: var(--red);
}

.strip-figure figcaption {
  margin-top: 0.75rem;
  font-size: 0.875rem;
  color: var(--ink-soft);
  max-width: 62ch;
}

/* Inline conversion card */
.convert {
  margin-top: 3.25rem;
  padding: clamp(1.5rem, 3vw, 2.25rem);
  background: var(--navy-wash);
  border: 1px solid var(--rule);
}

.convert h2 {
  border: 0;
  padding: 0;
  margin: 0.75rem 0 0;
  font-size: clamp(1.5rem, 2.4vw, 1.875rem);
  color: var(--navy-deep);
}

.convert p {
  margin-top: 0.75rem;
  font-size: 1.0625rem;
  color: var(--ink-soft);
  max-width: 62ch;
}

.convert .btn {
  margin-top: 1.5rem;
}

/* ---------- Service pages ----------
   A trade page is that trade's slice of the maintenance year. The chart is the
   same instrument as the home page — same component, same needle, same script;
   only which months are marked changes. */

/* A month this trade belongs in: the degree tick opens into a full gold bar. */
.month[data-season="peak"]::before {
  width: 100%;
  height: 3px;
}

/* Both markings can land on one cell, and "now" outranks "in season". */
.month[data-season="peak"]:not([data-current]) {
  background: rgba(244, 178, 35, 0.09);
}

.month[data-season="peak"]:not([data-current]) .month-name {
  color: var(--gold);
}

.season-key::before {
  content: "";
  display: inline-block;
  width: 1.75rem;
  height: 3px;
  margin-right: 0.625rem;
  vertical-align: 0.22em;
  background: var(--gold);
}

.head-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: 2rem;
}

/* The scope index carries no third column, so the description takes the room
   and its "typical calls" line sits under it rather than beside it. */
.ledger-pair {
  grid-template-columns: minmax(11rem, 0.9fr) minmax(0, 2.2fr);
}

.ledger-body > p:not(.ledger-calls) {
  color: var(--ink-soft);
  font-size: 1rem;
}

.ledger-body .ledger-calls {
  margin-top: 0.75rem;
}

/* Field guide: what the board sees, beside what it usually turns out to be.
   Ruled rows rather than a table — this gets read on a phone, on the property. */
.diagnose {
  padding: clamp(3.5rem, 6vw, 6rem) 0;
  background: var(--navy-wash);
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}

.diagnose-list {
  margin: 0;
  border-top: 2px solid var(--navy-deep);
}

.diagnose-list > div {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.35fr);
  gap: 0.375rem clamp(1.5rem, 3vw, 3rem);
  align-items: baseline;
  padding: 1.5rem 0.75rem;
  border-bottom: 1px solid var(--rule);
}

/* These are sentences, not instrument labels, so they stay in the body face. */
.diagnose-list dt {
  font-weight: 600;
  color: var(--navy-deep);
}

.diagnose-list dd {
  margin: 0;
  color: var(--ink-soft);
}

/* The other seven bearings — the coverage argument, kept live on every trade. */
.bearings {
  padding: clamp(3.5rem, 6vw, 6rem) 0;
}

.bearing-index {
  border-top: 2px solid var(--navy-deep);
}

.bearing-row {
  display: grid;
  grid-template-columns: 3rem minmax(10rem, 0.9fr) minmax(0, 1.8fr);
  gap: 0.375rem clamp(1.25rem, 2.5vw, 2.5rem);
  align-items: baseline;
  padding: 1.25rem 0.75rem;
  border-bottom: 1px solid var(--rule-soft);
  color: inherit;
  text-decoration: none;
  transition: background-color 150ms var(--ease);
}

.bearing-row:hover {
  background: var(--navy-wash);
}

.bearing-row b {
  font-family: var(--display);
  font-weight: 600;
  font-size: 0.8125rem;
  letter-spacing: 0.09em;
  color: var(--gold-ink);
}

.bearing-name {
  font-family: var(--display);
  font-weight: 700;
  font-size: 1.25rem;
  text-transform: uppercase;
  letter-spacing: 0.015em;
}

.bearing-row:hover .bearing-name,
.bearing-row:focus-visible .bearing-name {
  text-decoration: underline;
  text-underline-offset: 0.18em;
}

.bearing-note {
  color: var(--ink-soft);
  font-size: 1rem;
}

/* ---------- Contact ---------- */
.contact {
  padding: clamp(2.5rem, 5vw, 4rem) 0 clamp(3.5rem, 6vw, 5.5rem);
}

.contact-grid {
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
  gap: clamp(2rem, 5vw, 4rem);
  align-items: start;
}

.contact-details {
  margin: 0;
  border-top: 2px solid var(--navy-deep);
}

.contact-details > div {
  display: grid;
  gap: 0.375rem;
  padding: 1.25rem 0;
  border-bottom: 1px solid var(--rule-soft);
}

.contact-details dt {
  font-family: var(--display);
  font-weight: 600;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--navy);
}

.contact-details dd {
  margin: 0;
  font-size: 1.0625rem;
}

.contact-details dd a {
  font-weight: 600;
  text-decoration: none;
}

.contact-details dd a:hover {
  text-decoration: underline;
}

.contact-details .urgent {
  color: var(--red);
  font-weight: 600;
}

.contact-aside {
  margin-top: 2rem;
  padding: 1.5rem;
  background: var(--navy-wash);
  border: 1px solid var(--rule);
}

.contact-aside h2 {
  font-size: 1.25rem;
  color: var(--navy-deep);
}

.contact-aside p {
  margin-top: 0.75rem;
  font-size: 0.9375rem;
  color: var(--ink-soft);
}

/* ---------- Form ---------- */
/* The honeypot. Moved out of view rather than display:none, because some bots
   skip fields that are explicitly hidden. Never give this a visible style. */
.hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* One edge or one elevation, not both: this panel commits to the edge. */
.form-panel {
  padding: clamp(1.5rem, 3vw, 2.25rem);
  border: 1px solid var(--navy-deep);
  background: var(--paper);
}

.form-panel > h2 {
  font-size: 1.75rem;
  color: var(--navy-deep);
}

.form-panel > h2 + p {
  margin-top: 0.75rem;
  color: var(--ink-soft);
  font-size: 0.9375rem;
}

.form {
  display: grid;
  gap: 1.25rem;
  margin-top: 1.75rem;
}

.form-row {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.25rem;
}

.field {
  display: grid;
  gap: 0.375rem;
}

.field > .label {
  font-family: var(--display);
  font-weight: 600;
  font-size: 0.8125rem;
  text-transform: uppercase;
  letter-spacing: 0.075em;
  color: var(--navy-deep);
}

.field > .label em {
  font-style: normal;
  color: var(--red);
}

.field .optional {
  font-family: var(--body);
  font-size: 0.75rem;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink-soft);
}

input,
select,
textarea {
  width: 100%;
  min-height: 3rem;
  padding: 0.6875rem 0.875rem;
  border: 1px solid var(--rule);
  border-radius: 2px;
  background: var(--paper);
  font-family: var(--body);
  font-size: 1rem;
  color: var(--ink);
  transition:
    border-color 150ms var(--ease),
    box-shadow 150ms var(--ease);
}

textarea {
  resize: vertical;
  min-height: 8rem;
  line-height: 1.6;
}

select {
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--navy) 50%),
    linear-gradient(135deg, var(--navy) 50%, transparent 50%);
  background-position: calc(100% - 1.125rem) 1.375rem,
    calc(100% - 0.75rem) 1.375rem;
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
  padding-right: 2.5rem;
}

input::placeholder,
textarea::placeholder {
  color: #64798d;
}

input:hover,
select:hover,
textarea:hover {
  border-color: #93a8bb;
}

input:focus,
select:focus,
textarea:focus {
  outline: none;
  border-color: var(--navy);
  box-shadow: inset 0 0 0 1px var(--navy);
}

input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  outline: 2px solid var(--navy);
  outline-offset: 2px;
}

input[aria-invalid="true"],
select[aria-invalid="true"],
textarea[aria-invalid="true"] {
  border-color: var(--red);
  box-shadow: inset 0 0 0 1px var(--red);
}

.field-error {
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--red);
}

.field-error:empty {
  display: none;
}

.form button[disabled] {
  opacity: 0.55;
  cursor: not-allowed;
}

.form-status {
  margin: 0;
  min-height: 1.5rem;
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--navy-deep);
}

.form-status[data-tone="error"] {
  color: var(--red);
}

.form-consent {
  font-size: 0.8125rem;
  color: var(--ink-soft);
  line-height: 1.5;
  max-width: 62ch;
}

/* Success state */
.form-done {
  display: grid;
  gap: 1rem;
  justify-items: start;
  padding: 0.5rem 0;
}

.form-done img {
  width: 3.5rem;
}

.form-done h2 {
  font-size: 1.875rem;
  color: var(--navy-deep);
}

.form-done p {
  color: var(--ink-soft);
  max-width: 46ch;
}

/* ---------- Responsive ---------- */
@media (max-width: 1080px) {
  .hero-grid {
    grid-template-columns: 1fr;
  }

  .dial {
    max-width: 470px;
  }

  .ledger-row {
    grid-template-columns: minmax(9rem, 0.8fr) minmax(0, 1.4fr);
  }

  .ledger-calls {
    grid-column: 2;
  }

  .footer-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* The nav collapses earlier than the layout does: Services and About took the
   row past what fits beside the lockup at the old 900px hand-off. Keep this in
   step with the width in initNav's resize handler. */
@media (max-width: 1024px) {
  .nav-toggle {
    display: inline-flex;
  }

  /* The open panel is a sheet dropping out of the header, so it spans the
     viewport. Going static here hands the containing block to the sticky
     .site-header — anchoring to .header-inner would inset it by the container
     gutter and make it read as a floating card. */
  .header-inner {
    position: static;
  }

  .site-nav {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    /* Matches the container gutter so nav items line up under the logo. */
    padding: 0.5rem 1.25rem 1.5rem;
    background: var(--paper);
    border-bottom: 1px solid var(--rule);
    box-shadow: var(--lift-sm);
  }

  .site-nav[data-open="true"] {
    display: flex;
  }

  .nav-link {
    min-height: 52px;
    border-bottom: 1px solid var(--rule-soft);
    padding-inline: 0;
  }

  .nav-link::after {
    left: 0;
    right: auto;
    width: 1.5rem;
    bottom: 0.75rem;
  }

  .nav-phone {
    min-height: 52px;
    margin-left: 0;
    padding-inline: 0;
    border-left: 0;
    border-bottom: 1px solid var(--rule-soft);
  }

  .site-nav .btn {
    margin-left: 0;
    margin-top: 1rem;
    min-height: 52px;
  }

  .header-inner {
    min-height: 80px;
  }

  .brand img {
    height: 64px;
  }

  /* Inside the stacked panel the menu is part of the list, not a layer over
     it: no border, no absolute positioning, just an indented sub-list. */
  .nav-group {
    display: block;
  }

  .nav-disclosure {
    width: 100%;
    justify-content: space-between;
  }

  .nav-menu {
    position: static;
    min-width: 0;
    padding: 0.25rem 0 0.75rem;
    border: 0;
    background: none;
  }

  .nav-menu a {
    min-height: 48px;
    padding: 0.375rem 0 0.375rem 0.25rem;
    font-size: 0.9375rem;
    color: var(--ink-soft);
  }

  .nav-menu a:hover,
  .nav-menu a:focus-visible {
    background: none;
  }

  .nav-menu-foot {
    margin-top: 0.25rem;
    padding-top: 0.5rem;
  }
}

@media (max-width: 900px) {
  .year-head,
  .band-grid,
  .contact-grid,
  .close-cta {
    grid-template-columns: 1fr;
  }

  .close-cta {
    align-items: start;
  }
}

@media (max-width: 720px) {
  body {
    font-size: 1rem;
  }

  .brand img {
    height: 56px;
  }

  /* The dial stays a dial. Same polar coordinates as desktop — only the label
     box and type scale down, both in percentages so the ring holds its
     proportions from 320px up. */
  .dial {
    /* Uses the full container on a phone; capped so it does not balloon and go
       airy on a large phone or a small tablet still inside this breakpoint. */
    max-width: 30rem;
    margin-top: 0.5rem;
  }

  .dial-mark {
    width: 33%;
  }

  .dial-item {
    width: 25%;
    padding: 0.125rem 0.25rem;
    font-size: clamp(0.75rem, 3.3vw, 0.9375rem);
    line-height: 1.1;
  }

  .dial-item b {
    font-size: 0.6875rem;
    letter-spacing: 0.1em;
  }

  /* E and W sit on the axis with the most room, so they get a wider box and
     read outward from the mark. */
  .dial-item[data-bearing="e"] {
    width: 27%;
    text-align: left;
  }

  .dial-item[data-bearing="w"] {
    width: 27%;
    text-align: right;
  }

  /* N and S ride further out than the diagonals. At mobile label heights the
     34% ring puts them within a few pixels of NE/NW and SE/SW; the vertical
     axis has the headroom to spare, so they take it. */
  .dial-item[data-bearing="n"] {
    --y: -41%;
  }

  .dial-item[data-bearing="s"] {
    --y: 41%;
  }

  .dial-caption {
    bottom: -1.5rem;
    font-size: 0.6875rem;
  }

  .ledger-row,
  .ledger-pair,
  .diagnose-list > div {
    grid-template-columns: 1fr;
    gap: 0.5rem;
    padding-inline: 0;
  }

  .ledger-calls {
    grid-column: 1;
  }

  /* The bearing letter keeps its column and the name sits beside it; dropping
     it to its own line would leave a stray "SE" floating above the trade. */
  .bearing-row {
    grid-template-columns: 2.5rem minmax(0, 1fr);
    padding-inline: 0;
  }

  .bearing-note {
    grid-column: 2;
  }

  .form-row {
    grid-template-columns: 1fr;
  }

  .footer-grid {
    grid-template-columns: 1fr;
  }

  .strip span {
    font-size: 0.6875rem;
    letter-spacing: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

@media print {
  .site-header,
  .nav-toggle,
  .close-cta,
  .btn {
    display: none !important;
  }

  body {
    color: #000;
    font-size: 11pt;
  }
}
