/* ==========================================================================
   components.css — concrete UI: buttons, cards, form controls, header,
   footer, step dots, hero, icons.
   --------------------------------------------------------------------------
   Selectors are flat .hs-* class names — no nesting, no specificity wars.
   ========================================================================== */

/* ============================  Buttons  ================================== */

.hs-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  /* v2: slimmer than before — Lewis's pills are short. Vertical padding is
     small; the 44px min-height below still guarantees an accessible target. */
  padding: 0.5em 1.4em;
  border: 2px solid transparent;
  border-radius: var(--radius-pill);
  background: var(--color-accent);
  color: var(--color-accent-ink);
  font-family: var(--font-body);
  /* v2: Lewis's button text is medium weight (not bold) and a touch larger. */
  font-weight: 500;
  font-size: var(--fs-step-1);
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  transition: transform var(--duration-fast) var(--ease-out),
              background-color var(--duration-base) var(--ease-out);
  /* Touch target is at least 44×44 even on the smallest CTAs. */
  min-height: 44px;
}

.hs-btn:hover { transform: translateY(-1px); }
.hs-btn:active { transform: translateY(0); }

.hs-btn[disabled],
.hs-btn[aria-disabled="true"] {
  opacity: 0.5;
  cursor: not-allowed;
  transform: none;
}

/* Saffron CTAs use plum focus ring for 4.5:1 contrast. */
.hs-btn:focus-visible {
  outline: 3px solid var(--color-focus-ring-on-saffron);
  outline-offset: 3px;
}

/* Secondary — outlined plum on cream. Medium weight like the filled CTA. */
.hs-btn--ghost {
  background: transparent;
  color: var(--color-text);
  border-color: var(--color-border);
}
.hs-btn--ghost:focus-visible {
  outline-color: var(--color-focus-ring);
}

/* Tertiary — plain link with arrow. */
.hs-btn--link {
  background: transparent;
  color: var(--color-text);
  padding-inline: 0;
  font-weight: 600;
}

/* Plum-filled pill — used for the case-study Back/Next pager (v2). Cream
   text on plum clears 4.5:1; the focus ring switches to saffron to stay
   visible against the dark fill. */
.hs-btn--plum {
  background: var(--color-text);
  color: var(--color-text-on-dark);
}
.hs-btn--plum:focus-visible {
  outline-color: var(--color-focus-ring);
}

/* Right-arrow icon — referenced inline via the .hs-btn__arrow span. */
.hs-btn__arrow {
  display: inline-grid;
  place-items: center;
  width: 1.4em;
  height: 1.4em;
  transition: transform var(--duration-base) var(--ease-out);
}
.hs-btn:hover .hs-btn__arrow { transform: translateX(2px); }
.hs-btn__arrow svg { width: 100%; height: 100%; fill: currentColor; }
/* v2: thinner arrow stroke to match Lewis's lighter "→" (inline SVGs ship at
   2.5; CSS overrides the presentation attribute site-wide). */
.hs-btn__arrow svg path { stroke-width: 2; }
.hs-arrow-btn svg path { stroke-width: 2; }

/* ============================  Header / nav  ============================= */

.hs-header {
  display: block;
  /* v2: the header is a compact white bar with a faint hairline beneath it,
     sitting above the cream page / full-bleed hero (was transparent on
     cream). NOTE: this wrapper is emitted by hs-header.js #render() — the
     class must be present in the live DOM, not just the JS-off fallback. */
  background: var(--hs-white);
  border-bottom: 1px solid var(--color-border-muted);
  padding-block: var(--space-s);
}
@media (min-width: 50rem) {
  .hs-header { padding-block: var(--space-m); }
}

.hs-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-l);
}

/* Wordmark — Lewis's mark is sans-serif (DM Sans), bold, plum, two lines.
   The display serif (DM Serif Display) is reserved for headings; using it
   here re-types the brand and breaks the supplied identity. */
.hs-header__brand {
  display: inline-block;
  color: var(--color-text);
  text-decoration: none;
  font-family: var(--font-body);
  font-weight: 700;
  line-height: 0.98;
  font-size: clamp(1.05rem, 0.95rem + 0.4vw, 1.2rem);
  letter-spacing: -0.01em;
}
.hs-header__brand-mark {
  display: block;
  white-space: pre-line;
}
/* The "&" sits below "Hebble" with a short underline beneath it — that
   underline is the brand's small signature, picked up from the icon. */
.hs-header__brand-amp {
  display: inline-block;
  text-decoration: underline;
  text-decoration-thickness: 0.12em;
  text-underline-offset: 0.12em;
}

/* v2: the brand is now Lewis's supplied wordmark SVG (plum, two-line
   "Hebble & Stone"). Sized by height; the cropped viewBox keeps it tight
   so it reads at header scale without a tall, mostly-empty click target.
   The legacy .hs-header__brand-mark text rules above are retained for the
   JS-off fallback authored inside each page's <hs-header>. */
.hs-header__logo {
  display: block;
  height: clamp(2.25rem, 1.9rem + 1vw, 2.75rem);
  width: auto;
}

.hs-nav {
  display: flex;
  gap: var(--space-l);
  align-items: center;
}

.hs-nav__link {
  /* v2: nav uses the brighter logo plum and a heavier weight (was the darker
     #5A2439 at weight 500, which read as dark grey next to Lewis's nav). */
  color: var(--hs-plum-logo);
  text-decoration: none;
  padding: var(--space-2xs) 0;
  font-size:var(--fs-step-1);
}
.hs-nav__link[aria-current="page"] {
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 0.25em;
}

/* The header "Get started" pill is tighter than the in-body CTAs so it sits
   comfortably inside the compact bar (Lewis's header button is small). Only
   on desktop — on mobile it drops into the nav panel and keeps a 44px tap
   target. */
@media (min-width: 50rem) {
  .hs-nav > .hs-btn {
    font-size: var(--fs-step--1);
    padding: 0.6em 1.15em;
    min-height: 0;
  }
}

/* Mobile: collapse nav links into a disclosure. The button is rendered by
   the <hs-header> custom element only on viewports where it's needed.    */
.hs-header__toggle { display: none; }
@media (max-width: 50rem) {
  .hs-header__toggle {
    display: inline-grid;
    place-items: center;
    width: 44px; height: 44px;
    border: 2px solid var(--color-border);
    background: transparent;
    border-radius: var(--radius-sm);
    cursor: pointer;
  }

  /* Open nav panel. Distinct visual treatment so it reads as a panel
     hovering above the page — not a slim line continuing the header.
     Reasons (we built this site, we're allowed to over-explain):
       – `top: calc(100% + 1rem)` gives the panel a clear gap below the
         hamburger so the two outlines never touch.
       – White surface + plum border + soft shadow distinguishes it from
         the cream page background even for low-contrast vision.
       – Larger tap targets (1rem block padding per link) help motor-
         impaired users hit the right thing.
       – `gap` on the column flex replaces relying on individual margins. */
  .hs-nav {
    position: absolute;
    inset: auto 0 auto auto;
    top: calc(100% + 1rem);
    right: 0;
    min-width: min(20rem, calc(100vw - 2 * var(--gutter)));
    background: var(--color-surface);
    border: 2px solid var(--color-text);
    border-radius: var(--radius-card);
    box-shadow: 0 16px 32px -16px rgba(90, 36, 57, 0.25);
    flex-direction: column;
    align-items: stretch;
    padding: var(--space-s);
    gap: var(--space-3xs);
  }
  .hs-nav[hidden] { display: none; }
  .hs-header__inner { position: relative; }

  .hs-nav__link {
    display: block;
    padding: var(--space-s) var(--space-m);
    border-radius: var(--radius-sm);
    font-size: var(--fs-step-1);
    font-weight: 600;
    line-height: 1.2;
  }
  .hs-nav__link:hover,
  .hs-nav__link:focus-visible {
    background: var(--color-bg-alt);
  }
  .hs-nav__link[aria-current="page"] {
    /* On mobile the current page is signalled with a saffron bar to the
       left of the link rather than the desktop underline — easier to
       see at small sizes. */
    background: var(--color-bg-alt);
    border-left: 4px solid var(--color-accent);
    padding-left: calc(var(--space-m) - 4px);
    text-decoration: none;
  }
  /* The "Get started" CTA in the open nav becomes a full-width button
     so it lands as the obvious primary action. */
  .hs-nav .hs-btn {
    justify-content: center;
    margin-top: var(--space-2xs);
  }
}

/* ============================  Footer  =================================== */

/* v2: the footer now sits on the cream page (was a plum block), with plum
   headings/links and the supplied wordmark in place of a text brand. */
.hs-footer {
  /* The footer's own top padding already separates it from page content, so a
     full 3xl margin on top of that stacked with the last section's bottom
     padding read as too large (most visible on /about under the bone CTA). */
  margin-top: var(--space-l);
  padding-block: var(--space-2xl);
  background: var(--color-bg);
  color: var(--color-text-body);
}
.hs-footer a {
  color: var(--color-text);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.22em;
}
.hs-footer a:hover { text-decoration-thickness: 2px; }
.hs-footer__logo {
  display: block;
  height: clamp(2.5rem, 2rem + 1.4vw, 3.25rem);
  width: auto;
  margin-bottom: var(--space-m);
}
.hs-footer__cols {
  display: grid;
  gap: var(--space-2xl);
  grid-template-columns: repeat(auto-fit, minmax(min(14rem, 100%), 1fr));
  /* v2: footer copy/links sit a notch larger than before. */
  font-size: var(--fs-step-1);
}
.hs-footer__cols ul li { padding-block: var(--space-2xs); }
.hs-footer__cols p { color: var(--color-text-body); max-width: 34ch; }
.hs-footer h2 {
  color: var(--color-text);
  font-size: var(--fs-step-0);
  font-family: var(--font-body);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  margin-bottom: var(--space-m);
}
.hs-footer__legal {
  margin-top: var(--space-2xl);
  padding-top: var(--space-l);
  /* v2: full container-width plum rule (was a narrow, faint sand line that
     only spanned the paragraph's measure). */
  max-width: none;
  border-top: 1px solid var(--color-border);
  font-size: var(--fs-step-0);
  color: var(--color-text-body);
}

/* ============================  Hero  ===================================== */

.hs-hero {
  padding-block: var(--space-2xl) var(--space-3xl);
  /* v2: full-bleed rose band with rounded BOTTOM corners only — square at
     the top where it meets the white header, curving into the cream below. */
  background: var(--color-bg-rose);
  border-radius: 0 0 2.5rem 2.5rem;
}
.hs-hero__grid {
  display: grid;
  gap: var(--space-xl);
  align-items: end;
}
@media (min-width: 60rem) {
  .hs-hero__grid { grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); }
}
.hs-hero__title {
  font-size: var(--fs-step-5);
  margin-bottom: var(--space-m);
}
.hs-hero__lede {
  font-size: var(--fs-step-1);
  font-weight: 500;
  color: var(--hs-plum);
  max-width: 36ch;
  margin-bottom: var(--space-l);
}

/* Hero standfirst — the intro line under a page H1 on /about, /audit,
   /our-work, /blog and single posts. Standardised so they all match: one size
   (step-1, ~20px) and a touch more breathing room under the headline than the
   default 16px stack gap. (Home's hero lede is a separate component above,
   by design.) */
.hs-hero-lede {
  font-size: var(--fs-step-1);
  color: var(--color-text-body);
  margin-block-start: var(--space-m);
}
/* Small reassurance line under the hero CTA (Lewis's design). */
.hs-hero__note {
  margin: var(--space-s) 0 0 0;
  font-size: var(--fs-step--1);
  color: var(--color-text-body);
}

/* ============================  Cards  ==================================== */

.hs-card {
  position: relative; /* anchor for .hs-card__cover link */
  background: var(--color-surface);
  border: 2px solid transparent;
  border-radius: var(--radius-card);
  padding: var(--space-l);
  display: flex;
  flex-direction: column;
  gap: var(--space-s);
  transition: transform var(--duration-base) var(--ease-out),
              box-shadow var(--duration-base) var(--ease-out);
}

.hs-card--bone  { background: var(--color-bg-alt); }
.hs-card--sand  { background: var(--color-surface-muted); }
.hs-card--saffron { background: var(--color-accent); color: var(--color-accent-ink); }
.hs-card--green   { background: var(--color-success); color: var(--color-text-on-dark); }
.hs-card--plum    { background: var(--color-text); color: var(--color-text-on-dark); }

.hs-card__title {
  font-family: var(--font-display);
  font-size: var(--fs-step-2);
  margin: 0;
  color: inherit;
  line-height: var(--lh-snug);
}
.hs-card__body { margin: 0; color: inherit; }

/* Card icon — neutral container. On coloured cards (saffron / green / plum)
   the icon sits in a small lighter disc so it still has a visible halo;
   on white cards it sits inside a saffron disc for warmth. The
   `overflow: hidden` keeps wide-aspect icons inside the circle.       */
.hs-card__icon {
  width: 3.5rem;
  height: 3.5rem;
  margin-bottom: var(--space-s);
  background: var(--color-accent);
  border-radius: 50%;
  display: grid;
  place-items: center;
  padding: 0.7rem;
  flex-shrink: 0;
  overflow: hidden;
}
.hs-card--saffron .hs-card__icon,
.hs-card--green   .hs-card__icon,
.hs-card--plum    .hs-card__icon {
  background: rgba(255, 255, 255, 0.92);
}
.hs-card__icon img,
.hs-card__icon svg {
  width: 100%; height: 100%;
  object-fit: contain;
  filter: brightness(0) saturate(100%) invert(13%) sepia(40%) saturate(2200%)
          hue-rotate(312deg) brightness(92%) contrast(96%);
}

/* When a card is wrapped in (or contains) a "cover" link, the whole card
   surface becomes clickable and lifts on hover. The link uses an absolute
   pseudo-element that fills the card, so any text / buttons inside still
   work as normal. */
.hs-card__cover {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  z-index: 1;
  /* Keep the underlying card text selectable / readable. */
  font-size: 0; color: transparent;
  text-indent: -9999px;
}
.hs-card:has(.hs-card__cover:hover),
.hs-card:has(.hs-card__cover:focus-visible) {
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
}
.hs-card:has(.hs-card__cover:focus-visible) {
  outline: var(--border-focus);
  outline-offset: 3px;
}
/* Real buttons / links inside the card must sit above the cover link. */
.hs-card > .hs-btn,
.hs-card > p > .hs-btn,
.hs-card > .hs-card__cta {
  position: relative;
  z-index: 2;
}

/* ============================  Audit tile (horizontal colour-block)  ==== */
/* The "Our starting point" cards on the homepage. Lewis's design is a
   horizontal card: a large rounded colour block (saffron / green / blue)
   holding a white icon on the left, the title + body in the middle, and a
   circular bone arrow button on the right. Stacked vertically (one per row).
   The whole card is a link via .hs-audit__cover so the <h3> heading stays
   real for assistive tech while the full surface stays clickable. */

.hs-audit {
  position: relative;
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: clamp(var(--space-m), 1rem + 2vw, var(--space-xl));
  background: var(--hs-white);
  border-radius: var(--radius-card);
  padding: var(--space-s);
  box-shadow: var(--shadow-sm);
  transition: transform var(--duration-base) var(--ease-out),
              box-shadow var(--duration-base) var(--ease-out);
}

/* The coloured block + white icon. */
.hs-audit__icon {
  width: clamp(5.5rem, 4rem + 7vw, 9rem);
  aspect-ratio: 1;
  border-radius: var(--radius-md);
  display: grid;
  place-items: center;
  padding: clamp(1rem, 0.6rem + 2vw, 1.75rem);
  overflow: hidden;
}
.hs-audit--saffron .hs-audit__icon { background: var(--hs-saffron); }
.hs-audit--green   .hs-audit__icon { background: var(--hs-green); }
.hs-audit--blue    .hs-audit__icon { background: var(--hs-blue); }
.hs-audit__icon img,
.hs-audit__icon svg {
  width: 100%; height: 100%;
  object-fit: contain;
  filter: brightness(0) invert(1); /* white mark on the colour block */
}

.hs-audit__body { min-width: 0; }
.hs-audit__title {
  font-family: var(--font-display);
  font-size: var(--fs-step-3);
  color: var(--hs-plum);
  margin: 0 0 var(--space-2xs) 0;
  line-height: var(--lh-snug);
}
.hs-audit__text {
  margin: 0;
  color: var(--color-text-body);
  max-width: 46ch;
}

/* Circular arrow button — a visual affordance; the cover link does the work. */
.hs-audit__arrow {
  flex-shrink: 0;
  width: 2.75rem; height: 2.75rem;
  border-radius: 50%;
  background: var(--hs-bone);
  color: var(--hs-plum);
  display: grid;
  place-items: center;
  transition: transform var(--duration-base) var(--ease-out),
              background var(--duration-base) var(--ease-out);
}
.hs-audit__arrow svg { width: 42%; height: 42%; fill: none; }

/* Cover link — fills the card, keeps inner text selectable. */
.hs-audit__cover {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  z-index: 1;
  font-size: 0; color: transparent;
}
.hs-audit:has(.hs-audit__cover:hover),
.hs-audit:has(.hs-audit__cover:focus-visible) {
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
}
.hs-audit:has(.hs-audit__cover:hover) .hs-audit__arrow,
.hs-audit:has(.hs-audit__cover:focus-visible) .hs-audit__arrow {
  background: var(--hs-saffron);
  transform: translateX(2px);
}
.hs-audit:has(.hs-audit__cover:focus-visible) {
  outline: var(--border-focus);
  outline-offset: 3px;
}

/* On narrow screens the arrow drops below the text so the colour block and
   copy keep a comfortable width. */
@media (max-width: 34rem) {
  .hs-audit {
    grid-template-columns: auto 1fr;
    gap: var(--space-s);
  }
  .hs-audit__arrow { grid-column: 2; justify-self: start; }
}

/* ============================  Arrow button (shared affordance)  ======== */
/* The circular arrow first used on the audit tiles, lifted into a reusable
   piece for the v2 blog + project cards. It's a visual affordance only —
   the card's stretched cover link does the actual navigating, so this is
   never a focusable control itself. Cards opt into the hover/focus colour
   shift via their own `:has(.hs-card__cover:hover) .hs-arrow-btn` rule. */
.hs-arrow-btn {
  flex-shrink: 0;
  width: 2.75rem; height: 2.75rem;
  border-radius: 50%;
  background: var(--hs-bone);
  color: var(--hs-plum);
  display: grid;
  place-items: center;
  transition: transform var(--duration-base) var(--ease-out),
              background var(--duration-base) var(--ease-out);
}
.hs-arrow-btn svg { width: 42%; height: 42%; fill: none; }

/* ============================  Icon row (feature strip)  ================ */

.hs-feature {
  text-align: center;
}
/* Default feature icon — a yellow disc with the illustrated mark sitting
   inside it, recoloured plum via a CSS filter so it reads against the
   saffron disc. The source SVGs ship in saffron; the filter values below
   are precomputed to map #F9AE35 → #5A2439.

   `overflow: hidden` is critical: the disc is a circle (border-radius
   50%) but the inscribed image is rectangular. Wide-aspect icons
   (security, frame) would otherwise visually spill past the circle's
   chord at the top/bottom edges. Clipping to the radius keeps the
   silhouette clean. */
.hs-feature__icon {
  width: 5rem; height: 5rem;
  margin: 0 auto var(--space-m);
  background: var(--color-accent);
  border-radius: 50%;
  display: grid;
  place-items: center;
  padding: 0.9rem;
  overflow: hidden;
}
.hs-feature__icon img,
.hs-feature__icon svg {
  /* Inside the disc we want the image bounding box to be a SQUARE so
     it fits within the circle's inscribed square — both dimensions at
     100% of the padded content area, with `object-fit: contain` letting
     the wide-aspect SVGs letterbox vertically. */
  width: 100%;
  height: 100%;
  object-fit: contain;
  /* Lewis's design puts WHITE marks inside the saffron disc, not plum.
     brightness(0) zeroes the source saffron to black; invert(1) flips it
     to pure white. (The earlier saffron→plum hue-rotate was a Matt-ism.) */
  filter: brightness(0) invert(1);
}

/* "Bare" variant — drops the disc, used in the "Common website issues"
   row where Lewis's design shows the illustrated mark on its own. The
   icons are sized by height (3rem) so they read as the same visual
   weight despite the very different viewBox aspect ratios of the source
   SVGs. */
.hs-feature__icon--bare {
  background: transparent;
  padding: 0;
  width: auto;             /* the parent grid cell centres it */
  height: 3rem;
  margin-inline: auto;
  margin-bottom: var(--space-m);
  display: flex;
  align-items: center;
  justify-content: center;
}
.hs-feature__icon--bare img,
.hs-feature__icon--bare svg {
  height: 100%;
  width: auto;
  max-width: 5.5rem;
  filter: none; /* keep the original saffron */
}
.hs-feature__title {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: var(--fs-step-1);
  margin-bottom: var(--space-2xs);
}
.hs-feature__body {
  color: var(--color-text-body);
  font-size: var(--fs-step-0);
  max-width: 32ch;
  margin: 0 auto;
}

/* ============================  Numbered steps  =========================== */

.hs-step {
  text-align: center;
}
.hs-step__num {
  display: inline-grid;
  place-items: center;
  width: 3.5rem; height: 3.5rem;
  border-radius: 50%;
  /* v2: filled plum disc with a cream numeral (was a saffron disc). */
  background: var(--color-text);
  color: var(--color-text-on-dark);
  font-family: var(--font-display);
  font-size: var(--fs-step-2);
  margin-bottom: var(--space-s);
}
.hs-step__title {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: var(--fs-step-1);
  margin-bottom: var(--space-2xs);
}

/* Report steps grid — four items split by thin plum vertical rules on
   desktop (collapses to a single column, no rules, on mobile). */
.hs-report-steps {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0;
}
.hs-report-steps .hs-step { padding-inline: var(--space-l); }
.hs-report-steps .hs-step + .hs-step { border-left: 1px solid var(--color-border); }
@media (max-width: 52rem) {
  .hs-report-steps { grid-template-columns: 1fr; gap: var(--space-xl); }
  .hs-report-steps .hs-step { padding-inline: 0; }
  .hs-report-steps .hs-step + .hs-step { border-left: 0; }
}

/* ============================  CTA row helper  =========================== */
/* When a section's CTA needs extra breathing room above the button — used
   on "Common website issues" and at the bottom of foundation grids. */

.hs-cta-row {
  display: flex;
  justify-content: center;
  margin-top: var(--space-xl);
}

/* ============================  Form controls  ============================ */

.hs-field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
}
.hs-field__label {
  font-weight: 600;
  color: var(--color-text);
}
.hs-field__hint {
  font-size: var(--fs-step--1);
  color: var(--color-text-body);
}
.hs-field__error {
  color: var(--hs-plum);
  font-weight: 600;
  font-size: var(--fs-step--1);
}
.hs-field__error[hidden] { display: none; }

#form-status {
  text-align: center;
  margin-block-start: var(--space-m);
}

.hs-input,
.hs-textarea {
  width: 100%;
  padding: 0.85em 1em;
  background: var(--color-surface);
  border: 2px solid var(--color-border-muted);
  border-radius: var(--radius-pill);
  font-size: var(--fs-step-0);
  color: var(--color-text);
  transition: border-color var(--duration-base) var(--ease-out);
}

.hs-textarea {
  border-radius: var(--radius-lg);
  min-height: 8rem;
  resize: vertical;
  line-height: var(--lh-base);
}

.hs-input:focus,
.hs-textarea:focus {
  border-color: var(--color-border);
  outline-offset: 2px;
}

.hs-input[aria-invalid="true"],
.hs-textarea[aria-invalid="true"] {
  border-color: var(--hs-plum);
}

/* Honeypot — hidden from sighted + assistive users. Bots fill it. */
.hs-honeypot {
  position: absolute;
  left: -10000px;
  width: 1px; height: 1px;
  overflow: hidden;
}

/* ============================  Option card (selectable)  ================= */
/* Wraps a real <input type="radio"> + <label>. The radio remains keyboard
   navigable; the visual is the entire labelled card.                     */

.hs-option {
  position: relative;
  display: block;
  cursor: pointer;
}
.hs-option__input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  margin: 0;
  cursor: pointer;
  /* Keep the radio in the tab order, but invisible — focus styling lives
     on the visible card via :has() / :focus-within. Span the full card
     so any click anywhere on the card selects the option. */
}
.hs-option__card {
  background: var(--color-surface);
  border: 2px solid transparent;
  border-radius: var(--radius-card);
  padding: var(--space-l);
  display: flex;
  flex-direction: column;
  gap: var(--space-s);
  min-height: 100%;
  transition: border-color var(--duration-base) var(--ease-out),
              transform var(--duration-base) var(--ease-out),
              box-shadow var(--duration-base) var(--ease-out);
}
.hs-option:hover .hs-option__card {
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
}
.hs-option__icon {
  width: 4rem; height: 4rem;
  margin-bottom: var(--space-2xs);
}
.hs-option__icon img, .hs-option__icon svg {
  width: 100%; height: 100%; object-fit: contain;
}
.hs-option__title {
  /* Form controls are all DM Sans — no serif inside the get-started form. */
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--fs-step-2);
  margin: 0;
  line-height: var(--lh-snug);
}
.hs-option__body { color: var(--color-text-body); margin: 0; }

.hs-option__check {
  position: absolute;
  top: var(--space-m);
  right: var(--space-m);
  width: 1.75rem; height: 1.75rem;
  border-radius: 50%;
  background: var(--color-text);
  color: var(--color-text-on-dark);
  display: none;
  place-items: center;
  z-index: 1;
}
.hs-option__check svg { width: 60%; height: 60%; fill: currentColor; }

/* When the wrapped input is checked, highlight the visible card.
   No permanent border on the unchecked state — that border is reserved
   for genuinely active or focused inputs. */
.hs-option:has(.hs-option__input:checked) .hs-option__card {
  border-color: var(--color-border);
}
.hs-option:has(.hs-option__input:checked) .hs-option__check {
  display: grid;
}
.hs-option:has(.hs-option__input:focus-visible) .hs-option__card {
  outline: var(--border-focus);
  outline-offset: 3px;
}

/* ============================  Step dots (progress)  ==================== */

.hs-stepdots {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  margin-block: var(--space-l);
}
.hs-stepdots__dot {
  width: 0.875rem; height: 0.875rem;
  border-radius: 50%;
  background: var(--color-border-muted);
  display: inline-block;
}
.hs-stepdots__dot--done {
  background: var(--color-success);
}
.hs-stepdots__dot--current {
  background: transparent;
  border: 3px solid var(--color-success);
  width: 1.4rem; height: 1.4rem;
}
.hs-stepdots__back {
  width: 1.75rem; height: 1.75rem;
  border-radius: 50%;
  background: var(--color-accent);
  color: var(--color-accent-ink);
  border: 0;
  display: inline-grid;
  place-items: center;
  cursor: pointer;
}
.hs-stepdots__back[disabled] { opacity: 0.4; cursor: not-allowed; }
.hs-stepdots__back svg { width: 60%; height: 60%; fill: currentColor; transform: scaleX(-1); }

/* ============================  Audit-report hero panel  ================= */
/* The right-hand half of the homepage hero. Lewis's design
   (/fixed/reports-svg-layout.png) is a WHITE report card holding three bone
   "Score" tiles (63 / 65 / 28) above two bone panels of redacted lines —
   the message is "you get scores plus a prioritised written report", not a
   stats meter. Palette: white card, bone (#EDE9E2) tiles/panels, sand
   (#D9D2C9) bars/dots/block, plum numbers. */

.hs-report {
  background: var(--hs-white);
  border-radius: var(--radius-lg);
  padding: clamp(1.25rem, 0.8rem + 1.8vw, 1.75rem);
  display: grid;
  gap: var(--space-s);
  box-shadow:
    inset 0 0 0 1px rgba(90, 36, 57, 0.05),
    0 18px 40px -28px rgba(90, 36, 57, 0.30);
}

/* --- Score tiles --- */
.hs-report__scores {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-2xs);
  margin: 0;
  padding: 0;
  list-style: none;
}
.hs-report__tile {
  background: var(--hs-bone);
  border-radius: var(--radius-md);
  padding: var(--space-m) var(--space-2xs) var(--space-s);
  display: grid;
  justify-items: center;
  gap: 0.2rem;
}
.hs-report__score {
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 1.2rem + 2vw, 2.5rem);
  line-height: 1;
  color: var(--hs-plum);
}
.hs-report__cap {
  font-size: var(--fs-step--1);
  color: var(--hs-ink);
}

/* --- Redacted-line panels --- */
.hs-report__panel {
  background: var(--hs-bone);
  border-radius: var(--radius-md);
  padding: var(--space-m);
  display: flex;
  flex-direction: column;
  /* flex-start so each bar keeps its own inline width instead of being
     stretched to fill the cross axis. */
  align-items: flex-start;
  gap: 0.6rem;
}
.hs-report__bar {
  height: 0.6rem;
  border-radius: var(--radius-pill);
  background: var(--hs-sand);
}
.hs-report__block {
  height: 2.25rem;
  width: 46%;
  margin-top: 0.2rem;
  border-radius: var(--radius-sm);
  background: var(--hs-sand);
}

/* --- Lower panel: rows of dot + line --- */
.hs-report__panel--rows { gap: var(--space-s); }
.hs-report__row {
  display: flex;
  align-items: center;
  gap: var(--space-s);
  width: 100%;
}
.hs-report__dot {
  flex-shrink: 0;
  width: 1.1rem; height: 1.1rem;
  border-radius: 50%;
  background: var(--hs-sand);
}

/* --- Countdown motif (v2) --- */
/* Replaces the three score tiles: a colon-separated row of three numbers.
   Decorative — the segments render their settled values in HTML and
   home-hero.js animates them counting up on load when motion is allowed.
   tabular-nums keeps digit width steady so the row doesn't jitter mid-count. */
.hs-countdown {
  display: flex;
  align-items: stretch;
  gap: var(--space-2xs);
}
.hs-countdown__seg {
  flex: 1;
  background: var(--hs-bone);
  border-radius: var(--radius-md);
  padding: var(--space-m) var(--space-2xs);
  display: grid;
  place-items: center;
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 1.2rem + 2vw, 2.75rem);
  line-height: 1;
  color: var(--hs-plum);
  font-variant-numeric: tabular-nums;
}
.hs-countdown__colon {
  display: grid;
  place-items: center;
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 1rem + 1.5vw, 2.25rem);
  line-height: 1;
  color: var(--hs-sand);
}

/* ============================  Foundation card (linked image card)  ===== */
/* The "Building strong foundations" cards on the homepage. Each is a
   real <a> with a visible card chrome (surface + soft border + radius),
   a constrained image at the top, and a "Read more" affordance at the
   bottom so it's obvious the card navigates. Only the image lifts on
   hover — the text stays put so it never feels like the copy is
   shifting under your eyes. */

/* v2: foundations are bare linked blocks — no surface, border, shadow or
   hover lift (Lewis dropped the card treatment). Still real links. */
.hs-foundation {
  position: relative;
  display: flex;
  flex-direction: column;
  background: transparent;
  border: 0;
  color: inherit;
  text-decoration: none;
}
.hs-foundation:focus-visible {
  outline: var(--border-focus);
  outline-offset: 3px;
  border-radius: var(--radius-card);
}

/* Media wrapper — the image is what moves on hover, not the text. */
.hs-foundation__media {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  max-height: 16rem;
  object-fit: cover;
  border-radius: var(--radius-card);
}

.hs-foundation__body-wrap {
  padding: var(--space-m) 0 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-s);
}
.hs-foundation__title {
  font-family: var(--font-display);
  font-size: var(--fs-step-2);
  color: var(--color-text);
  margin: 0;
  line-height: var(--lh-snug);
}
/* Lewis pairs each foundation title with a short DM Sans tagline
   ("Systems you can trust" / "Design that excludes no one"). */
.hs-foundation__sub {
  margin: calc(-1 * var(--space-2xs)) 0 0 0;
  font-weight: 600;
  color: var(--color-text-body);
}
.hs-foundation__body {
  margin: 0;
  color: var(--color-text-body);
}

/* Read-more cue — explicit text plus an arrow so it reads obviously as
   a link. Saffron underline picks up the brand accent. */
.hs-foundation__more {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  font-weight: 600;
  color: var(--color-text);
  margin-top: var(--space-2xs);
}
.hs-foundation__more::after {
  content: "";
  display: inline-block;
  width: 1em; height: 1em;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M5 12h14m0 0l-6-6m6 6l-6 6' stroke='black' stroke-width='2.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/></svg>") center/contain no-repeat;
          mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M5 12h14m0 0l-6-6m6 6l-6 6' stroke='black' stroke-width='2.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/></svg>") center/contain no-repeat;
  transition: transform var(--duration-base) var(--ease-out);
}
.hs-foundation:hover .hs-foundation__more::after,
.hs-foundation:focus-visible .hs-foundation__more::after {
  transform: translateX(3px);
}
.hs-foundation__more {
  text-decoration: underline;
  text-decoration-color: var(--color-accent);
  text-decoration-thickness: 2px;
  text-underline-offset: 0.18em;
}

/* ============================  Focus card (about-page founders)  ======== */
/* A small horizontal card placed under each portrait, linking to the
   topic page that founder is most associated with. Visually quieter
   than the foundation cards on the homepage; functionally identical. */

.hs-focus-card {
  display: flex;
  align-items: center;
  gap: var(--space-m);
  padding: var(--space-m);
  background: var(--color-bg-alt);
  border-radius: var(--radius-card);
  text-decoration: none;
  color: inherit;
  transition: background var(--duration-base) var(--ease-out),
              transform var(--duration-base) var(--ease-out);
  /* Anchor to the bottom of the portrait column so both focus cards
     align horizontally even when the founders' bios are different
     lengths. Combined with `height: 100%` on .hs-portrait, this gives
     a shared baseline regardless of copy length. */
  margin-top: auto;
}
.hs-focus-card:hover,
.hs-focus-card:focus-visible {
  background: var(--color-surface-muted);
  transform: translateY(-1px);
}
/* Lewis's design uses a rounded colour BLOCK (not a disc) with a white
   mark — saffron for the security focus, green for accessibility. */
.hs-focus-card__icon {
  flex-shrink: 0;
  width: 3.25rem; height: 3.25rem;
  background: var(--color-accent);
  border-radius: var(--radius-md);
  display: grid; place-items: center;
  padding: 0.6rem;
  overflow: hidden;
}
.hs-focus-card--security      .hs-focus-card__icon { background: var(--hs-saffron); }
.hs-focus-card--accessibility .hs-focus-card__icon { background: var(--hs-green); }
.hs-focus-card__icon img,
.hs-focus-card__icon svg {
  width: 100%; height: 100%;
  object-fit: contain;
  filter: brightness(0) invert(1); /* white mark on the colour block */
}
.hs-focus-card__text {
  font-size: var(--fs-step--1);
  line-height: var(--lh-snug);
  color: var(--color-text-body);
}
.hs-focus-card__text strong {
  display: block;
  color: var(--color-text);
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--fs-step-1);
  line-height: 1.1;
  margin-bottom: 0.2rem;
}
/* The "See our X work →" call-out at the end of the focus card.
   Forced onto its own line — when it wrapped inline with the body copy
   the arrow could land alone on a new line, which read as broken. As a
   block element it gets a clean rhythm: title / body / link. */
.hs-focus-card__text em {
  display: block;
  margin-top: var(--space-2xs);
  font-style: normal;
  font-weight: 600;
  color: var(--color-text);
  text-decoration: underline;
  text-decoration-color: var(--color-accent);
  text-decoration-thickness: 2px;
  text-underline-offset: 0.18em;
}

/* ============================  Feature row (icon + text horizontally)  == */
/* About-page "Communities we serve" block — an illustrated mark sits to
   the left of a heading + paragraph, instead of the centred icon stacks
   used on the homepage. Collapses to a stacked layout on narrow viewports. */

.hs-feature-row {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-l);
  align-items: start;
}
@media (min-width: 48rem) {
  .hs-feature-row { grid-template-columns: auto 1fr; gap: var(--space-xl); }
}
.hs-feature-row__icon {
  width: 5.5rem;
  height: 5.5rem;
  background: var(--color-accent);
  border-radius: 50%;
  display: grid;
  place-items: center;
  padding: 1rem;
  flex-shrink: 0;
  overflow: hidden;
}
.hs-feature-row__icon img,
.hs-feature-row__icon svg {
  width: 100%;
  height: 100%;
  object-fit: contain;
  /* White mark inside the saffron disc — see .hs-feature__icon img above. */
  filter: brightness(0) invert(1);
}

/* ============================  Media + text block  ===================== */
/* Two-column "photo beside copy" rows on /about/ (mission, communities).
   Column order follows DOM order — put the <img> first for image-left,
   the text block first for image-right. Collapses to a single column on
   narrow viewports (image stacks above/below its copy as authored). */

.hs-media {
  display: grid;
  gap: var(--space-xl);
  align-items: center;
  grid-template-columns: 1fr;
}
@media (min-width: 50rem) {
  /* Default: image-left (narrower) + copy-right (wider). */
  .hs-media { grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr); }
  /* Image-right: keep the photo the narrower column, copy on the left. */
  .hs-media--img-right { grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr); }
}
.hs-media__img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--radius-card);
}
/* Anchor the crop to the top — used on the HOPE photo so the org's banner
   and logo stay in frame and the trim comes off the bottom instead. */
.hs-media__img--top { object-position: top; }

/* ============================  About hero banner  ====================== */
/* Wide cyclists banner at the top of /about/ (Lewis's design). The source
   photo is portrait, so we use a fluid banner height + object-fit: cover to
   crop it to a landscape strip — object-position keeps the riders in frame. */

.hs-about-hero {
  width: 100%;
  height: clamp(14rem, 9rem + 26vw, 30rem);
  object-fit: cover;
  /* Landscape grower photo: subject's face sits high, the crate of greens
     mid-frame. Anchor a touch above centre so both survive the banner crop. */
  object-position: center 35%;
  border-radius: var(--radius-card);
}

/* --- About page: tighten stacked spacing on mobile (desktop unchanged) --- */
/* Lead blocks stack on mobile: keep the 64px desktop COLUMN gap, but give the
   stacked rows a small gap so the bold lead and its supporting paragraph stay
   visually paired instead of drifting 64px apart. row-gap only shows when
   stacked; column-gap only when side by side, so desktop is untouched. */
.grid--2.hs-lead-grid { row-gap: var(--space-m); }
@media (max-width: 45rem) {
  /* Pull the foundations lead block and the full-bleed image strip together. */
  [aria-labelledby="foundations-lead"] { padding-bottom: var(--space-m); }
  .hs-strip-section { padding-top: var(--space-m); }
  /* Blog archive ends with a content grid (no CTA band), so its bottom padding
     stacked on the footer offset read as a mega-gap on mobile. Trim it to match
     the other pages' trailing space. */
  .hs-archive-end { padding-bottom: var(--space-l); }
}

/* ============================  Portrait (about-page founders)  ========== */
/* The founder portraits on /about/. Each image fills a fixed-aspect frame
   so the supporting text always starts at the same vertical position
   across both founders. Source headshots should be cropped to a similar
   tightness (head + shoulders) before being saved into /assets/img/photos/
   — that keeps the two portraits balanced without per-photo CSS tweaks. */

.hs-portrait {
  display: flex;
  flex-direction: column;
  gap: var(--space-s);
  max-width: 22rem;
  /* Stretch to match the tallest sibling in the grid so the focus card
     below can anchor to a shared baseline. */
  height: 100%;
}
.hs-portrait__frame {
  width: 100%;
  max-width: 14rem;
  aspect-ratio: 4 / 5;
  border-radius: var(--radius-card);
  overflow: hidden;
}
.hs-portrait__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.hs-portrait__name {
  font-family: var(--font-display);
  font-size: var(--fs-step-2);
  color: var(--color-text);
  margin: 0;
}
.hs-portrait__role {
  margin: 0;
  color: var(--color-text-body);
}
.hs-portrait__bio {
  margin: var(--space-s) 0 0 0;
}

/* ============================  Site preview (case-study hero)  ========= */
/* A "screenshot card" used at the top of each case-study page. Sits in a
   soft frame to read as a sample of the work without competing with the
   editorial copy below. The inner asset can be a real screenshot (.webp)
   or a stylised SVG placeholder authored to match the case-study's tone. */

.hs-screenshot {
  display: block;
  width: 100%;
  background: var(--color-bg-alt);
  border-radius: var(--radius-card);
  padding: var(--space-s);
  box-shadow: var(--shadow-md);
}
.hs-screenshot__img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: calc(var(--radius-card) - 6px);
  /* Preserve the SVG/screenshot's own aspect ratio — but cap the height
     so it never dominates the page on tall viewports. */
  max-height: 32rem;
  object-fit: cover;
  object-position: top center;
}
.hs-screenshot__caption {
  display: block;
  margin: var(--space-s) var(--space-xs) 0;
  font-size: var(--fs-step--1);
  color: var(--color-text-body);
}

/* ============================  Laptop frame (v2 case-study hero/card)  == */
/* v2 presents project screenshots inside a soft rose panel rather than the
   bone frame above. Used both as the single-project hero and inside the
   project archive cards. The inner asset (SVG mockup or .webp screenshot)
   keeps its own aspect ratio; the rose padding is the "mat" around it. */
.hs-laptop-frame {
  display: grid;
  place-items: center;
  width: 100%;
  margin: 0;
  background: var(--color-bg-rose);
  border-radius: var(--radius-lg);
  padding: clamp(var(--space-m), 1rem + 2vw, var(--space-xl));
}
.hs-laptop-frame__img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
}
/* Card context: a fixed window so unequal screenshots line up in the grid. */
.hs-laptop-frame--card { padding: clamp(var(--space-s), 0.5rem + 2vw, var(--space-l)); }
.hs-laptop-frame--card .hs-laptop-frame__img {
  aspect-ratio: 16 / 10;
  object-fit: cover;
  object-position: top center;
}

/* ============================  Tag (eyebrow label)  ==================== */

.hs-tag {
  display: inline-block;
  font-size: var(--fs-step--1);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-text);
  text-decoration: underline;
  text-underline-offset: 0.25em;
}

/* ============================  Category badge (blog)  =================== */
/* A small pill that sits next to (or above) a post title. Two variants
   coordinate with the blog's two starting categories: SECURITY (plum) and
   ACCESSIBILITY (green). Easily extended — add a new variant + CSS rule. */

.hs-category {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  font-family: var(--font-body);
  font-size: var(--fs-step--1);
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 0.35em 0.85em;
  border-radius: 999px;
  background: var(--color-text);
  color: var(--color-text-on-dark);
  text-decoration: none;
  line-height: 1;
}
.hs-category::before {
  content: "";
  width: 0.55em; height: 0.55em;
  border-radius: 50%;
  background: var(--color-accent);
}
.hs-category--security      { background: var(--hs-plum);   color: var(--color-text-on-dark); }
.hs-category--security::before { background: var(--hs-saffron); }
.hs-category--accessibility { background: var(--hs-green);  color: var(--color-text-on-dark); }
.hs-category--accessibility::before { background: var(--hs-saffron); }

/* ============================  Article (blog post body)  ================ */

.hs-article {
  --measure: 64ch;
}
.hs-article h2,
.hs-article h3 {
  margin-top: var(--space-xl);
  /* v2: body subheadings are DM Sans bold (not the display serif) — see
     the single-post mockup. The serif is reserved for the title + pullquote. */
  font-family: var(--font-body);
  font-weight: 700;
  color: var(--color-text);
  line-height: var(--lh-snug);
}
.hs-article h2 { font-size: var(--fs-step-1); }
.hs-article h3 { font-size: var(--fs-step-0); }
.hs-article p,
.hs-article ul,
.hs-article ol {
  max-width: var(--measure);
}
.hs-article ul, .hs-article ol {
  padding-left: 1.2em;
}
.hs-article li + li { margin-top: var(--space-2xs); }
.hs-article blockquote {
  margin: var(--space-l) 0;
  padding: var(--space-m) var(--space-l);
  border-left: 4px solid var(--color-accent);
  background: var(--color-bg-alt);
  border-radius: var(--radius-sm);
  font-family: var(--font-display);
  font-size: var(--fs-step-1);
  color: var(--color-text);
}
.hs-article code {
  font-family: var(--font-mono);
  font-size: 0.92em;
  background: var(--color-bg-alt);
  padding: 0.1em 0.4em;
  border-radius: 4px;
}

/* Pullquote — v2's editorial extract. Distinct from the default
   left-bordered blockquote: a full rose panel, larger serif, no rule. Used
   inside articles by tagging a <blockquote class="hs-pullquote">. It breaks
   the measure (wider than body copy) on purpose to read as a feature. */
.hs-pullquote {
  margin: var(--space-xl) 0;
  padding: var(--space-l) clamp(var(--space-l), 1rem + 3vw, var(--space-2xl));
  max-width: none;
  background: var(--color-bg-rose);
  border: 0;
  border-radius: var(--radius-lg);
  font-family: var(--font-display);
  font-size: var(--fs-step-2);
  line-height: var(--lh-snug);
  color: var(--color-text);
}
.hs-pullquote p { max-width: none; margin: 0; }
.hs-pullquote p + p { margin-top: var(--space-s); }

/* Single-post header (v2): a meta line (date · author left, read-time right)
   above a full-width hero image, with the title sitting below the image. */
.hs-post-meta {
  display: flex;
  justify-content: space-between;
  gap: var(--space-s);
  flex-wrap: wrap;
  font-size: var(--fs-step--1);
  color: var(--color-text-body);
  margin: 0;
}
.hs-post-hero {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  background: var(--color-surface-muted); /* placeholder / fallback while loading */
  border-radius: var(--radius-card);
  object-fit: cover;
  margin: 0;
}

/* ============================  Post preview card  ======================= */
/* A small teaser card used on the blog index. The whole card is a
   stretched link via .hs-card__cover. */

.hs-post-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-s);
}
.hs-post-card__cover {
  aspect-ratio: 16 / 10;
  border-radius: var(--radius-card);
  background: var(--color-accent);
  position: relative;
  overflow: hidden;
  display: grid;
  place-items: center;
}
.hs-post-card__cover--security      { background: var(--hs-plum); }
.hs-post-card__cover--accessibility { background: var(--hs-green); }
/* The cover holds a single illustrated mark — large, off-centred, half
   visible — to evoke an editorial header without needing photography. */
.hs-post-card__cover svg,
.hs-post-card__cover img {
  width: 55%;
  height: 55%;
  object-fit: contain;
  opacity: 0.85;
  transform: translate(8%, 10%);
  filter: brightness(0) saturate(100%) invert(98%) sepia(8%)
          saturate(290%) hue-rotate(13deg) brightness(105%) contrast(95%);
}
.hs-post-card__cover--saffron svg,
.hs-post-card__cover--saffron img {
  filter: brightness(0) saturate(100%) invert(13%) sepia(40%) saturate(2200%)
          hue-rotate(312deg) brightness(92%) contrast(96%);
}
.hs-post-card__title {
  font-family: var(--font-display);
  font-size: var(--fs-step-2);
  margin: 0;
  line-height: var(--lh-snug);
}
/* Visible "Read more" affordance.
   The whole card is clickable via .hs-card__cover, but without a visible
   cue sighted users have nothing to tell them so. The pseudo-element
   isn't read by AT (the cover link's aria-label covers that), it's there
   purely as a visual signal. `margin-top: auto` parks it at the bottom of
   the flex column so it lines up across cards of unequal height. */
.hs-post-card::after {
  content: "Read more →";
  margin-top: auto;
  padding-top: var(--space-s);
  font-weight: 600;
  color: var(--color-text);
  text-decoration: underline;
  text-decoration-color: var(--color-accent);
  text-decoration-thickness: 2px;
  text-underline-offset: 0.18em;
  align-self: start;
}
.hs-post-card__meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-s);
  align-items: center;
  font-size: var(--fs-step--1);
  color: var(--color-text-body);
}

/* ============================  v2 home components  ===================== */

/* Feature icon, ring variant — Lewis's v2 circular outline icons (icons-v2),
   recoloured from their delivered saffron to brand plum, with NO disc behind
   them (the ring is part of the SVG). Used in "Why work with us" and
   "Common website issues". The filter is the codebase's saffron→plum map. */
.hs-feature__icon--ring {
  width: clamp(5rem, 4rem + 3.5vw, 6.75rem);
  height: clamp(5rem, 4rem + 3.5vw, 6.75rem);
  background: transparent;
  padding: 0;
  overflow: visible;
}
.hs-feature__icon--ring img {
  filter: brightness(0) saturate(100%) invert(13%) sepia(40%) saturate(2200%)
          hue-rotate(312deg) brightness(92%) contrast(96%);
}

/* v2: section intro paragraphs sit at medium weight (Lewis's are heavier than
   plain body copy). Applied to the centred blurb under each section heading. */
.hs-section-intro { font-weight: 500; }

/* Route-card media — a flat tinted panel standing in for the illustration
   until real artwork lands (decorative; aria-hidden in the markup). */
.hs-card__media {
  aspect-ratio: 16 / 10;
  border-radius: var(--radius-md);
  margin-bottom: var(--space-xs);
}
.hs-card__media--rose    { background: var(--color-bg-rose); }
.hs-card__media--iceblue { background: var(--color-bg-iceblue); }

/* Route picker (v2): two transparent cards (no surface/border/hover) split by
   a vertical rule on desktop. The button is the only link — dropping the
   stretched card cover also kills the hover-shadow-flicker bug. */
.hs-route-grid {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(var(--space-xl), 2rem + 4vw, var(--space-3xl));
  align-items: stretch;
}
@media (max-width: 48rem) {
  .hs-route-grid { grid-template-columns: 1fr; gap: var(--space-2xl); }
}
@media (min-width: 48.001rem) {
  .hs-route-grid::before {
    content: "";
    position: absolute;
    inset-block: 0;
    left: 50%;
    width: 1px;
    background: var(--color-border);
  }
}
.hs-route-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-m);
}
.hs-route-card__img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius-card);
}
.hs-route-card__cta { margin: var(--space-2xs) 0 0 0; padding-top: 0; margin-top: auto; text-align: center; }

/* Process timeline — "Our starting point — the Audit". Numbered outline
   discs joined by a vertical line. The connector is a flex line that fills
   each step's height down to the next disc, so it tracks variable copy
   length without hard-coded gaps. */
.hs-process {
  position: relative;
  display: grid;
  gap: var(--space-xl);
  margin: 0 auto;
  padding: 0;
  list-style: none;
  max-width: 48rem;
}
/* One continuous plum line down the disc-column centre, running from a short
   stub above the first disc to a long stub below the last (matches Lewis's
   unbroken rule). It sits behind the discs (z-index), and each disc carries
   the section's ice-blue fill so the line is masked inside the rings. */
.hs-process::before {
  content: "";
  position: absolute;
  z-index: 0;
  /* Overshoot far past the list; the section's overflow:hidden clips the line
     exactly to the ice-blue band, so it touches the top and bottom edges. */
  top: -60rem;
  bottom: -60rem;
  left: 2.5rem;
  width: 2px;
  background: var(--hs-plum);
  transform: translateX(-1px);
}
.hs-process__step {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: clamp(var(--space-m), 1rem + 2vw, var(--space-xl));
  align-items: center;
}
.hs-process__marker {
  position: relative;
  z-index: 1;
  display: flex;
  justify-content: center;
}
.hs-process__num {
  flex-shrink: 0;
  width: 5rem;
  height: 5rem;
  border: 2px solid var(--hs-plum);
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-family: var(--font-display);
  font-size: var(--fs-step-3);
  color: var(--hs-plum);
  background: var(--color-bg-iceblue);
}
.hs-process__title {
  font-family: var(--font-display);
  font-size: var(--fs-step-2);
  color: var(--hs-plum);
  margin: 0 0 var(--space-2xs) 0;
  line-height: var(--lh-snug);
}
.hs-process__body p { margin: 0; color: var(--color-text-body); max-width: 52ch; }
/* Mobile: stack like the report steps — disc centred above its text, no
   connector line (it overshot the band and crossed the centred heading). */
@media (max-width: 52rem) {
  .hs-process::before { display: none; }
  .hs-process__step {
    grid-template-columns: 1fr;
    justify-items: center;
    text-align: center;
    gap: var(--space-s);
  }
  .hs-process__body p { max-width: 40ch; margin-inline: auto; }
}

/* Testimonial card — pastel-tinted quote cards (v2 "Don't take our word
   for it"). A large opening quote glyph, the quote, then attribution. */
.hs-quote {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  gap: var(--space-m);
  padding: var(--space-l);
  border-radius: var(--radius-card);
  margin: 0;
  min-height: 16rem;
}
.hs-quote--rose    { background: var(--color-bg-rose); }
.hs-quote--iceblue { background: var(--color-bg-iceblue); }
.hs-quote--bone    { background: var(--color-bg-alt); }
/* Large, faint white quotation mark behind the text, top-left (Lewis's
   background flourish). Decorative — the body text sits above it. */
.hs-quote::before {
  content: "\201C";
  position: absolute;
  top: -0.15em;
  left: 0.15em;
  z-index: 0;
  font-family: var(--font-display);
  font-size: 8rem;
  line-height: 1;
  color: var(--hs-white);
  opacity: 0.7;
  pointer-events: none;
}
.hs-quote__body {
  position: relative;
  z-index: 1;
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--fs-step-1);
  line-height: var(--lh-snug);
  color: var(--hs-plum);
}
.hs-quote__by {
  position: relative;
  z-index: 1;
  margin-top: auto;
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
}
.hs-quote__name { font-weight: 700; color: var(--color-text); }
.hs-quote__org  { font-size: var(--fs-step--1); color: var(--color-text-body); }

/* ============================  Blog archive (v2)  ====================== */
/* The post grid: a full-width featured card (image + text side by side) over
   a row of regular cards (image on top). v2 drops the old icon cover and the
   "Read more" text in favour of an image placeholder, an overlaid white
   category pill, and a circular diagonal-arrow affordance. */
.hs-blog-grid {
  display: grid;
  gap: var(--space-l);
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
@media (max-width: 60rem) { .hs-blog-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 40rem) { .hs-blog-grid { grid-template-columns: 1fr; } }

.hs-blog-grid .hs-post-card {
  padding: var(--space-s);
  gap: var(--space-s);
}
.hs-blog-grid .hs-post-card::after { content: none; } /* suppress legacy read-more */
.hs-blog-grid .hs-post-card__meta { justify-content: space-between; width: 100%; }

.hs-post-card__media {
  position: relative;
  aspect-ratio: 16 / 11;
  border-radius: var(--radius-md);
  background: var(--color-surface-muted); /* placeholder / fallback while loading */
  overflow: hidden;
}
.hs-post-card__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.hs-category-badge {
  position: absolute;
  top: var(--space-s);
  left: var(--space-s);
  z-index: 1;
  background: var(--color-surface);
  color: var(--color-text);
  font-family: var(--font-body);
  font-weight: 700;
  font-size: var(--fs-step-0);
  padding: 0.45em 1em;
  border-radius: var(--radius-pill);
  box-shadow: var(--shadow-sm);
}
.hs-post-card__text {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  flex: 1;
  padding-inline: var(--space-2xs);
}
.hs-post-card__text > p { margin: 0; }
.hs-post-card__foot {
  margin-top: auto;
  padding-top: var(--space-s);
  display: flex;
  justify-content: flex-end;
}
.hs-post-card:has(.hs-card__cover:hover) .hs-arrow-btn,
.hs-post-card:has(.hs-card__cover:focus-visible) .hs-arrow-btn {
  background: var(--hs-saffron);
}

/* Featured (first) post — image and text side by side, full grid width. */
.hs-post-card--featured {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-s);
  align-items: stretch;
}
.hs-post-card--featured .hs-post-card__media {
  aspect-ratio: auto;
  min-height: 20rem;
  height: 100%;
}
.hs-post-card--featured .hs-post-card__text { padding: var(--space-m); }
.hs-post-card--featured .hs-post-card__title { font-size: var(--fs-step-3); }
@media (max-width: 48rem) {
  .hs-post-card--featured { grid-template-columns: 1fr; }
  .hs-post-card--featured .hs-post-card__media { min-height: 14rem; }
}

/* ============================  Projects archive (v2)  ================== */
/* One large featured project over a row of smaller ones. Each card is a
   rose-framed screenshot with a label / title / one-line subtitle beneath —
   no card chrome, the rose frame is the visual anchor. Whole card links via
   .hs-card__cover; the frame lifts on hover. */
.hs-project-grid {
  display: grid;
  gap: var(--space-2xl);
  grid-template-columns: 1fr 1fr;
}
@media (max-width: 48rem) { .hs-project-grid { grid-template-columns: 1fr; } }

.hs-project-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-m);
}
.hs-project-card--featured { grid-column: 1 / -1; }

.hs-project-card .hs-laptop-frame {
  transition: transform var(--duration-base) var(--ease-out),
              box-shadow var(--duration-base) var(--ease-out);
}
.hs-project-card:has(.hs-card__cover:hover) .hs-laptop-frame,
.hs-project-card:has(.hs-card__cover:focus-visible) .hs-laptop-frame {
  transform: translateY(-3px);
  box-shadow: var(--shadow-md);
}
.hs-project-card:has(.hs-card__cover:focus-visible) {
  outline: var(--border-focus);
  outline-offset: 4px;
  border-radius: var(--radius-lg);
}

.hs-project-card__label {
  font-size: var(--fs-step--1);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-text-body);
  margin: 0 0 var(--space-2xs) 0;
}
.hs-project-card__title {
  font-family: var(--font-display);
  font-size: var(--fs-step-2);
  color: var(--color-text);
  margin: 0 0 var(--space-2xs) 0;
  line-height: var(--lh-snug);
}
.hs-project-card--featured .hs-project-card__title { font-size: var(--fs-step-3); }
.hs-project-card__sub {
  margin: 0;
  color: var(--color-text-body);
}

/* ============================  Single project (v2)  =================== */
/* Sector / Scope / Site / Region row — sits under the laptop hero with a
   thin rule above and no filled box (was a bone panel). */
.hs-project-meta {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-l);
  margin: 0;
  padding-top: var(--space-l);
  border-top: 1px solid var(--color-border-muted);
}
@media (max-width: 40rem) { .hs-project-meta { grid-template-columns: repeat(2, 1fr); } }
.hs-project-meta dt {
  font-weight: 700;
  color: var(--color-text);
  margin-bottom: var(--space-2xs);
}
.hs-project-meta dd { margin: 0; color: var(--color-text-body); }

/* Body sections — heading on the left, copy on the right (collapses to a
   single column on narrow viewports). */
.hs-case-section {
  display: grid;
  grid-template-columns: 1fr 2fr;
  gap: clamp(var(--space-m), 1rem + 2vw, var(--space-2xl));
  align-items: start;
}
@media (max-width: 48rem) {
  .hs-case-section { grid-template-columns: 1fr; gap: var(--space-s); }
}
.hs-case-section__head h2 {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: var(--fs-step-2);
  color: var(--color-text);
  line-height: var(--lh-snug);
  margin: 0;
}

/* Prev/next pager — a ghost "Back to work" + a filled "Next project". */
.hs-pagenav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-m);
}

/* ============================  Laptop mockup (self-framed render)  ====== */
/* Lewis's project mockups (orto / la-finestra-blu / hopesupport) are
   self-contained: a laptop render with its own drop-shadow sitting on a soft
   rose background that already matches --hs-rose. So inside .hs-laptop-frame
   we drop the panel "mat" + the inner box-shadow and simply round the
   corners — otherwise we'd get a shadowed pink square on a pink mat. */
.hs-laptop-frame--mockup { padding: 0; background: transparent; }
.hs-laptop-frame--mockup .hs-laptop-frame__img {
  box-shadow: none;
  border-radius: var(--radius-lg);
}
/* In the archive card's fixed 16/10 window, centre the crop so the laptop
   (centred in the square source) stays in frame, not the top-anchored
   default used by the SVG previews. */
.hs-laptop-frame--card.hs-laptop-frame--mockup .hs-laptop-frame__img {
  object-position: center;
}

/* ============================  About v2 — editorial statements  ========= */
/* Lewis's refreshed /about/ (PDF p.6) and the /audit/ page that reuses its
   template. Large plum "statement" lines sit on soft rose / ice-blue bands;
   two-column intros pair a bold lead with supporting copy. */

/* Bold lead paragraph (left column of the intro pairs). */
.hs-lead {
  font-weight: 700;
  color: var(--color-text);
  margin: 0;
}

/* Big plum statement line on a coloured band. */
.hs-statement {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--fs-step-3);
  line-height: 1.25;
  color: var(--color-text);
  max-width: 38ch;
  margin: 0;
}
/* The audit band's line is indented from the left in Lewis's design. */
@media (min-width: 50rem) {
  .hs-statement--right {
    margin-inline-start: 22%;
    max-width: 34ch;
  }
}

/* Image strip — two photos that run full-bleed to the screen edges (Lewis's
   design). The wider photo takes ~60% of the viewport, a 40px gutter, then
   the narrower one fills the rest. Only the inner (facing) corners are
   rounded; the edges anchored to the screen stay square. Stacks to a boxed,
   fully-rounded pair on narrow viewports. */
.hs-image-strip {
  display: grid;
  gap: var(--space-s);
  grid-template-columns: 1fr;
  padding-inline: var(--gutter);
}
.hs-image-strip__img {
  width: 100%;
  height: clamp(13rem, 9rem + 16vw, 24rem);
  object-fit: cover;
  border-radius: var(--radius-card);
}
@media (min-width: 40rem) {
  .hs-image-strip {
    /* 60% + 40px gutter + (40% - 40px) = 100% of the full-width strip. */
    grid-template-columns: 60% calc(40% - 40px);
    column-gap: 40px;
    padding-inline: 0;
  }
  /* Taller, screen-filling photos on desktop (Lewis's design). */
  .hs-image-strip__img { height: 45vh; }
  .hs-image-strip__img--left  { border-radius: 0 var(--radius-lg) var(--radius-lg) 0; }
  .hs-image-strip__img--right { border-radius: var(--radius-lg) 0 0 var(--radius-lg); }
}

/* CIC promise — left prose, right a ruled list of commitments. The vertical
   rule + bullet dots only appear once the columns sit side by side. */
.hs-promise-list {
  margin: 0;
  padding: 0;
  list-style: none;
}
.hs-promise-list > li + li { margin-top: var(--space-l); }
.hs-promise-list h3 {
  font-family: var(--font-body);
  font-size: var(--fs-step-0);
  font-weight: 700;
  color: var(--color-text);
  margin: 0 0 var(--space-2xs);
}
.hs-promise-list p { margin: 0; color: var(--color-text-body); }
@media (min-width: 50rem) {
  /* The rule must run the FULL height of the cream band, edge to edge. To do
     that we zero the section's own block padding and move it onto the two
     columns instead. The grid stretches both columns to the band height, so
     the rule (on the stretched .hs-promise column) now spans top to bottom,
     with the column padding holding the content inset from the band edges. */
  .hs-promise-section { padding-block: 0; }
  .hs-promise-section .split { align-items: stretch; }
  .hs-promise-section .split > * { padding-block: var(--space-3xl); }
  .hs-promise {
    border-inline-start: 2px solid var(--color-border);
    padding-inline-start: var(--space-xl);
  }
  .hs-promise-list > li { position: relative; }
  .hs-promise-list > li::before {
    content: "";
    position: absolute;
    inset-inline-start: calc(-1 * var(--space-xl) - 7px);
    top: 0.4em;
    width: 8px; height: 8px;
    border-radius: 50%;
    background: var(--color-text);
    /* 3px ring in the cream band colour so the rule appears to pass cleanly
       behind each dot (Lewis's design). */
    border: 3px solid var(--color-bg);
    box-sizing: content-box;
  }
}

/* Audit area cards — the four-area breakdown on /audit/. Lewis's ring icons
   shown at their natural saffron, no disc behind them. A fixed 2×2 grid
   (not auto-fit) keeps the four areas balanced and the columns readable. */
.hs-audit-areas {
  display: grid;
  /* Single column on mobile: a tighter gap so the four areas don't sprawl.
     The roomier 2xl gap returns for the 2x2 desktop grid below. */
  gap: var(--space-l);
  grid-template-columns: 1fr;
}
@media (min-width: 48rem) {
  .hs-audit-areas { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-2xl); }
}
.hs-audit-area__icon {
  width: 4.5rem; height: 4.5rem;
  margin-bottom: var(--space-s);
}
.hs-audit-area__icon img { width: 100%; height: 100%; display: block; }
.hs-audit-area__title {
  font-family: var(--font-body);
  font-size: var(--fs-step-1);
  font-weight: 700;
  color: var(--color-text);
  margin: 0 0 var(--space-2xs);
}
.hs-audit-area__body { margin: 0; color: var(--color-text-body); }

/* ============================  About v2 — sans heading utility  ========= */
/* Lewis's refreshed design sets the big hero in DM Serif Display but the
   smaller section headings ("Who are Hebble & Stone?", the closing CTA) in
   DM Sans. This opts an individual heading out of the serif default. */
.hs-h--sans {
  font-family: var(--font-body);
  font-weight: 700;
}

/* ============================  About v2 — founder cards  ================ */
/* Circular, matched-size founder portraits (Lewis's design), plus the
   additions Matt asked for: a tinted "why I co-founded" callout and an
   expandable expertise list using native <details> (works without JS). */
.hs-portrait__frame--round {
  border-radius: 50%;
  aspect-ratio: 1;
  max-width: 12rem;
}
.hs-portrait__frame--round .hs-portrait__img { object-position: top center; }
/* The official founder photos are cut-outs on a transparent background, so a
   pastel frame colour shows behind the subject (Lewis's design): Matt rose,
   Lewis ice-blue. */
.hs-portrait__frame--rose    { background: var(--color-bg-rose); }
.hs-portrait__frame--iceblue { background: var(--color-bg-iceblue); }

.hs-founder-why {
  margin-top: var(--space-s);
  padding: var(--space-m);
  border-radius: var(--radius-card);
}
.hs-founder-why--iceblue { background: var(--color-bg-iceblue); }
.hs-founder-why--rose    { background: var(--color-bg-rose); }
.hs-founder-why__label {
  margin: 0 0 var(--space-2xs);
  font-size: var(--fs-step--1);
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-text);
}
.hs-founder-why p { margin: 0; }

.hs-founder-more {
  margin-top: var(--space-s);
  border-top: 1px solid var(--color-border-muted);
  padding-top: var(--space-s);
}
.hs-founder-more > summary {
  cursor: pointer;
  font-weight: 700;
  color: var(--color-text);
  list-style: none;
  display: flex;
  align-items: center;
  gap: var(--space-2xs);
}
.hs-founder-more > summary::-webkit-details-marker { display: none; }
.hs-founder-more > summary::after {
  content: "";
  width: 0.55em; height: 0.55em;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(45deg);
  transition: transform 150ms ease;
}
.hs-founder-more[open] > summary::after { transform: rotate(-135deg); }
.hs-founder-more > summary:focus-visible {
  outline: var(--border-focus);
  outline-offset: 3px;
  border-radius: var(--radius-sm);
}
.hs-founder-more ul {
  margin: var(--space-s) 0 0;
  padding-inline-start: 1.1em;
  color: var(--color-text-body);
}
.hs-founder-more li + li { margin-top: var(--space-2xs); }

/* Mobile: the two founder cards stack, so the collapsed "More about X's
   expertise" toggle floats just above the NEXT founder's photo and reads as
   that person's heading. Fix the ownership by (a) dropping the toggle's own
   hairline here (it mimics a section divider once stacked) and (b) adding one
   clear rule BETWEEN the founders, centred in the 64px row gap, so each person
   reads as a single bounded unit. Scoped below the ~46rem single-column point
   so it can never fire while the cards are side by side. */
@media (max-width: 45rem) {
  .hs-founder-more {
    border-top: 0;
    padding-top: 0;
    margin-top: var(--space-m);
  }
  .hs-portrait + .hs-portrait {
    border-top: 1px solid var(--color-border);
    padding-top: var(--space-2xl);
  }
}

/* deploy-cache-bust */
