/* ==========================================================================
   Eightstep site: page furniture and content blocks
   Uses variables and shared components from tokens.css.

   Each section is a self-contained block that any page can use, in any
   order: hero, logos, feature rows, delivery, features, bento, proof,
   stories, testimonial, news, FAQ, then the footer. Spacing contract: a block owns its
   bottom padding (a pb-* utility on its section) and never its top; the
   hero owns both; the footer owns its top. blocks.md describes each block's
   markup, options and scripts.
   ========================================================================== */
::selection {
  background-color: var(--mclaren-500);
  color: var(--neutral-950);
}
.container {
  width: 100%;
  max-width: calc(var(--layout-max) + var(--layout-gutter) * 2);
  margin-inline: auto;
  padding-inline: var(--layout-gutter);
}

/* ==========================================================================
   Backdrop
   McLaren and coral glows from the top corners, behind the header, hero and
   whatever follows. main.js sets the height to the bottom of the element
   marked data-backdrop-end (the hero if none is), and the mask fades
   everything out by then. Over the glows, main.js draws an arch of fine
   lines, or with backdrop--coil, a coil running left to right under the
   hero. The arch of fine lines over the glows
   is drawn by main.js.
   ========================================================================== */
.backdrop {
  position: absolute;
  top: 0;
  left: 0;
  z-index: -1;
  width: 100%;
  height: 100vh;
  pointer-events: none;
  -webkit-mask-image: linear-gradient(#000 45%, transparent);
  mask-image: linear-gradient(#000 45%, transparent);
}

/* The coil sits low, so its backdrop fades later */
.backdrop--coil {
  -webkit-mask-image: linear-gradient(#000 70%, transparent);
  mask-image: linear-gradient(#000 70%, transparent);
}

/* Radii match GLOW_REACH in main.js, so each line takes the colour beneath it */
.backdrop::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    radial-gradient(75% 95% at 0% 0%, var(--glow-left), transparent),
    radial-gradient(75% 95% at 100% 0%, var(--glow-right), transparent);
  background-blend-mode: multiply;
  opacity: .3;
}

.backdrop__arch {
  position: relative;
  display: block;
  width: 100%;
  height: 100%;
}

/* ==========================================================================
   Header
   Sticks to the top; once the page scrolls, main.js adds header--scrolled
   for a translucent paper background with a blur behind it.
   ========================================================================== */
.header {
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
}

/* Anchored sections land just below the header, not under it */
:root { scroll-padding-top: calc(var(--header-h) + var(--space-4)); }

/* Paper and blur sit on a layer behind the header's content, not on the
   header itself: a blur on the header would stop the mega menu's own blur
   from reaching the page behind it */
.header::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  transition: background-color var(--duration-base) var(--ease-out);
}

.header--scrolled::before {
  background: var(--surface-header);
  backdrop-filter: blur(var(--blur-header));
}

/* The open phone menu sits over page content, so it gets solid paper */
.header--open::before { background: var(--surface-page); }

.header__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  min-height: var(--header-h);
  padding-block: var(--space-3);
}

.header__logo { border-radius: var(--radius-sm); }
.header__logo img { width: auto; height: 45px; }

/* Menu button: two bars that cross into a close mark when open */
.header__toggle {
  position: relative;
  width: var(--control-h-md);
  height: var(--control-h-md);
  border: 0;
  border-radius: var(--radius-md);
  background: var(--action-secondary-bg);
  cursor: pointer;
  transition: var(--transition-control);
}
.header__toggle:hover { background: var(--action-secondary-bg-hover); }
.header__toggle:active { background: var(--action-secondary-bg-pressed); transform: translateY(1px); }

.header__toggle::before,
.header__toggle::after {
  content: "";
  position: absolute;
  left: 11px;
  right: 11px;
  height: 2px;
  border-radius: 1px;
  background: var(--text-primary);
  transition: transform var(--duration-base) var(--ease-in-out);
}
.header__toggle::before { top: 15px; }
.header__toggle::after { top: 23px; }

.header--open .header__toggle::before { transform: translateY(4px) rotate(45deg); }
.header--open .header__toggle::after { transform: translateY(-4px) rotate(-45deg); }

/* Small screens: nav and booking button open as a panel under the bar,
   over the page content rather than pushing it down */
.header__menu {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  display: none;
  flex-direction: column;
  gap: var(--space-4);
  max-height: calc(100vh - var(--header-h));
  padding: var(--space-2) var(--layout-gutter) var(--space-6);
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--surface-page);
  box-shadow: var(--shadow-lg);
  /* Shadow below only, so the bar and panel read as one sheet */
  clip-path: inset(0 0 -64px 0);
}
.header--open .header__menu { display: flex; }

.nav__list,
.megamenu__cards,
.megamenu__list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.nav__link {
  display: block;
  padding: var(--space-3) 0;
  border-radius: var(--radius-md);
  color: var(--text-primary);
  font-weight: var(--weight-semibold);
  text-decoration: none;
  transition: var(--transition-control);
}

/* An item with a menu and no page of its own is a label: a button, so the
   keyboard can still reach its menu, styled to match the links */
button.nav__link {
  border: 0;
  background: none;
  font-family: inherit;
  font-size: inherit;
  line-height: inherit;
  cursor: default;
}

.megamenu { display: none; }

/* Small screens: an item with a menu expands in place. The label spans the
   panel with a chevron at its end, which turns over while the menu is open,
   and the menu lists its pages under the label */
@media (max-width: 1023px) {
  button.nav__link {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    text-align: left;
    cursor: pointer;
  }

  button.nav__link::after {
    content: "";
    width: 8px;
    height: 8px;
    margin-right: var(--space-3);
    border-right: 2px solid currentColor;
    border-bottom: 2px solid currentColor;
    transform: translateY(-2px) rotate(45deg);
    transition: transform var(--duration-base) var(--ease-in-out);
  }
  .nav__item--open > button.nav__link::after { transform: translateY(2px) rotate(-135deg); }

  .nav__item--open > .megamenu {
    display: block;
    padding-bottom: var(--space-3);
  }

  .megamenu__card,
  .megamenu__link {
    display: block;
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-md);
    color: var(--text-primary);
    text-decoration: none;
  }
  .megamenu__card[aria-current="page"],
  .megamenu__link[aria-current="page"] { background: var(--surface-hover); }

  .megamenu__title,
  .megamenu__link { font-weight: var(--weight-semibold); }

  .megamenu__title,
  .megamenu__text { display: block; }

  .megamenu__text {
    color: var(--text-secondary);
    font-size: var(--text-sm);
  }

  /* Secondary links: titles only, grouped on a sunken fill as on desktop */
  .megamenu__list {
    margin-top: var(--space-2);
    padding-block: var(--space-2);
    border-radius: var(--radius-md);
    background: var(--surface-sunken);
  }
}

@media (min-width: 1024px) {
  .header__toggle { display: none; }

  .header__inner { position: relative; }

  .header__menu {
    position: static;
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: var(--space-5);
    max-height: none;
    padding: 0;
    overflow: visible;
    background: none;
    box-shadow: none;
    clip-path: none;
  }

  .nav__list {
    display: flex;
    gap: var(--space-2);
  }

  /* Square pill on hover, and while the item's menu is open */
  .nav__link { padding: var(--space-2) var(--space-3); }
  .nav__link:hover,
  .nav__item--open > .nav__link { background: var(--surface-card); }

  /* ---------- Mega menu ----------
     A translucent rim around a more solid panel, both over a blur.
     main.js adds nav__item--open on hover or Arrow Down, and sets left so
     the menu opens under its nav item without leaving the container. */
  .megamenu {
    position: absolute;
    top: 100%;
    left: 0;
    display: block;
    max-width: calc(100% - var(--layout-gutter) * 2);
    padding: var(--space-2);
    border-radius: var(--radius-xl);
    background: var(--surface-menu-edge);
    backdrop-filter: blur(var(--blur-menu));
    box-shadow: var(--shadow-lg);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-4px);
    transition: opacity var(--duration-fast) var(--ease-out), transform var(--duration-fast) var(--ease-out), visibility 0s linear var(--duration-fast);
  }

  .nav__item--open > .megamenu {
    opacity: 1;
    visibility: visible;
    transform: none;
    transition: opacity var(--duration-base) var(--ease-out), transform var(--duration-base) var(--ease-out);
  }

  /* Invisible strip over the gap above the menu, so the pointer can move
     down from the nav item without leaving it */
  .megamenu::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 100%;
    height: var(--space-4);
  }

  .megamenu__panel {
    display: flex;
    gap: var(--space-2);
    padding: var(--space-2);
    border-radius: var(--radius-lg);
    background: var(--surface-menu);
  }

  /* Two cards per column; every third card starts a new column to the right */
  .megamenu__cards {
    display: grid;
    grid-auto-flow: column;
    grid-template-rows: repeat(2, auto);
    gap: var(--space-1);
  }

  .megamenu__card {
    display: block;
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-md);
    color: var(--text-primary);
    text-decoration: none;
    transition: var(--transition-control);
  }
  .megamenu__card:hover,
  .megamenu__card[aria-current="page"] { background: var(--surface-hover); }

  .megamenu__title {
    display: block;
    font-weight: var(--weight-semibold);
  }

  /* One line only: the card widens to fit rather than wrapping */
  .megamenu__text {
    display: block;
    color: var(--text-secondary);
    font-size: var(--text-sm);
    white-space: nowrap;
  }

  /* Secondary links: titles only, grouped on a sunken fill instead of a divider */
  .megamenu__list {
    padding: var(--space-2);
    border-radius: var(--radius-md);
    background: var(--surface-sunken);
  }

  .megamenu__link {
    display: block;
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-sm);
    color: var(--text-primary);
    font-weight: var(--weight-semibold);
    text-decoration: none;
    white-space: nowrap;
    transition: var(--transition-control);
  }
  .megamenu__link:hover { background: var(--surface-hover); }
}

/* ==========================================================================
   Hero
   The same structure on every page: hero__text (an optional eyebrow, a
   headline, a lead and a row of actions) and, optionally, hero__media (a
   photo with floats). The Contact page swaps the actions for a contacts
   list and the media for an enquiry form (hero__form). The home hero is centred, with its visual below and
   padding from py-150; its headline is the h1. Service pages use
   hero--split: the page's name as an eyebrow, which is the h1, then a
   smaller headline in a p styled as a title, left aligned, and a square
   photo beside it. Its top padding comes from pt-100; its bottom padding
   is set here, to hold the backdrop's coil with a gap above and below.
   ========================================================================== */
.hero { text-align: center; }

/* The page's name above the headline. On service pages it's the h1. */
.hero__eyebrow {
  margin-bottom: var(--space-4);
  color: var(--text-secondary);
  font-size: var(--text-md);
  font-weight: var(--weight-semibold);
}

/* Plain text from the CMS: balance evens out the line breaks, no manual splits */
.hero__title {
  font-size: var(--text-display);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-display);
  letter-spacing: var(--tracking-tight);
  text-wrap: balance;
}

.hero__lead {
  max-width: 40ch;
  margin: var(--space-6) auto 0;
  font-size: var(--text-lead);
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-3);
  margin-top: var(--space-8);
}

/* Optional large visual below the actions: a photo with floats over its edges */
.hero__media {
  position: relative;
  max-width: 1040px;
  margin: var(--space-16) auto 0;
  text-align: left;
}

/* --focus on the img sets the crop's focal point */
.hero__image {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-lg);
  object-fit: cover;
  object-position: var(--focus, 50% 50%);
}

.hero__float--start {
  left: var(--space-3);
  bottom: var(--space-6);
}

.hero__float--end {
  top: var(--space-6);
  right: var(--space-3);
  animation-delay: -3s;
}

/* ---------- Split hero, for service pages ---------- */
/* The bottom padding holds the coil: its height, which main.js reads,
   with a gap above (to the hero's content) and below (to the next block) */
.hero--split {
  --coil-height: 112px;
  --coil-gap: 68px;
  padding-bottom: calc(var(--coil-height) + var(--coil-gap) * 2);
  text-align: left;
}

.hero--split .hero__title { font-size: var(--text-headline); }

.hero--split .hero__lead {
  max-width: 44ch;
  margin-inline: 0;
}

.hero--split .hero__actions { justify-content: flex-start; }

.hero--split .hero__media,
.hero--split .hero__form { margin: var(--space-12) 0 0; }

/* Contact details in place of the actions */
.hero--split .hero__contacts { margin-top: var(--space-8); }

.hero--split .hero__image { aspect-ratio: 3 / 2; }

/* Split hero: text left, a square photo right */
@media (min-width: 768px) {
  .hero--split .container {
    display: grid;
    grid-template-columns: 1fr minmax(0, 320px);
    align-items: center;
    column-gap: var(--space-12);
  }

  .hero--split .hero__media,
  .hero--split .hero__form { margin: 0; }
  .hero--split .hero__image { aspect-ratio: 1; }

  /* hero--form: the form's top lines up with the lead. The text's parts join
     the hero's grid, so the form can start on the lead's row; the last row
     takes whatever extra height the form needs. */
  .hero--form .container {
    grid-template-rows: repeat(4, auto) 1fr;
    align-items: start;
  }

  .hero--form .hero__text { display: contents; }
  .hero--form .hero__text > * { grid-column: 1; }

  /* The same top margin as .hero__lead, so the two start level */
  .hero--form .hero__form {
    grid-column: 2;
    grid-row: 3 / -1;
    margin-top: var(--space-6);
  }
}

@media (min-width: 1024px) {
  .hero--split .container {
    grid-template-columns: 1fr minmax(0, 420px);
    column-gap: var(--space-16);
  }
}

/* Overhang the photo's edges once there's room beside it */
@media (min-width: 1200px) {
  .hero--split .container { grid-template-columns: 1fr minmax(0, 480px); }

  .hero__float--start {
    left: calc(var(--space-10) * -1);
    bottom: var(--space-12);
  }

  .hero__float--end {
    top: var(--space-12);
    right: calc(var(--space-10) * -1);
  }
}

/* ---------- Tiles hero: footage in the shape of the mark ----------
   hero--tiles fills the split hero's media slot with two tiles of footage
   (an img each for now, muted looping videos later, as hero__footage) laid
   out like the Eightstep mark: two squares at the mark's 26% radius, the
   front one up and to the right of the back one, overlapping by the same
   amounts. The box keeps the mark's 7:9 proportions. Floats sit around
   them as on the photo hero. */
.hero__tiles { aspect-ratio: 7 / 9; }

.hero__tile {
  position: absolute;
  width: calc(100% * 50 / 70);
  aspect-ratio: 1;
  overflow: hidden;
  border-radius: 26%;
  box-shadow: var(--shadow-lg);
}

.hero__tile--back {
  left: 0;
  bottom: 0;
}

.hero__tile--front {
  top: 0;
  right: 0;
}

.hero__footage {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--focus, 50% 50%);
}

/* A float in the pocket beside the back tile, under the front one */
.hero__float--side {
  right: var(--space-3);
  bottom: 22%;
  animation-delay: -1.5s;
}

/* Three notes crowd the smaller tiles, so the side one waits for 1200px.
   The hero__tiles ancestor outranks .note's own display, set later. */
@media (max-width: 1199px) {
  .hero__tiles .hero__float--side { display: none; }
}

/* The box is taller than it is wide. So the hero stays short enough for
   the logo strip to show on a 900px screen, the tiles reach down into the
   coil's band, which runs behind the back tile, and the band's gaps are
   trimmed. */
.hero--tiles { --coil-gap: 48px; }

@media (min-width: 768px) {
  .hero--tiles .hero__media { margin-bottom: calc(var(--coil-gap) * -1 - var(--coil-height) * 0.9); }
}

@media (min-width: 1200px) {
  .hero--tiles .container { grid-template-columns: 1fr minmax(0, 420px); }
  .hero__float--side { right: calc(var(--space-10) * -1); }
}

/* ==========================================================================
   Contacts
   Ways to reach us as a short list: an Eightstep icon beside a label, a
   value and a line of detail. The Contact page's hero holds one.
   ========================================================================== */
.contacts {
  display: grid;
  gap: var(--space-6);
  margin: 0;
  padding: 0;
  list-style: none;
}

.contacts__item {
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr);
  align-items: start;
  gap: var(--space-1) var(--space-4);
}

.contacts__icon { grid-row: span 3; }

.contacts__label {
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
}

.contacts__value { font-size: var(--text-lg); }
.contacts__value a { color: inherit; }

.contacts__text {
  color: var(--text-secondary);
  font-size: var(--text-sm);
}

/* ---------- Article hero: the post's title as the h1, its art below ----------
   The text sits in a reading column (--layout-measure) centred on the
   page, left aligned within it, and the Article block's body takes the
   same column. The eyebrow holds the way back to the index and the post's
   topic; a byline (the date and reading time) follows the lead. Article pages
   have no coil, so the bottom padding is a plain gap before the body. */
.hero--article {
  padding-bottom: var(--space-16);
  text-align: left;
}

.hero--article .hero__text {
  max-width: var(--layout-measure);
  margin-inline: auto;
}

.hero--article .hero__title {
  max-width: 22ch;
  font-size: var(--text-headline);
}

.hero--article .hero__lead {
  max-width: 60ch;
  margin-inline: 0;
}

.hero__crumb {
  border-radius: var(--radius-xs);
  color: inherit;
  text-decoration: none;
}
.hero__crumb:hover { text-decoration: underline; }

.hero__byline {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-3);
  margin-top: var(--space-8);
}

.hero__dateline { color: var(--text-secondary); }

/* The art fills the content column, wider than the text */
.hero--article .hero__media {
  max-width: none;
  margin: var(--space-12) 0 0;
}

/* Blog artwork is 2:1 */
.hero__image--art { aspect-ratio: 2 / 1; }

/* ---------- Article artwork ----------
   A photograph with the brand gradient laid over it: McLaren from the
   bottom left merging into coral at the top right, deliberately brighter
   than the page's hero glow. The img keeps its own layout class
   (hero__image, articles__art, news__art); the div.art around it only
   hosts the tint, which takes the wrapper's radius. --art-tint sets how
   much of the photo shows through. */
.art {
  position: relative;
  display: block;
  border-radius: var(--radius-lg);
}

.art::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(to top right, var(--mclaren-500), var(--coral-500));
  opacity: var(--art-tint, 0.45);
  pointer-events: none;
}

.hero--article .art { border-radius: var(--radius-xl); }

/* In News the art fills its panel, which clips it */
.news__panel > .art {
  position: absolute;
  inset: 0;
  border-radius: 0;
}

/* In the feature hero from 768px the art fills the media slot, like the image inside it */
@media (min-width: 768px) {
  .hero--feature .hero__media > .art {
    position: absolute;
    inset: 0;
  }
}

/* ---------- Feature hero: the newest article as the hero of the index ----------
   The text and the post's artwork sit in a white card (hero__card), like
   the article cards below it, with the same 12px inset so the text lines
   up with theirs: the art on top on phones at 2:1, then text left and art
   right from 768px, where the art fills the card's height. No coil
   beneath, so the bottom padding is a plain gap for the compact subscribe
   strip that follows. */
.hero--feature { padding-bottom: var(--space-16); }

.hero--feature .hero__card {
  position: relative;
  display: grid;
  gap: var(--space-5);
  padding: var(--space-3);
  border-radius: var(--radius-xl);
  background: var(--surface-card);
  box-shadow: var(--shadow-xs);
  transition: box-shadow var(--duration-base) var(--ease-out), transform var(--duration-base) var(--ease-out);
}
.hero--feature .hero__card:hover {
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
}

.hero--feature .hero__text { padding: var(--space-2) var(--space-3) var(--space-3); }

/* The whole card is the link, as the article cards are: the title's link
   reaches over the card (above the art, which is positioned), the focus
   ring goes on the card, and the button stays on top so it still works. */
.hero--feature .hero__title a {
  color: inherit;
  text-decoration: none;
}
.hero--feature .hero__title a::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: var(--radius-xl);
}
.hero--feature .hero__title a:focus-visible { box-shadow: none; }
.hero--feature .hero__card:has(a:focus-visible) { box-shadow: var(--focus-ring); }

.hero--feature .hero__actions {
  position: relative;
  z-index: 2;
}

.hero--feature .hero__media {
  order: -1;
  margin: 0;
}

.hero--feature .hero__image {
  aspect-ratio: 2 / 1;
  border-radius: var(--radius-lg);
  box-shadow: none;
}

@media (min-width: 768px) {
  .hero--feature .container { display: block; }

  .hero--feature .hero__card { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }

  .hero--feature .hero__text { padding: var(--space-6) var(--space-8) var(--space-6) var(--space-3); }

  .hero--feature .hero__media { order: 0; }

  /* As tall as the text beside it, cropping the art's sides as needed */
  .hero--feature .hero__image {
    position: absolute;
    inset: 0;
    height: 100%;
    aspect-ratio: auto;
  }
}

/* ==========================================================================
   Enquiry
   A contact form, with no card behind it: fields, a note and a send button.
   It posts without script; the reply comes back as #sent or #not-sent, which
   shows the matching message (:target). A field hidden off screen catches
   bots. The fields go two across when the form is wide enough, wherever it
   sits.
   ========================================================================== */
.enquiry {
  display: grid;
  gap: var(--space-5);
  container-type: inline-size;
}

.enquiry__fields {
  display: grid;
  gap: var(--space-5);
}

@container (min-width: 440px) {
  .enquiry__fields { grid-template-columns: repeat(2, 1fr); }
  .enquiry__message { grid-column: 1 / -1; }
}

.enquiry__trap {
  position: absolute;
  left: -9999px;
}

.enquiry__note {
  color: var(--text-secondary);
  font-size: var(--text-sm);
}

.enquiry__submit { justify-self: start; }

.enquiry__status {
  display: none;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-4);
  border-radius: var(--radius-md);
  font-weight: var(--weight-semibold);
}

.enquiry__status:target { display: flex; }
.enquiry__status--sent { background: var(--status-success-bg); color: var(--status-success-fg); }
.enquiry__status--error { background: var(--status-danger-bg); color: var(--status-danger-fg); }

/* ==========================================================================
   Logos
   Client logos, redrawn in one colour (neutral-300, #D3C5AD) in assets/logos.
   Each img's width and height set its optically balanced size. The strip
   never runs wider than the content column: rows of two on phones, three
   on tablets, then one row spread edge to edge across the column.
   ========================================================================== */
.logos { text-align: center; }

.logos__title {
  color: var(--text-secondary);
  font-size: var(--text-sm);
  font-weight: var(--weight-regular);
}

.logos__list {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  justify-items: center;
  align-items: center;
  gap: var(--space-8) var(--space-6);
  margin: var(--space-6) 0 0;
  padding: 0;
  list-style: none;
}

/* Shrinks to its cell if the cell is narrower than the logo */
.logos__logo {
  display: block;
  max-width: 100%;
  height: auto;
}

@media (min-width: 640px) {
  .logos__list { grid-template-columns: repeat(3, 1fr); }
}

@media (min-width: 1024px) {
  .logos__list {
    display: flex;
    justify-content: space-between;
    gap: var(--space-12);
  }
}

/* ==========================================================================
   Feature rows
   Stacked cards, each pairing a short pitch with a visual, after Stripe's
   product pages. The visual is product UI built from the .ui pieces, on a
   warm panel, a diagram (feature-row__diagram), or a photo filling it
   (feature-row__media--photo).
   ========================================================================== */
.feature-rows__list {
  display: grid;
  gap: var(--space-4);
}

.feature-row {
  display: grid;
  overflow: hidden;
  border-radius: var(--radius-xl);
  background: var(--surface-card);
  box-shadow: var(--shadow-xs);
}

.feature-row__text {
  display: grid;
  align-content: start;
  gap: var(--space-4);
  padding: var(--space-8) var(--space-6);
}

.feature-row__title {
  font-size: var(--text-lead);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
}

.feature-row__desc { color: var(--text-secondary); }

.feature-row__points {
  display: grid;
  gap: var(--space-3);
  margin: var(--space-2) 0 0;
  padding: 0;
  font-size: var(--text-sm);
  list-style: none;
}

.feature-row__points li {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
}

.feature-row__points .tick { margin-top: 2px; }

.feature-row__media {
  position: relative;
  display: grid;
  place-items: center;
  min-height: 320px;
  padding: var(--space-8) var(--space-6);
  background: radial-gradient(70% 70% at 50% 40%, var(--neutral-50), transparent), var(--neutral-100);
}

.feature-row__media .ui {
  width: 100%;
  max-width: 420px;
}

/* A diagram in place of product UI: an inline line drawing (see Diagrams,
   below) that fills the panel. It explains something, so its media isn't
   hidden from assistive tech. */
.feature-row__media:has(.diagram) { padding: var(--space-6); }

/* ---------- Diagrams ----------
   Inline SVG line drawings in fine strokes, labelled in the page's type.
   Each comes as a wide version and a stacked one for phones. main.js adds
   diagram--ready (lines hidden), then diagram--drawn when it scrolls into
   view: outlines draw in, labels fade up, then pulses travel along the links.
   Every drawn shape is a path with pathLength="1"; pulses use 100. Without
   the script, or with reduced motion, diagrams show finished and still. */
.diagram {
  display: block;
  width: 100%;
  height: auto;
}
.diagram--stacked { display: none; }

@media (max-width: 767px) {
  .diagram--wide { display: none; }
  .diagram--stacked { display: block; }
}

.diagram__panel-fill { fill: color-mix(in srgb, var(--neutral-0) 55%, transparent); }

.diagram__panel,
.diagram__ring,
.diagram__mesh {
  fill: none;
  stroke: var(--neutral-300);
  stroke-width: 2;
}

.diagram__ring-fill { fill: var(--neutral-0); }
.diagram__end { fill: var(--neutral-600); }

/* Timeline bars: Microsoft's retention in a light outline, your backup in ink */
.diagram__bar {
  fill: none;
  stroke-width: 2;
}
.diagram__bar--microsoft { stroke: var(--neutral-400); }
.diagram__bar--yours {
  stroke: var(--neutral-950);
  stroke-width: 2.5;
}
.diagram__bar-fill { fill: color-mix(in srgb, var(--neutral-0) 70%, transparent); }
.diagram__bar--yours-fill { fill: var(--neutral-0); }

/* How far Microsoft can extend a setting, as a dotted line */
.diagram__dash {
  fill: none;
  stroke: var(--neutral-400);
  stroke-width: 2;
  stroke-dasharray: 2 6;
  stroke-linecap: round;
}

.diagram__note--strong {
  fill: var(--text-primary);
  font-weight: var(--weight-semibold);
}

.diagram__pulse--bar { stroke-dasharray: 4 96; }

.diagram__guide {
  fill: none;
  stroke: var(--neutral-200);
  stroke-width: 1.5;
  stroke-dasharray: 2 6;
}

.diagram__unit {
  fill: none;
  stroke-width: 2.5;
}
.diagram__unit--source { stroke: var(--neutral-600); }
.diagram__unit--azure { stroke: var(--neutral-950); }
.diagram__light--source { fill: var(--neutral-600); }
.diagram__light--azure { fill: var(--neutral-950); }

.diagram__strand {
  fill: none;
  stroke: var(--neutral-400);
  stroke-width: 1.5;
  stroke-linecap: round;
}

.diagram__caption,
.diagram__note { fill: var(--text-secondary); }
.diagram__caption { font-weight: var(--weight-semibold); }

.diagram__label {
  fill: var(--text-primary);
  font-weight: var(--weight-semibold);
}

/* A short dash travelling along a link, resting between laps */
.diagram__pulse {
  fill: none;
  stroke: var(--neutral-950);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-dasharray: 5 95;
  stroke-dashoffset: 100;
  animation: diagram-pulse 3.2s var(--ease-in-out) infinite;
  animation-delay: var(--p, 0s);
}
.diagram__pulse--mesh { stroke: var(--neutral-600); }

@keyframes diagram-pulse {
  to { stroke-dashoffset: 0; }
}

.diagram--ready .diagram__draw {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
}
.diagram--ready .diagram__fade,
.diagram--ready .diagram__pulse { opacity: 0; }

.diagram--drawn .diagram__draw {
  stroke-dashoffset: 0;
  transition: stroke-dashoffset 1.2s var(--ease-out) var(--d, 0s);
}
.diagram--drawn .diagram__fade {
  opacity: 1;
  transition: opacity 0.6s var(--ease-out) var(--d, 0s);
}
.diagram--drawn .diagram__pulse {
  opacity: 1;
  transition: opacity 0.6s var(--ease-out) 1.8s;
}

@media (prefers-reduced-motion: reduce) {
  .diagram__pulse { display: none; }
}

.feature-row__media--photo { padding: 0; }

/* A float over the photo's bottom-left corner */
.feature-row__float {
  left: var(--space-6);
  bottom: var(--space-6);
}

.feature-row__photo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

@media (min-width: 1024px) {
  .feature-row {
    grid-template-columns: 1fr 1fr;
    min-height: 420px;
  }

  .feature-row__text { padding: var(--space-12); }
  .feature-row__media { padding: var(--space-12); }
}

/* ==========================================================================
   Delivery
   One section per delivery area of the service, as the SLA groups them. It
   opens with an h2 naming the area, then the area's headline service and
   what it does for you in one run of text: the service in ink, the benefit
   in grey. A full-width mock UI follows on a warm panel, running off the
   panel's bottom edge, then the area's other services as a features list.
   delivery--split swaps the mock for a photo, with the points beside it.
   ========================================================================== */
.delivery__lead {
  max-width: 56ch;
  font-size: var(--text-lead);
  line-height: 1.35;
}

.delivery__service,
.delivery__benefit {
  display: inline;
  font-size: inherit;
}

.delivery__service { font-weight: var(--weight-semibold); }
.delivery__benefit { color: var(--text-secondary); }

.delivery__stage {
  position: relative;
  height: 340px;
  margin-bottom: var(--space-10);
  padding: var(--space-6) var(--space-4) 0;
  overflow: hidden;
  border-radius: var(--radius-xl);
  background: radial-gradient(70% 90% at 50% 0%, var(--neutral-50), transparent), var(--neutral-100);
}

/* ---------- Split: the area's points to the left, a photo to the right ----------
   For an area better shown in people than in product UI. On phones the photo
   comes first. */
.delivery__split {
  display: grid;
  gap: var(--space-8);
}

.delivery__photo {
  position: relative;
  order: -1;
  min-height: 280px;
  overflow: visible;
}

/* --focus on the img sets the crop's focal point */
.delivery__image {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border-radius: var(--radius-xl);
  object-fit: cover;
  object-position: var(--focus, 50% 50%);
}

.delivery__split .delivery__float {
  right: auto;
  left: var(--space-3);
  bottom: var(--space-6);
}

@media (min-width: 1024px) {
  .delivery__split {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    gap: var(--space-16);
  }

  .delivery__split .features__list { grid-template-columns: repeat(2, 1fr); }

  .delivery__photo {
    order: 0;
    min-height: 0;
  }

  .delivery__split .delivery__float { left: calc(var(--space-10) * -1); }
}

/* ---------- Side: the mock beside the text ----------
   The intro and the area's points in one column, the mock's panel in the
   other, for a run of Delivery sections that would otherwise all stack the
   same way. Phones read intro, mock, points. From 1024px the panel sits
   beside both and stretches to their height (the mock still runs off its
   bottom edge); delivery--flip puts the panel on the left. The grid goes on
   the container. */
.delivery__side {
  display: grid;
  grid-template-areas: "intro" "stage" "list";
  gap: var(--space-8);
}

.delivery__side > .section-intro {
  grid-area: intro;
  margin-bottom: 0;
}

.delivery__side > .delivery__stage {
  grid-area: stage;
  margin-bottom: 0;
}

.delivery__side > .features__list { grid-area: list; }

@media (min-width: 1024px) {
  .delivery__side {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    grid-template-areas: "intro stage" "list stage";
    align-items: start;
    column-gap: var(--space-16);
  }

  .delivery--flip .delivery__side {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    grid-template-areas: "stage intro" "stage list";
  }

  /* Beside the text the panel is as tall as the text, so the mock sits
     centred in it with the panel showing round it, as a feature row's does,
     instead of running off the bottom */
  .delivery__side > .delivery__stage {
    display: grid;
    align-self: stretch;
    align-content: center;
    height: auto;
    min-height: 460px;
    padding: var(--space-14);
  }

  .delivery__side > .delivery__stage > .ui:not(.float) { min-height: 0; }

  .delivery__side > .features__list { grid-template-columns: repeat(2, 1fr); }
}

/* The mock is always taller than the panel, so every one runs off its bottom edge */
.delivery__stage > .ui:not(.float) { min-height: calc(100% + var(--space-6)); }

.delivery__float {
  right: var(--space-6);
  bottom: var(--space-6);
  animation-delay: -2s;
}

/* Shown from 768px only, for a mock that leaves no clear space on phones */
@media (max-width: 767px) {
  .float.delivery__float--wide { display: none; }   /* outranks .note, which sets display later in the file */
}

@media (min-width: 768px) {
  .delivery__stage {
    height: 420px;
    padding: var(--space-10) var(--space-10) 0;
  }

  .delivery__float {
    right: var(--space-16);
    bottom: var(--space-8);
  }
}

@media (min-width: 1024px) {
  .delivery__stage {
    height: 460px;
    padding: var(--space-14) var(--space-14) 0;
  }
}

/* ==========================================================================
   Topics
   A numbered list of short items beside the block's intro. The numbers come
   from a CSS counter, so the markup is a plain ol. On desktop the intro
   sticks while the list scrolls past it.
   ========================================================================== */
.topics__layout {
  display: grid;
  gap: var(--space-2);
}

.topics__list {
  display: grid;
  gap: var(--space-8) var(--space-6);
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: topic;
}

.topics__item {
  display: grid;
  align-content: start;
  gap: var(--space-2);
  padding-top: var(--space-6);
  border-top: 1px solid var(--neutral-200);
  counter-increment: topic;
}

.topics__item::before {
  content: counter(topic, decimal-leading-zero);
  margin-bottom: var(--space-4);
  color: var(--neutral-400);
  font-size: var(--text-title);
  font-weight: var(--weight-light);
  line-height: 1;
  letter-spacing: var(--tracking-tight);
}

.topics__title {
  font-size: var(--text-md);
  font-weight: var(--weight-semibold);
}

.topics__text { color: var(--text-secondary); }

@media (min-width: 640px) {
  .topics__list { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 1024px) {
  .topics__layout {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    gap: var(--space-16);
  }

  /* align-self keeps the intro its own height, so it can stick */
  .topics__intro {
    position: sticky;
    top: calc(var(--header-h) + var(--space-8));
    align-self: start;
    margin-bottom: 0;
  }
}

/* ==========================================================================
   Explorer
   A list of items, each a title and a line or two, with a visual each. Below
   1024px every visual shows under its item. From 1024px one item is chosen
   and its stage shows beside the list. There, each item's summary is covered
   by a button, labelled by its title, so links can't go in the text. main.js
   adds explorer--ready and marks the chosen item; without the script every
   stage shows under its item at every width.
   ========================================================================== */
/* minmax keeps a wide mock from stretching the column past the screen */
.explorer__list {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-12);
  margin: 0;
  padding: 0;
  list-style: none;
}

.explorer__summary {
  display: grid;
  gap: var(--space-2);
}

.explorer__title {
  font-size: var(--text-md);
  font-weight: var(--weight-semibold);
}

.explorer__text { color: var(--text-secondary); }

/* Only needed where items switch the stage, from 1024px */
.explorer__toggle { display: none; }

/* The visual: a warm panel the mock runs off the bottom of */
.explorer__stage {
  position: relative;
  height: 340px;
  margin-top: var(--space-6);
  padding: var(--space-6) var(--space-4) 0;
  overflow: hidden;
  border-radius: var(--radius-xl);
  background: radial-gradient(70% 90% at 50% 0%, var(--neutral-50), transparent), var(--neutral-100);
}

.explorer__stage > .ui { min-height: calc(100% + var(--space-6)); }

@media (min-width: 768px) {
  .explorer__stage {
    height: 420px;
    padding: var(--space-10) var(--space-10) 0;
  }
}

/* The list on the left as cards, the chosen stage on the right, as tall as the list */
@media (min-width: 1024px) {
  .explorer--ready .explorer__list {
    position: relative;
    min-height: 520px;
    gap: var(--space-3);
    padding-right: calc(58% + var(--space-12));
  }

  .explorer--ready .explorer__summary {
    position: relative;
    padding: var(--space-5) var(--space-6);
    border-radius: var(--radius-lg);
    transition: background-color var(--duration-fast) var(--ease-out), box-shadow var(--duration-fast) var(--ease-out);
  }

  /* Covers the summary, so the whole item chooses it */
  .explorer--ready .explorer__toggle {
    display: block;
    position: absolute;
    inset: 0;
    border: 0;
    border-radius: inherit;
    background: none;
    cursor: pointer;
  }

  .explorer__toggle:focus-visible { box-shadow: var(--focus-ring); }

  .explorer--ready .explorer__item:not(.explorer__item--on) .explorer__summary:hover { background: var(--surface-hover); }

  .explorer--ready .explorer__item--on .explorer__summary {
    background: var(--surface-card);
    box-shadow: var(--shadow-xs);
  }

  .explorer--ready .explorer__item--on .explorer__toggle { cursor: default; }

  .explorer--ready .explorer__stage {
    position: absolute;
    top: 0;
    right: 0;
    width: 58%;
    height: 100%;
    margin-top: 0;
  }

  .explorer--ready .explorer__item:not(.explorer__item--on) .explorer__stage { display: none; }

  .explorer--ready .explorer__item--on .explorer__stage { animation: explorer-in var(--duration-base) var(--ease-out); }
}

@keyframes explorer-in {
  from { opacity: 0; }
}

/* ==========================================================================
   Channels
   The ways to reach us, as cards: an Eightstep icon, an optional badge, a
   title, its action, then a line or two. Put the preferred way first, with
   the accent button; the others take secondary buttons.
   ========================================================================== */
.channels__list {
  display: grid;
  gap: var(--space-4);
  margin: 0;
  padding: 0;
  list-style: none;
}

.channels__item {
  display: grid;
  align-content: start;
  justify-items: start;
  gap: var(--space-3);
}

.channels__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  width: 100%;
  margin-bottom: var(--space-2);
}

.channels__title {
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
}

.channels__text { color: var(--text-secondary); }

.channels__action { margin-bottom: var(--space-1); }

@media (min-width: 768px) {
  .channels__list { grid-template-columns: repeat(2, 1fr); }
  .channels__item { padding: var(--space-10); }
}

/* ==========================================================================
   Features
   A grid of short items, each an icon, a title and a line or two, divided
   by hairlines.
   ========================================================================== */
.features__list {
  display: grid;
  gap: var(--space-8) var(--space-6);
  margin: 0;
  padding: 0;
  list-style: none;
}

.features__item {
  display: grid;
  align-content: start;
  gap: var(--space-2);
  padding-top: var(--space-6);
  border-top: 1px solid var(--neutral-200);
}

.dark-panel .features__item { border-top-color: var(--border-inverse); }

.features__icon {
  display: grid;
  place-items: center;
  width: var(--control-h-md);
  height: var(--control-h-md);
  margin-bottom: var(--space-2);
  border-radius: var(--radius-md);
  background: var(--action-secondary-bg);
  color: var(--text-primary);
}

.features__icon svg {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* For a sequence: an Eightstep icon paired with the step number, in place
   of the icon tile. Use the icon variant that suits the surface (mono-dark
   on a dark panel). */
.features__marker {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-2);
}

.features__brand {
  width: 40px;
  height: 40px;
}

.features__step {
  color: var(--text-secondary);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
}

.features__title {
  font-size: var(--text-md);
  font-weight: var(--weight-semibold);
}

.features__text { color: var(--text-secondary); }

@media (min-width: 640px) {
  .features__list { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 1024px) {
  .features__list { grid-template-columns: repeat(3, 1fr); }

  /* Exactly four items sit in one row */
  .features__list:has(> :nth-child(4):last-child) { grid-template-columns: repeat(4, 1fr); }
}

/* ==========================================================================
   Services
   A bento grid. Each card has soft McLaren and coral glows, multiplied so
   they overprint Ember where they meet, as in the mark. Glass product UI
   sits on top, some of it bleeding off the card's edges.
   ========================================================================== */
.bento {
  display: grid;
  gap: var(--space-4);
  margin: 0;
  padding: 0;
  list-style: none;
}

.bento__card {
  position: relative;
  display: flex;
  flex-direction: column;
  height: 460px;
  overflow: hidden;
  border-radius: var(--radius-lg);
  background: var(--surface-card);
  box-shadow: var(--shadow-xs);
  transition: transform var(--duration-base) var(--ease-out), box-shadow var(--duration-base) var(--ease-out);
  /* Own layer, so the glows can sit behind the content (z-index -1) and the
     title link's overlay can cover the whole card */
  isolation: isolate;
}
.bento__card:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
}

/* ---------- Glows ----------
   Soft radial McLaren and coral glows behind each card's UI. They're
   multiplied, so where two collide they merge towards Ember, as the mark
   overprints. Every glow fades to transparent before the title, so white
   still shows. Internet and data has none. */
.bento__card::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-blend-mode: multiply;
  opacity: 0.3; /* soft, so the UI leads */
}

.bento__card--it::before {
  background-image:
    radial-gradient(42% 85% at 56% 112%, var(--mclaren-500), transparent),
    radial-gradient(34% 75% at 102% 48%, var(--coral-500), transparent),
    radial-gradient(28% 60% at 80% 108%, var(--coral-300), transparent);
}

.bento__card--security::before {
  background-image:
    radial-gradient(42% 62% at -4% 92%, var(--coral-500), transparent),
    radial-gradient(40% 60% at 58% 116%, var(--mclaren-500), transparent),
    radial-gradient(32% 58% at 104% 44%, var(--coral-500), transparent);
}

.bento__card--e8::before {
  background-image:
    radial-gradient(72% 52% at -6% 98%, var(--mclaren-500), transparent),
    radial-gradient(70% 48% at 104% 78%, var(--coral-500), transparent);
}

.bento__card--backup::before {
  background-image:
    radial-gradient(76% 50% at 6% 104%, var(--coral-500), transparent),
    radial-gradient(64% 44% at 100% 100%, var(--mclaren-500), transparent),
    radial-gradient(50% 30% at 100% 52%, var(--coral-300), transparent);
}

.bento__card--m365::before {
  background-image:
    radial-gradient(66% 50% at -4% 72%, var(--mclaren-500), transparent),
    radial-gradient(76% 50% at 92% 108%, var(--coral-500), transparent);
}

/* ---------- Title: name in ink, description in grey, one run of text ---------- */
.bento__text {
  max-width: 34ch;
  padding: var(--space-6) var(--space-6) 0;
  font-size: var(--text-lead);
  line-height: 1.3;
}

.bento__title,
.bento__desc {
  display: inline;
  font-size: inherit;
}

.bento__title { font-weight: var(--weight-semibold); }
.bento__desc { color: var(--neutral-400); }

/* The whole card is the link */
.bento__link {
  color: inherit;
  text-decoration: none;
}
.bento__link::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  border-radius: inherit;
}
/* The card clips its contents, so the focus ring goes on the card itself */
.bento__link:focus-visible { box-shadow: none; }
.bento__card:has(.bento__link:focus-visible) { box-shadow: var(--focus-ring); }

/* ---------- Stage: the area under the title that holds the UI ----------
   Every stage starts the same distance below its title, with its main UI
   at the top. Main UIs may bleed off the card's right and bottom edges (the
   card clips them); smaller floats overlap them for depth. */
.bento__stage {
  --bleed: var(--space-10);
  position: relative;
  flex: 1;
  min-height: 0;
  margin-top: var(--space-14);
}

/* Bleeds off the right and bottom edges; the crop favours the group on the
   right so they stay in view on phones */
.bento__photo {
  position: absolute;
  top: 0;
  left: var(--space-6);
  width: calc(100% - var(--space-6));
  height: 100%;
  border-radius: var(--radius-lg) 0 0 0;
  object-fit: cover;
  object-position: 72% center;
}

/* ---------- Glass UI card ----------
   Product UI at 12px with 11px meta, brand colours and hairline rows */
.ui {
  margin: 0;
  overflow: hidden;
  border-radius: var(--radius-lg);
  background: var(--surface-glass);
  backdrop-filter: blur(var(--blur-menu));
  box-shadow: var(--shadow-md);
  font-size: var(--text-xs);
  line-height: 1.4;
}

.ui__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-4) var(--space-3);
}

.ui__title { font-weight: var(--weight-semibold); }

.ui__meta {
  color: var(--text-secondary);
  font-size: var(--text-2xs);
  white-space: nowrap;
}

.ui__button {
  flex: none;
  padding: var(--space-1) 10px;
  white-space: nowrap;
  border-radius: var(--radius-sm);
  background: var(--action-secondary-bg);
  font-weight: var(--weight-semibold);
}

.ui .badge {
  padding: 1px 6px;
  font-size: var(--text-2xs);
}

.ui__list {
  margin: 0;
  padding: 0 var(--space-4) var(--space-2);
  list-style: none;
}

/* Rows separate with a hairline under each, none under the last */
.ui__row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--border-subtle);
}
.ui__row:last-child { border-bottom: 0; }

/* A row lifted off the list to draw the eye */
.ui__row--raised {
  margin-inline: calc(var(--space-2) * -1);
  padding-inline: var(--space-2);
  border-bottom-color: transparent;
  border-radius: var(--radius-md);
  background: var(--surface-card);
  box-shadow: var(--shadow-md);
}

.ui__name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Microsoft product icon and file extension in the SharePoint list */
.ui__app {
  flex: none;
  width: 16px;
  height: 16px;
}

.ui__ext { color: var(--text-secondary); }

.ui__figure {
  font-size: var(--text-3xl);
  font-weight: var(--weight-semibold);
  line-height: 1;
  letter-spacing: var(--tracking-tight);
}

/* Success check, drawn with CSS */
.tick {
  position: relative;
  flex: none;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--status-success-solid);
}
.tick::after {
  content: "";
  position: absolute;
  left: 5.5px;
  top: 3px;
  width: 4px;
  height: 7px;
  border: solid var(--status-on-solid);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
.tick--pending {
  background: none;
  box-shadow: inset 0 0 0 2px var(--neutral-300);
}
.tick--pending::after { display: none; }

/* Initials, or the Eightstep mark for the monitor */
.avatar {
  display: grid;
  flex: none;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--neutral-100);
  color: var(--neutral-700);
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
  line-height: 1;
}
.avatar--brand {
  background: var(--neutral-0);
  box-shadow: inset 0 0 0 1px var(--border-subtle);
}
.avatar img {
  width: 12px;
  height: auto;
}

/* Placeholder lines standing in for body text */
.skeleton {
  display: block;
  height: 6px;
  border-radius: var(--radius-full);
  background: var(--neutral-100);
}
.skeleton--short { width: 60%; }

/* ---------- Product UI: tables, stat tiles, meters and charts ----------
   Mock data only. Columns marked ui__wide show from 768px. */
.ui__table {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
}

.ui__table th {
  padding: var(--space-2) var(--space-4);
  border-bottom: 1px solid var(--border-subtle);
  color: var(--text-secondary);
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
  text-align: left;
}
.ui__table th:first-child { width: 42%; }

.ui__table td {
  padding: 10px var(--space-4);
  border-bottom: 1px solid var(--border-subtle);
  vertical-align: middle;
}
.ui__table tr:last-child td { border-bottom: 0; }

/* Narrow screens: tighter columns, still lined up with the head */
@media (max-width: 767px) {
  .ui__table th,
  .ui__table td { padding-inline: var(--space-2); }
  .ui__table :is(th, td):first-child { padding-left: var(--space-4); }
  .ui__table :is(th, td):last-child { padding-right: var(--space-4); }
  .ui__table th:first-child { width: 36%; }
}

.ui__table .ui__name { display: block; }

/* Long names truncate inside their cell rather than spilling into the next */
.ui__table td { overflow: hidden; }
.ui__table .ui__status { display: flex; max-width: 100%; }
.ui__table .ui__status .ui__name { flex: 1; min-width: 0; }

.ui__wide { display: none; }

/* A second line under a name: who, where or when */
.ui__sub {
  display: block;
  overflow: hidden;
  color: var(--text-secondary);
  font-size: var(--text-2xs);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ui__status {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}

.ui__stats {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-2);
  margin: 0;
  padding: 0 var(--space-4) var(--space-3);
}

.ui__stats > div {
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
  background: var(--surface-sunken);
}

.ui__stats dt {
  color: var(--text-secondary);
  font-size: var(--text-2xs);
}

.ui__stats dd {
  margin: 0;
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
}

/* A progress meter: --value on the meter sets how full it is */
.ui__meter {
  display: block;
  max-width: 160px;
  height: 6px;
  margin-bottom: var(--space-1);
  overflow: hidden;
  border-radius: var(--radius-full);
  background: var(--neutral-100);
}

.ui__meter > span {
  display: block;
  width: var(--value);
  height: 100%;
  border-radius: inherit;
  background: var(--status-success-solid);
}

/* An app icon beside a name and a second line */
.ui__item {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}
.ui__item > span { min-width: 0; }

.ui__app--lg {
  width: 24px;
  height: 24px;
}

/* A pair of buttons in a head; --ink is the one that goes ahead */
.ui__actions {
  display: flex;
  flex: none;
  gap: 6px;
}

.ui__button--ink {
  background: var(--neutral-950);
  color: var(--neutral-0);
}

/* An app named by its initials, on a rounded square */
.avatar--square {
  width: 32px;
  height: 32px;
  border-radius: var(--radius-sm);
}

/* An app's own icon on the square */
.avatar--square img { width: 20px; }

/* ---------- A held email, taken apart ----------
   The message as its reader would see it, with numbered pins on its tells,
   and beside it (below, on phones) what each pin means */
.held {
  display: grid;
  gap: var(--space-6);
  padding: var(--space-1) var(--space-4) var(--space-4);
}

.message {
  display: grid;
  align-content: start;
  gap: var(--space-2);
  min-width: 0;
}

.message__from {
  display: flex;
  align-items: center;
  gap: 10px;
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--border-subtle);
}

.message__sender { min-width: 0; }
.message__sender .ui__name { display: block; }

.message__address,
.message__subject {
  display: flex;
  align-items: center;
  gap: 6px;
}

.message__address {
  color: var(--text-secondary);
  font-size: var(--text-2xs);
  white-space: nowrap;
}

.message__subject {
  margin: var(--space-2) 0 var(--space-1);
  font-size: var(--text-md);
  font-weight: var(--weight-semibold);
}

/* Body text stands in from 768px; phones go straight to the link and file */
.message .skeleton { display: none; }

.message__parts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-2);
}

/* The email's own button and attachment */
.message__link,
.message__file {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 6px 10px;
  border-radius: var(--radius-sm);
}

.message__link {
  background: var(--action-secondary-bg);
  font-weight: var(--weight-semibold);
  text-decoration: underline;
}

.message__file { background: var(--surface-sunken); }

.message__type {
  padding: 1px var(--space-1);
  border-radius: var(--radius-xs);
  background: var(--neutral-200);
  color: var(--neutral-700);
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
}

/* A numbered pin, tying a tell in the message to what it means */
.pin {
  display: inline-grid;
  flex: none;
  place-items: center;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--neutral-950);
  color: var(--neutral-0);
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
  line-height: 1;
}

.tells__list {
  display: grid;
  gap: var(--space-3);
  margin: var(--space-3) 0 0;
  padding: 0;
  list-style: none;
}

.tells__item {
  display: flex;
  align-items: flex-start;
  gap: 10px;
}
.tells__item .pin { margin-top: 1px; }

@media (min-width: 768px) {
  .held {
    grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
    gap: var(--space-10);
  }

  .message .skeleton { display: block; }
}

/* ---------- On ink: a console in dark mode ----------
   data-theme="dark" swaps the semantic colours (see tokens.css); this sets
   the surface, and the pieces drawn in fixed neutrals */
.ui--ink {
  background: var(--surface-inverse);
  color: var(--text-primary);
}

.ui--ink .avatar {
  background: var(--neutral-700);
  color: var(--neutral-200);
}

/* ---------- A process tree: how an attack branched ----------
   Nested lists, each node joined to its children by lines. Stacked by
   default, with a straight run indented only where it branches; from
   1200px it runs left to right, as a storyline. */
.tree {
  --tree-line: var(--neutral-700);
  margin: 0;
  padding: var(--space-1) var(--space-4) var(--space-4);
}

.tree,
.tree ul {
  list-style: none;
}

.tree ul {
  margin: 0;
  padding: 0;
}

.tree li { position: relative; }

.tree__node {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  height: 48px;
  padding: 0 var(--space-3) 0 var(--space-2);
  border-radius: var(--radius-md);
  background: var(--neutral-800);
}

.tree__text {
  flex: 1;
  min-width: 0;
}
.tree__text .ui__name { display: block; }

/* The program that did the harm */
.tree__node--threat { background: var(--status-danger-bg); }
.tree__node--threat .ui__sub { color: var(--status-danger-fg); }
.tree__node--threat .avatar {
  background: color-mix(in srgb, var(--status-danger-fg) 18%, transparent);
  color: var(--status-danger-fg);
}

.tree ul > li::before,
.tree ul > li::after {
  content: "";
  position: absolute;
  background: var(--tree-line);
}

/* Stacked: a line down from under the parent's tile, across to each child */
@media (max-width: 1199px) {
  .tree ul { padding-left: 40px; }
  .tree ul > li { padding-top: var(--space-2); }

  .tree ul > li::before {
    top: 0;
    bottom: 0;
    left: -17px;
    width: 2px;
  }
  .tree ul > li:last-child::before {
    bottom: auto;
    height: calc(var(--space-2) + 24px);
  }

  .tree ul > li::after {
    top: calc(var(--space-2) + 23px);
    left: -17px;
    width: 17px;
    height: 2px;
  }

  /* A single child sits straight under its parent */
  .tree ul:has(> li:only-child) { padding-left: 0; }
  .tree ul:has(> li:only-child) > li::before {
    left: 23px;
    height: var(--space-2);
  }
  .tree ul:has(> li:only-child) > li::after { display: none; }
}

/* Side by side: each list is a column, joined by a stub out of the parent
   and a spine down the children */
@media (min-width: 1200px) {
  .tree li {
    display: flex;
    align-items: center;
  }

  .tree ul {
    position: relative;
    display: flex;
    flex: 1;
    flex-direction: column;
    min-width: 0;
    padding-left: var(--space-12);
  }

  .tree ul > li { padding-block: 6px; }
  .tree ul > li:only-child { padding-block: 0; }

  .tree__node { flex: none; }
  .tree__node:only-child {
    flex: 1;
    max-width: 320px;
  }

  .tree li > ul::before {
    content: "";
    position: absolute;
    top: 50%;
    left: 0;
    width: var(--space-6);
    height: 2px;
    margin-top: -1px;
    background: var(--tree-line);
  }

  .tree ul > li::before {
    top: 0;
    bottom: 0;
    left: calc(var(--space-6) * -1);
    width: 2px;
  }
  .tree ul > li:first-child::before { top: 50%; }
  .tree ul > li:last-child::before { bottom: 50%; }
  .tree ul > li:only-child::before { display: none; }

  .tree ul > li::after {
    top: 50%;
    left: calc(var(--space-6) * -1);
    width: var(--space-6);
    height: 2px;
    margin-top: -1px;
  }
}

/* ---------- Steps along a line, such as a threat's response ----------
   From 768px; phones keep to the tree */
.steps {
  display: none;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: var(--space-2);
  margin: 0 var(--space-4);
  padding: var(--space-4) 0;
  border-top: 1px solid var(--border-subtle);
  list-style: none;
}

.steps__item {
  position: relative;
  display: grid;
  gap: 6px;
}

/* The line runs from each tick to just short of the next */
.steps__item:not(:last-child)::after {
  content: "";
  position: absolute;
  top: 7px;
  left: 20px;
  right: -4px;
  height: 2px;
  border-radius: 1px;
  background: var(--neutral-700);
}

@media (min-width: 768px) {
  .steps { display: grid; }
}

/* ---------- A computer's screen, with a system prompt ----------
   What someone sees when software that isn't approved tries to run: a
   dialog, centred on their screen */
.desk {
  display: flex;
  flex-direction: column;
}

.desk__bar {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: 10px var(--space-4);
}

.desk__screen {
  flex: 1;
  margin: 0 var(--space-2);
  padding: var(--space-4) var(--space-3);
  border-radius: var(--radius-md) var(--radius-md) 0 0;
  background: var(--neutral-100);
}

.prompt {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-4);
  max-width: 400px;
  margin-inline: auto;
  padding: var(--space-5);
  border-radius: var(--radius-xl);
  background: var(--surface-card);
  box-shadow: var(--shadow-lg);
}

.prompt__head {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
}
.prompt__head > div { min-width: 0; }

.prompt__icon {
  flex: none;
  width: 32px;
  height: 32px;
}

.prompt__title {
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
}

.prompt__field {
  display: grid;
  gap: 6px;
}

/* A text field, bordered as form fields are */
.prompt__input {
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--neutral-300);
  border-radius: var(--radius-md);
}

.prompt__actions { justify-content: flex-end; }

@media (min-width: 768px) {
  .desk__screen { padding-block: var(--space-8); }
}

/* ---------- A lesson: progress, a question, choices and feedback ---------- */
.lesson__progress {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-1);
  margin: 0 var(--space-4) var(--space-5);
  padding: 0;
  list-style: none;
}

.lesson__step {
  height: 4px;
  border-radius: var(--radius-full);
  background: var(--neutral-100);
}
.lesson__step--done { background: var(--neutral-950); }
.lesson__step--on { background: var(--neutral-400); }

.lesson__question {
  margin: 0 var(--space-4) var(--space-4);
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  line-height: 1.3;
  letter-spacing: var(--tracking-tight);
}

.lesson__choices {
  display: grid;
  gap: var(--space-2);
  margin: 0;
  padding: 0 var(--space-4) var(--space-4);
  list-style: none;
}

/* Each choice is a radio, bordered as form controls are; --on is chosen */
.choice {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: var(--space-3);
  border: 1px solid var(--neutral-300);
  border-radius: var(--radius-md);
  background: var(--surface-card);
}
.choice--on {
  border-color: var(--neutral-950);
  box-shadow: inset 0 0 0 1px var(--neutral-950);
}

.choice__mark {
  position: relative;
  flex: none;
  width: 16px;
  height: 16px;
  margin-top: 1px;
  border-radius: 50%;
  box-shadow: inset 0 0 0 1.5px var(--neutral-300);
}
.choice--on .choice__mark {
  background: var(--neutral-950);
  box-shadow: none;
}
.choice--on .choice__mark::after {
  content: "";
  position: absolute;
  inset: 5px;
  border-radius: 50%;
  background: var(--neutral-0);
}

.choice__text { min-width: 0; }
.choice__text .ui__name { display: block; }

/* The part of a fake address that gives it away */
.choice mark {
  padding: 0 1px;
  border-radius: 2px;
  background: var(--status-danger-bg);
  color: var(--status-danger-fg);
}

.lesson__feedback {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin: 0 var(--space-4) var(--space-4);
  padding: var(--space-3) var(--space-3) var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  background: var(--surface-sunken);
}
.lesson__feedback .ui__name { white-space: normal; }

@media (min-width: 1024px) {
  .lesson__choices { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* ---------- A restore picker: a moment, the items, where they go ----------
   Mock UI for restore flows, laid out as choices rather than a table */
.restore__when { padding: 0 var(--space-4) var(--space-4); }

/* Restore points along a line; --on is the one chosen */
.restore__line {
  position: relative;
  display: flex;
  justify-content: space-between;
  margin: var(--space-3) 0 var(--space-6);
  padding: 0;
  list-style: none;
}
.restore__line::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  height: 2px;
  border-radius: 1px;
  background: var(--neutral-200);
}

.restore__point {
  position: relative;
  width: 10px;
  height: 10px;
  border: 2px solid var(--neutral-300);
  border-radius: 50%;
  background: var(--surface-card);
}
.restore__point span {
  position: absolute;
  top: calc(100% + 6px);
  left: 50%;
  color: var(--text-secondary);
  font-size: var(--text-2xs);
  white-space: nowrap;
  transform: translateX(-50%);
}
.restore__point:first-child span { left: 0; transform: none; }
.restore__point:last-child span { right: 0; left: auto; transform: none; }
.restore__point--on {
  border-color: var(--neutral-950);
  background: var(--neutral-950);
  box-shadow: 0 0 0 4px var(--neutral-200);
}
.restore__point--on span {
  color: var(--text-primary);
  font-weight: var(--weight-semibold);
}

/* Items as tiles; --on is ticked for restore */
.restore__tiles {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-2);
  margin: 0;
  padding: 0 var(--space-4) var(--space-4);
  list-style: none;
}

.restore__tile {
  position: relative;
  display: grid;
  gap: 2px;
  padding: var(--space-3);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  background: var(--surface-card);
}
.restore__tile--on {
  border-color: var(--neutral-950);
  box-shadow: inset 0 0 0 1px var(--neutral-950);
}
.restore__tile .ui__name { display: block; }

.restore__icon {
  width: 32px;
  height: 32px;
  margin-bottom: var(--space-2);
}

.restore__check {
  position: absolute;
  top: var(--space-3);
  right: var(--space-3);
  width: 16px;
  height: 16px;
  border-radius: var(--radius-xs);
  box-shadow: inset 0 0 0 1.5px var(--neutral-300);
}
.restore__tile--on .restore__check {
  background: var(--neutral-950);
  box-shadow: none;
}
.restore__tile--on .restore__check::after {
  content: "";
  position: absolute;
  left: 5.5px;
  top: 2.5px;
  width: 4px;
  height: 8px;
  border: solid var(--neutral-0);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

/* Where to restore to, as a two-way choice */
.restore__where {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4) var(--space-4);
  border-top: 1px solid var(--border-subtle);
}
.restore__where .ui__meta { margin-right: var(--space-2); }

.restore__choice {
  padding: var(--space-1) 10px;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-full);
  color: var(--text-secondary);
}
.restore__choice--on {
  border-color: var(--neutral-950);
  background: var(--neutral-950);
  color: var(--neutral-0);
}

@media (min-width: 768px) {
  .restore__tiles { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* A chart beside a list */
.ui__split {
  display: grid;
  gap: var(--space-4);
  padding: 0 var(--space-4) var(--space-4);
}

.ui__split .ui__list { padding: 0; }

/* Columns shrink to fit, so long names truncate instead of widening them */
.ui__split > * { min-width: 0; }

/* A chart in a split, on a sunken panel */
.ui__chart {
  padding: var(--space-3) var(--space-4) var(--space-4);
  border-radius: var(--radius-md);
  background: var(--surface-sunken);
}

.ui__legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-4);
  margin: 0 0 var(--space-4);
  padding: 0;
  color: var(--text-secondary);
  font-size: var(--text-2xs);
  list-style: none;
}

.ui__legend li {
  display: flex;
  align-items: center;
  gap: 6px;
}

.ui__key {
  width: 8px;
  height: 8px;
  border-radius: 2px;
}

/* Stacked bars: each part's --value is its share of the bar's height (mock data) */
.ui__bars {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-3);
  height: 200px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.ui__bar {
  display: flex;
  flex-direction: column;
  gap: 6px;
  color: var(--text-secondary);
  font-size: var(--text-2xs);
  text-align: center;
}

.ui__bar-stack {
  display: flex;
  flex: 1;
  flex-direction: column;
  justify-content: flex-end;
  width: 100%;
  max-width: 48px;
  margin-inline: auto;
  overflow: hidden;
  border-radius: var(--radius-xs) var(--radius-xs) 0 0;
}

.ui__bar-part {
  display: block;
  flex: none;
  height: var(--value);
}

.ui__key--operational,
.ui__bar-part--operational { background: var(--neutral-300); }
.ui__key--warranty,
.ui__bar-part--warranty { background: var(--neutral-600); }
.ui__key--capital,
.ui__bar-part--capital { background: var(--neutral-950); }

@media (min-width: 768px) {
  .ui__wide { display: table-cell; }
  .ui__stats { grid-template-columns: repeat(4, 1fr); }

  .ui__split {
    grid-template-columns: 1fr 1fr;
    align-items: start;
  }
}

/* ---------- Floats ----------
   Smaller UI overlapping a larger visual: solid, so nothing shows through,
   with a deeper shadow, each drifting gently on its own rhythm. Any block
   can use them; the visual it floats over needs position: relative. */
.float {
  position: absolute;
  z-index: 1;
  max-width: calc(100% - var(--space-6));
  background: var(--surface-card);
  box-shadow: var(--shadow-lg);
  animation: drift 6s var(--ease-in-out) infinite;
}

@keyframes drift {
  50% { transform: translateY(-6px); }
}

@media (prefers-reduced-motion: reduce) {
  .float { animation: none; }
}

/* A one-line notification: tick or avatar, then title and meta */
.note {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px var(--space-4) 10px 10px;
  white-space: nowrap;
}

/* Text-only note */
.note--latency {
  padding: var(--space-2) var(--space-3);
  font-weight: var(--weight-semibold);
}

/* An approval, with the limits that come with it (from 1200px), indented
   to the title */
.approval {
  width: 240px;
  padding: var(--space-3) var(--space-4) var(--space-4) var(--space-3);
}

.approval__head {
  display: flex;
  align-items: center;
  gap: 10px;
}

.approval__list {
  display: none;
  gap: var(--space-1);
  margin: var(--space-3) 0 0;
  padding: var(--space-3) 0 0 26px;
  border-top: 1px solid var(--border-subtle);
  color: var(--text-secondary);
  list-style: none;
}

@media (min-width: 1200px) {
  .approval__list { display: grid; }
}

/* A benchmark: the latest figure, over a small bar chart (from 1024px)
   with the latest in ink */
.bench {
  width: 228px;
  padding: var(--space-3) var(--space-4) var(--space-4);
}

.bench__head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.bench__figure {
  font-size: var(--text-3xl);
  font-weight: var(--weight-semibold);
  line-height: 1;
  letter-spacing: var(--tracking-tight);
}

.bench__bars {
  display: none;
  grid-template-columns: repeat(4, 1fr);
  align-items: end;
  gap: 6px;
  height: 32px;
  margin: var(--space-3) 0 0;
  padding: 0;
  list-style: none;
}

.bench__bars li {
  height: var(--value);
  border-radius: var(--radius-xs) var(--radius-xs) 0 0;
  background: var(--neutral-300);
}
.bench__bars li:last-child { background: var(--neutral-950); }

@media (min-width: 1024px) {
  .bench__bars { display: grid; }
}

/* ---------- Managed IT: ticket note over the photo's left edge ---------- */
.note--ticket {
  left: var(--space-3);
  bottom: var(--space-6);
}

/* ---------- Cyber security ----------
   Phones: the stat card bleeds off the right and bottom, an alert overlaps it.
   From 640px: the stat card bleeds off the bottom, and a quarantined email
   and the alert overlap its right edge, over its padding so the chart stays
   clear. The stat card narrows so the email always fits. */
.threats {
  position: absolute;
  top: 0;
  right: calc(var(--bleed) * -1);
  bottom: calc(var(--bleed) * -1);
  left: var(--space-6);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-5) calc(var(--bleed) + var(--space-5)) calc(var(--bleed) + var(--space-5)) var(--space-5);
}

.threats__figure {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

/* Seven-day bar chart: heights are mock data, today is ink.
   It grows to fill whatever height the stat card has spare. */
.chart {
  display: grid;
  flex: 1;
  grid-template-columns: repeat(7, 1fr);
  gap: var(--space-2);
  min-height: 80px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.chart__day {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 6px;
  color: var(--text-secondary);
  font-size: var(--text-2xs);
  text-align: center;
}

.chart__bar {
  display: block;
  border-radius: var(--radius-xs) var(--radius-xs) 0 0;
  background: var(--neutral-200);
}
.chart__day:nth-child(1) .chart__bar { height: 45%; }
.chart__day:nth-child(2) .chart__bar { height: 62%; }
.chart__day:nth-child(3) .chart__bar { height: 38%; }
.chart__day:nth-child(4) .chart__bar { height: 74%; }
.chart__day:nth-child(5) .chart__bar { height: 58%; }
.chart__day:nth-child(6) .chart__bar { height: 30%; }
.chart__day:nth-child(7) .chart__bar { height: 82%; background: var(--neutral-950); }

/* Where the week's threats came from (from 640px; phones keep the card simple) */
.split {
  display: none;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-2);
  margin: 0;
  padding-block: var(--space-3);
  border-block: 1px solid var(--border-subtle);
}

.split dt {
  color: var(--text-secondary);
  font-size: var(--text-2xs);
}

.split dd {
  margin: 0;
  font-weight: var(--weight-semibold);
}

/* Email preview: sender, subject, placeholder body, verdict */
.mail {
  display: none;
  gap: var(--space-2);
  width: 280px;
  padding: 14px var(--space-4);
  animation-duration: 7s;
}

.mail__head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: var(--space-1);
}

.mail__subject { font-weight: var(--weight-semibold); }

.mail__verdict {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-1);
  padding-top: 10px;
  border-top: 1px solid var(--border-subtle);
  color: var(--text-secondary);
}

.note--isolated {
  left: var(--space-3);
  bottom: var(--space-6);
  animation-duration: 8s;
  animation-delay: -3s;
}

@media (min-width: 640px) {
  .bento__stage--security {
    --main: min(440px, 100% - 308px);
    --overlap: calc(var(--space-6) + var(--main) - var(--space-5));
  }

  .threats {
    right: auto;
    width: var(--main);
    padding-right: var(--space-5);
  }

  .split { display: grid; }

  .mail {
    display: grid;
    top: var(--space-6);
    left: var(--overlap);
  }

  .note--isolated {
    left: var(--overlap);
    bottom: var(--space-8);
  }
}

/* ---------- Essential 8: compliance report ----------
   Bleeds off the right and bottom; the content keeps clear of the right edge */
.report {
  position: absolute;
  top: 0;
  right: calc(var(--bleed) * -1);
  bottom: calc(var(--bleed) * -1);
  left: var(--space-6);
  padding-right: var(--bleed);
}

.report__summary {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  margin: 0 var(--space-4);
  padding: var(--space-1) 0 var(--space-4);
  border-bottom: 1px solid var(--border-subtle);
}

.report__score {
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  line-height: 1.2;
}

/* Maturity ring: one arc per strategy, the pending one in neutral */
.ring {
  flex: none;
  width: 64px;
  height: 64px;
}

.ring__arc {
  fill: none;
  stroke: var(--status-success-solid);
  stroke-width: 9;
}
.ring__arc--pending { stroke: var(--neutral-200); }

/* ---------- Backup: monitor and engineer in a chat channel ----------
   Bleeds off the bottom, so the thread reads as ongoing */
.chat {
  position: absolute;
  top: 0;
  right: var(--space-6);
  bottom: calc(var(--bleed) * -1);
  left: var(--space-6);
}

.chat .ui__head { border-bottom: 1px solid var(--border-subtle); }

.chat__list {
  display: grid;
  gap: var(--space-4);
  margin: 0;
  padding: var(--space-4);
  list-style: none;
}

.chat__msg {
  display: grid;
  grid-template-columns: 24px 1fr;
  column-gap: 10px;
}

.chat__who { font-weight: var(--weight-semibold); }
.chat__who .ui__meta {
  margin-left: var(--space-1);
  font-weight: var(--weight-regular);
}

.chat__text {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  margin-top: 2px;
}

/* ---------- Microsoft 365: SharePoint in a browser window ----------
   Bleeds off the right and bottom; a restore toast floats over the list */
.browser {
  position: absolute;
  top: 0;
  right: calc(var(--bleed) * -1);
  bottom: calc(var(--bleed) * -1);
  left: var(--space-6);
  padding-right: var(--bleed);
}

.browser__bar {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: 10px var(--space-4);
  border-bottom: 1px solid var(--border-subtle);
}

/* Three window controls from one repeated dot */
.browser__dots {
  flex: none;
  width: 40px;
  height: 8px;
  background: radial-gradient(circle, var(--neutral-300) 3.5px, transparent 4px) 0 0 / 14px 8px repeat-x;
}

.browser__url {
  flex: 1;
  min-width: 0;
  max-width: 280px;
  padding: 3px 10px;
  overflow: hidden;
  border-radius: var(--radius-full);
  background: var(--surface-sunken);
  color: var(--text-secondary);
  font-size: var(--text-2xs);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.note--restored {
  right: var(--space-6);
  bottom: var(--space-6);
  animation-delay: -4s;
}

/* ---------- Map: Australia in dots, gradient-filled, with pulses between cities ---------- */
.bento__stage--map {
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 0 var(--space-6) var(--space-6);
}

.map {
  width: 100%;
  height: auto;
  max-height: 100%;
}

.map-stop--mclaren { stop-color: var(--mclaren-500); }
.map-stop--coral { stop-color: var(--coral-500); }

/* On a page, the dots take the warm neutrals: McLaren and coral are for
   calls to action and the bento glows only */
.map-stop--near { stop-color: var(--neutral-500); }
.map-stop--far { stop-color: var(--neutral-300); }

.map__land {
  fill: none;
  stroke: url(#map-dots);
  stroke-width: 3.4;
  stroke-linecap: round;
}

.map__routes path {
  fill: none;
  stroke: var(--neutral-950);
  stroke-opacity: .3;
  stroke-width: 1;
}

/* One short dash per route; the gap is longer than the route, so each pulse rests before the next */
.map__pulses path {
  fill: none;
  stroke: var(--neutral-950);
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-dasharray: 12 188;
  stroke-dashoffset: 200;
  animation: route-pulse 4s var(--ease-in-out) infinite;
}
.map__pulses path:nth-child(2) { animation-delay: -.5s; }
.map__pulses path:nth-child(3) { animation-delay: -1s; }
.map__pulses path:nth-child(4) { animation-delay: -1.5s; }
.map__pulses path:nth-child(5) { animation-delay: -2s; }
.map__pulses path:nth-child(6) { animation-delay: -2.5s; }
.map__pulses path:nth-child(7) { animation-delay: -3s; }
.map__pulses path:nth-child(8) { animation-delay: -3.5s; }

@keyframes route-pulse {
  to { stroke-dashoffset: 0; }
}

.map__cities circle {
  fill: var(--neutral-950);
  stroke: var(--neutral-0);
  stroke-width: 1.5;
}

@media (prefers-reduced-motion: reduce) {
  .map__pulses { display: none; }
}

.note--latency {
  top: 0;
  right: var(--space-6);
}

.ui--chip {
  position: absolute;
  left: var(--space-6);
  bottom: var(--space-6);
  display: inline-flex;
  flex: none;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  font-weight: var(--weight-semibold);
}

/* ---------- Layout ---------- */
@media (min-width: 640px) {
  .bento { grid-template-columns: repeat(2, 1fr); }
  .bento__card--anchor,
  .bento__card--wide { grid-column: 1 / -1; }
}

@media (min-width: 1024px) {
  .bento { grid-template-columns: repeat(3, 1fr); }
  .bento__card { height: 480px; }
  .bento__card--wide { grid-column: span 2; }

  /* The anchor runs full width: text on the left, photo on the right */
  .bento__card--anchor {
    display: grid;
    grid-template-columns: 5fr 7fr;
    height: 420px;
  }

  /* Side by side, the photo starts level with the title instead of below it,
     and the ticket note overlaps the photo's left edge */
  .bento__card--anchor .bento__stage { margin-top: 0; }
  .bento__card--anchor .bento__photo {
    top: var(--space-6);
    height: calc(100% - var(--space-6));
  }
  .note--ticket {
    left: 0;
    bottom: var(--space-8);
  }
}

/* ==========================================================================
   Proof
   A centred headline, four numbers and, optionally, an infinity loop in
   fine lines. The first number is highlighted; hovering another moves the
   highlight there. Bottom padding: pb-100 with the loop (its canvas adds
   its own space below), pb-150 without.
   ========================================================================== */
.proof__intro {
  display: grid;
  justify-items: center;
  gap: var(--space-4);
  margin-bottom: var(--space-16);
  text-align: center;
}

.proof__title { max-width: 18ch; }

.proof__lead {
  max-width: 44ch;
  font-size: var(--text-lead);
}

/* Equal columns that a long number can't stretch */
.proof__stats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  margin: 0;
  padding: 0;
  list-style: none;
}

.proof__stat {
  position: relative;
  display: grid;
  align-content: start;
  gap: var(--space-3);
  padding: var(--space-8) var(--space-3);
  color: var(--text-secondary);
  text-align: center;
  transition: color var(--duration-base) var(--ease-out);
}

/* Hairlines above and below, fading at both ends, in the stat's own colour */
.proof__stat::before,
.proof__stat::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, currentColor, transparent);
  opacity: .3;
  transition: opacity var(--duration-base) var(--ease-out);
}
.proof__stat::before { top: 0; }
.proof__stat::after { bottom: 0; }

/* Two rows on smaller screens share one line between them */
.proof__stat:nth-child(n + 3)::before { display: none; }

.proof__stat:first-child,
.proof__stat:hover { color: var(--text-primary); }
.proof__stat:first-child::before,
.proof__stat:first-child::after,
.proof__stat:hover::before,
.proof__stat:hover::after { opacity: 1; }

.proof__stats:hover .proof__stat:not(:hover) { color: var(--text-secondary); }
.proof__stats:hover .proof__stat:not(:hover)::before,
.proof__stats:hover .proof__stat:not(:hover)::after { opacity: .3; }

.proof__number {
  font-size: var(--text-stat);
  font-weight: var(--weight-light);
  line-height: 1;
  letter-spacing: var(--tracking-tight);
}

.proof__caption {
  max-width: 28ch;
  margin-inline: auto;
  font-size: var(--text-sm);
}

.proof__source {
  margin-top: var(--space-6);
  color: var(--text-secondary);
  font-size: var(--text-xs);
  text-align: center;
}

/* Lines are drawn by main.js; the glow behind them is CSS */
.proof__loop {
  display: block;
  width: 100%;
  height: clamp(240px, 30vw, 420px);
  margin-top: var(--space-10);
  background: radial-gradient(42% 46% at 50% 50%, var(--loop-glow), transparent);
}

@media (min-width: 1024px) {
  .proof__stats { grid-template-columns: repeat(4, 1fr); }
  .proof__stat:nth-child(n + 3)::before { display: block; }
  .proof__caption { font-size: var(--text-md); }
}

/* ==========================================================================
   Stories
   Customer stories as a vertical accordion: a stack of rows, each showing
   the client's logo and a one-line teaser. One story is open below its
   row: the quote, then a wide photo. Opening another
   closes it. main.js adds stories--ready and the open class; without the
   script every story shows open. A single story is simply shown open.
   ========================================================================== */
.stories__list {
  display: grid;
  gap: var(--space-3);
}

.story {
  overflow: hidden;
  border-radius: var(--radius-xl);
  background: var(--surface-card);
  box-shadow: var(--shadow-xs);
}

/* ---------- Row: logo, a one-line teaser, and an open/close icon ---------- */
.story__head {
  margin: 0;
  font-size: inherit;
  font-weight: inherit;
}

.story__toggle {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: var(--space-4) var(--space-6);
  width: 100%;
  padding: var(--space-5) var(--space-6);
  border: 0;
  border-radius: inherit;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: background-color var(--duration-fast) var(--ease-out);
}
.stories--ready .story:not(.story--open) .story__toggle:hover { background: var(--surface-hover); }
.story__toggle:disabled { cursor: default; }

/* The card clips its contents, so the focus ring goes on the card */
.story__toggle:focus-visible { box-shadow: none; }
.story:has(.story__toggle:focus-visible) { box-shadow: var(--focus-ring); }

/* Each logo's width and height attributes set its optically balanced size */
.story__logo {
  grid-column: 1;
  max-width: 100%;
  height: auto;
}

.story__teaser {
  grid-column: 1;
  font-weight: var(--weight-semibold);
}

/* The shared icon button, holding a plus whose upright turns flat as the
   story opens. It sits inside the row's button, so the row drives its hover. */
.story__icon {
  grid-column: 2;
  grid-row: 1 / span 2;
}
.stories--ready .story:not(.story--open) .story__toggle:hover .story__icon { background: var(--action-secondary-bg-hover); }


/* No icon when there's nothing to open, before main.js runs or with one story */
.story__toggle:disabled .story__icon,
.stories:not(.stories--ready) .story__icon { display: none; }

/* ---------- Panel: the quote, then a wide photo ---------- */
.story__panel {
  display: grid;
  grid-template-rows: 1fr;
}

.story__inner {
  min-height: 0;
  overflow: hidden;
}

/* Once main.js runs, closed panels fold to nothing and hide from assistive tech */
.stories--ready .story__panel {
  transition: grid-template-rows var(--duration-slow) var(--ease-out);
}
.stories--ready .story:not(.story--open) .story__panel { grid-template-rows: 0fr; }
.stories--ready .story:not(.story--open) .story__inner {
  visibility: hidden;
  transition: visibility 0s linear var(--duration-slow);
}

/* Set while main.js first folds them */
.stories--settling .story__panel,
.stories--settling .story:not(.story--open) .story__inner,
.stories--settling .icon-plus__upright { transition: none; }

.story__figure {
  display: grid;
  gap: var(--space-5);
  margin: 0;
  padding: var(--space-2) var(--space-6) var(--space-8);
}

/* Quote marks come from CSS, so the text from the CMS stays plain.
   The opening mark hangs into the margin. Shared with the Testimonial block. */
.story__quote,
.testimonial__quote {
  margin: 0;
  color: var(--neutral-500);
  font-size: clamp(1.25rem, 0.95rem + 1vw, 1.75rem);
  line-height: 1.25;
  letter-spacing: var(--tracking-tight);
  quotes: "\201C" "\201D";
  text-wrap: pretty;
}
:is(.story__quote, .testimonial__quote) p { text-indent: -0.42em; }
:is(.story__quote, .testimonial__quote) p::before { content: open-quote; }
:is(.story__quote, .testimonial__quote) p::after { content: close-quote; }


.story__media {
  position: relative;
  margin: 0 var(--space-3) var(--space-3);
  overflow: hidden;
  border-radius: var(--radius-lg);
  aspect-ratio: 4 / 3;
}

.story__image {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

@media (min-width: 640px) {
  /* Logo and teaser share one line */
  .story__toggle {
    grid-template-columns: 200px 1fr auto;
    padding: var(--space-6) var(--space-8);
  }
  .story__teaser { grid-column: 2; }
  .story__icon { grid-column: 3; grid-row: 1; }

  .story__figure { padding: var(--space-2) var(--space-8) var(--space-10); }
  .story__media { aspect-ratio: 16 / 9; }
}

@media (min-width: 1024px) {
  /* The quote lines up with the teaser above */
  .story__figure { padding-left: calc(var(--space-8) + 200px + var(--space-6)); }
  .story__media { aspect-ratio: 3 / 1; }
}

/* ==========================================================================
   Testimonial
   One customer's quote in a slim card, for placing between other blocks: a
   photo on the left, the quote beside it and the client's logo under the
   quote. It has no heading, so its section carries an aria-label. Stacks on
   phones, with the photo on top.
   ========================================================================== */
.testimonial__card {
  display: grid;
  gap: var(--space-3);
  margin: 0;
  padding: var(--space-3);
  overflow: hidden;
  border-radius: var(--radius-xl);
  background: var(--surface-card);
  box-shadow: var(--shadow-xs);
}

/* --focus on the img sets the crop's focal point */
.testimonial__media {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius-lg);
  aspect-ratio: 16 / 9;
}

.testimonial__image {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--focus, 50% 50%);
}

.testimonial__body {
  display: grid;
  align-content: center;
  gap: var(--space-6);
  padding: var(--space-5) var(--space-3) var(--space-4);
}

/* The logo's width and height attributes set its optically balanced size */
.testimonial__logo {
  max-width: 100%;
  height: auto;
}

@media (min-width: 768px) {
  .testimonial__card {
    /* The photo takes about a third of the card */
    grid-template-columns: minmax(0, 8fr) minmax(0, 17fr);
    gap: 0;
  }

  .testimonial__media {
    align-self: center;
    aspect-ratio: 4 / 3;
  }

  .testimonial__body {
    gap: var(--space-8);
    padding: var(--space-8) var(--space-10);
  }
}

@media (min-width: 1024px) {
  .testimonial__body { padding: var(--space-10) var(--space-14); }
}

/* ==========================================================================
   News
   The latest blog posts as a graphical accordion. One post is open: its
   artwork fills most of the row and its text shows below. The rest wait to
   the right in narrowing slivers. The row loops: a post you move past folds
   away to the left, then rejoins at the end, so it never runs out. Widths
   come from each panel's data-offset (its place after the open post) and
   order, which main.js sets; the HTML starts with the first post open.
   ========================================================================== */
.news__head {
  display: grid;
  gap: var(--space-6);
  margin-bottom: var(--space-10);
}

/* Heading in ink, a second line in grey at the same size */
.news__lead {
  color: var(--neutral-400);
  font-size: var(--text-title);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
}

.news__controls {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.news__all {
  margin-right: var(--space-4);
  color: inherit;
  font-weight: var(--weight-semibold);
  text-decoration: none;
}
.news__all:hover { text-decoration: underline; }

/* ---------- Panels ---------- */
.news__panels {
  display: flex;
  height: clamp(240px, 32vw, 440px);
  touch-action: pan-y;
}

/* Margins rather than gap, so folded panels leave no space behind. Each
   panel's margin is on its left, so whichever comes last ends flush. */
.news__panel {
  position: relative;
  flex: 0 0 var(--space-2);
  min-width: 0;
  margin-left: var(--space-2);
  overflow: hidden;
  border-radius: var(--radius-lg);
  background: var(--surface-inverse);
  transition:
    flex var(--duration-slow) var(--ease-out),
    margin var(--duration-slow) var(--ease-out),
    opacity var(--duration-slow) var(--ease-out);
}

.news__panel[data-offset="0"] { flex: 1 1 0; margin-left: 0; }
.news__panel[data-offset="1"] { flex-basis: 15%; margin-left: var(--space-4); }
.news__panel[data-offset="2"] { flex-basis: 7.5%; margin-left: var(--space-4); }
.news__panel[data-offset="3"] { flex-basis: 3.5%; margin-left: var(--space-3); }
.news__panel[data-offset^="-"] {
  flex-basis: 0;
  margin-left: 0;
  opacity: 0;
}

/* Moves a panel round the loop in one go, while it's folded */
.news__panel--jump { transition: none; }

/* Height-bound and centred, so the art holds still while the panel resizes */
.news__art {
  position: absolute;
  top: 0;
  left: 50%;
  width: auto;
  max-width: none;
  height: 100%;
  transform: translateX(-50%);
}

/* A soft shade along the bottom of the open panel, so its topic reads over busy artwork */
.news__panel::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, color-mix(in srgb, var(--surface-inverse) 85%, transparent), transparent 45%);
  opacity: 0;
  transition: opacity var(--duration-base) var(--ease-out);
}
.news__panel[data-offset="0"]::after {
  opacity: 1;
  transition-delay: var(--duration-slow);
}

/* The post's topic, over the open panel's artwork */
.news__kicker {
  position: absolute;
  z-index: 1;
  left: var(--space-5);
  bottom: var(--space-4);
  max-width: calc(100% - var(--space-10));
  color: var(--text-inverse);
  font-size: var(--text-lg);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  opacity: 0;
  transition: opacity var(--duration-base) var(--ease-out);
}
.news__panel[data-offset="0"] .news__kicker {
  opacity: 1;
  transition-delay: var(--duration-slow);
}

/* ---------- The open post's text ---------- */
.news__details { margin-top: var(--space-6); }

.news__detail {
  display: grid;
  gap: var(--space-5);
  align-items: start;
  animation: news-in var(--duration-slow) var(--ease-out);
}
.news__detail[hidden] { display: none; }

@keyframes news-in {
  from { opacity: 0; transform: translateY(4px); }
}

/* Title in ink and summary in grey, one run of text */
.news__text {
  max-width: 60ch;
  font-size: var(--text-lead);
  line-height: 1.3;
}

.news__headline,
.news__summary {
  display: inline;
  font-size: inherit;
}

.news__headline { font-weight: var(--weight-semibold); }
.news__summary { color: var(--text-secondary); }

.news__link { justify-self: start; }

@media (prefers-reduced-motion: reduce) {
  .news__detail { animation: none; }
}

@media (min-width: 640px) {
  .news__head {
    grid-template-columns: 1fr auto;
    align-items: end;
  }

  .news__detail {
    grid-template-columns: 1fr auto;
    gap: var(--space-8);
  }

  .news__kicker {
    left: var(--space-6);
    bottom: var(--space-5);
    font-size: var(--text-title);
  }
}

/* ==========================================================================
   FAQ
   Questions as native details elements sharing name="faq", so one opens at
   a time with no script. Rows match the stories rows: a card each, with the
   shared icon button holding a plus that turns into a minus. From 1024px
   the heading sits beside the questions.
   ========================================================================== */
.faq__list {
  display: grid;
  gap: var(--space-3);
}

.faq__item {
  overflow: hidden;
  border-radius: var(--radius-xl);
  background: var(--surface-card);
  box-shadow: var(--shadow-xs);
}

.faq__question {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: var(--space-6);
  padding: var(--space-4) var(--space-4) var(--space-4) var(--space-6);
  font-weight: var(--weight-semibold);
  list-style: none;
  cursor: pointer;
  transition: background-color var(--duration-fast) var(--ease-out);
}
.faq__question::-webkit-details-marker { display: none; }
.faq__item:not([open]) .faq__question:hover { background: var(--surface-hover); }
.faq__item:not([open]) .faq__question:hover .icon-button { background: var(--action-secondary-bg-hover); }

/* The card clips its contents, so the focus ring goes on the card */
.faq__question:focus-visible { box-shadow: none; }
.faq__item:has(.faq__question:focus-visible) { box-shadow: var(--focus-ring); }

.faq__answer {
  max-width: 64ch;
  padding: 0 var(--space-6) var(--space-6);
  color: var(--text-secondary);
}

@media (min-width: 640px) {
  .faq__question { padding: var(--space-5) var(--space-5) var(--space-5) var(--space-8); }
  .faq__answer { padding: 0 var(--space-8) var(--space-8); }
}

@media (min-width: 1024px) {
  .faq__layout {
    display: grid;
    grid-template-columns: 1fr 2fr;
    gap: var(--space-12);
    align-items: start;
  }

  .faq__layout .section-intro { margin-bottom: 0; }
}

/* ==========================================================================
   Articles
   The index of posts, newest first. The newest is a feature card with its
   artwork beside the text from 1024px; the next few are cards with artwork,
   two across from 768px; everything older is a plain list of date, title
   and topic. In the cards the title is the link, stretched over the whole
   card. The same cards make a short "keep reading" row at the end of a post.
   ========================================================================== */
.articles__feature,
.articles__card {
  position: relative;
  display: grid;
  gap: var(--space-5);
  padding: var(--space-3);
  border-radius: var(--radius-xl);
  background: var(--surface-card);
  box-shadow: var(--shadow-xs);
  transition: box-shadow var(--duration-base) var(--ease-out), transform var(--duration-base) var(--ease-out);
}
.articles__feature:hover,
.articles__card:hover {
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
}

/* The post's artwork, 2:1 */
.articles__art {
  width: 100%;
  aspect-ratio: 2 / 1;
  border-radius: var(--radius-lg);
  object-fit: cover;
}

.articles__text {
  display: grid;
  align-content: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3) var(--space-3);
}

.articles__kicker {
  color: var(--text-secondary);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
}

.articles__title {
  font-size: var(--text-lead);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  text-wrap: balance;
}
.articles__feature .articles__title { font-size: var(--text-title); }

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

/* The whole card is the link: the title's link reaches over the card, and
   the focus ring goes on the card itself */
.articles__feature .articles__title a::after,
.articles__card .articles__title a::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: var(--radius-xl);
}
.articles__feature .articles__title a:focus-visible,
.articles__card .articles__title a:focus-visible { box-shadow: none; }
.articles__feature:has(a:focus-visible),
.articles__card:has(a:focus-visible) { box-shadow: var(--focus-ring); }

.articles__summary { color: var(--text-secondary); }
.articles__feature .articles__summary {
  max-width: 44ch;
  font-size: var(--text-lead);
}

.articles__meta {
  color: var(--text-secondary);
  font-size: var(--text-sm);
}

.articles__grid {
  display: grid;
  gap: var(--space-6);
  margin: 0;
  padding: 0;
  list-style: none;
}
.articles__feature + .articles__grid { margin-top: var(--space-6); }

/* ---------- The list: older posts, with no art ---------- */
.articles__list {
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Rows separate with a hairline, as table rows do */
.articles__row {
  display: grid;
  gap: var(--space-1) var(--space-8);
  padding-block: var(--space-5);
  border-top: 1px solid var(--border-subtle);
}
.articles__row:last-child { border-bottom: 1px solid var(--border-subtle); }

.articles__row .articles__title {
  font-size: var(--text-lg);
  letter-spacing: normal;
}
.articles__row .articles__title a:hover {
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.articles__date {
  color: var(--text-secondary);
  font-size: var(--text-sm);
}

@media (min-width: 640px) {
  .articles__row {
    grid-template-columns: 11rem 1fr auto;
    align-items: baseline;
  }
}

@media (min-width: 768px) {
  .articles__grid { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 1024px) {
  .articles__feature {
    grid-template-columns: 3fr 2fr;
    align-items: center;
  }
  .articles__feature .articles__text { padding: var(--space-6) var(--space-8) var(--space-6) var(--space-3); }
}

/* ==========================================================================
   Subscribe
   A call to action to get new articles by email: a white card with the
   pitch and a short form. It posts like the enquiry form, so it shares the
   enquiry's status, trap and note pieces, and the form is a container, so
   the field and button go side by side once it's wide enough. On the index
   it's a block of its own; inside a post it's an aside between paragraphs
   (subscribe--inline), without the container, and stays in one column.
   ========================================================================== */
.subscribe__card {
  display: grid;
  gap: var(--space-8);
  padding: var(--space-6);
  border-radius: var(--radius-xl);
  background: var(--surface-card);
  box-shadow: var(--shadow-xs);
}

.subscribe__text {
  display: grid;
  gap: var(--space-4);
  justify-items: start;
}

.subscribe__title {
  font-size: var(--text-title);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  text-wrap: balance;
}

.subscribe__lead {
  max-width: 44ch;
  color: var(--text-secondary);
  font-size: var(--text-lead);
}

.subscribe__row {
  display: grid;
  gap: var(--space-3);
}

@container (min-width: 440px) {
  .subscribe__row {
    grid-template-columns: 1fr auto;
    align-items: end;
  }
}

.subscribe--inline .subscribe__card { padding: var(--space-5); }
.subscribe--inline .subscribe__title { font-size: var(--text-2xl); }
.subscribe--inline .subscribe__lead { font-size: var(--text-md); }

@media (min-width: 640px) {
  .subscribe__card { padding: var(--space-8); }
}

@media (min-width: 1024px) {
  .subscribe__card {
    grid-template-columns: 1fr 1fr;
    align-items: center;
    gap: var(--space-16);
    padding: var(--space-12);
  }

  .subscribe--inline .subscribe__card {
    grid-template-columns: 1fr;
    gap: var(--space-6);
    padding: var(--space-8);
  }
}

/* ---------- Compact: a slim sunken strip, under the index's hero ----------
   No icon, smaller type, and a sunken fill instead of a white card, so it
   reads as a footnote to the featured article rather than a block. */
.subscribe--compact .subscribe__card {
  gap: var(--space-5);
  padding: var(--space-5);
  border-radius: var(--radius-lg);
  background: var(--surface-sunken);
  box-shadow: none;
}

.subscribe--compact .subscribe__text { gap: var(--space-1); }
.subscribe--compact .subscribe__title { font-size: var(--text-lg); }
.subscribe--compact .subscribe__lead { font-size: var(--text-sm); }
.subscribe--compact .enquiry__note { font-size: var(--text-xs); }

@media (min-width: 1024px) {
  .subscribe--compact .subscribe__card {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: var(--space-10);
    padding: var(--space-5) var(--space-6);
  }
}

/* ==========================================================================
   Article
   A post's body: running text in the same reading column as the hero's
   text (--layout-measure), centred on the page. The body is plain HTML
   from the author (paragraphs, headings, lists, quotes, figures), spaced
   here rather than in the markup, with the base link style. A subscribe
   aside can sit between paragraphs.
   ========================================================================== */
.article__body {
  display: grid;
  gap: var(--space-5);
  max-width: var(--layout-measure);
  margin-inline: auto;
  font-size: var(--text-lg);
}

.article__body h2 {
  margin-top: var(--space-6);
  font-size: var(--text-2xl);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
}

.article__body strong { font-weight: var(--weight-semibold); }

.article__body ul,
.article__body ol {
  display: grid;
  gap: var(--space-3);
  margin: 0;
  padding-left: 1.25em;
}

.article__body blockquote {
  margin: 0;
  color: var(--text-secondary);
  font-size: var(--text-lead);
}

.article__body figure { margin: var(--space-3) 0; }
.article__body figure img { border-radius: var(--radius-lg); }
.article__body figcaption {
  margin-top: var(--space-3);
  color: var(--text-secondary);
  font-size: var(--text-sm);
}

.article__body .subscribe { margin-block: var(--space-6); }

/* ==========================================================================
   Footer
   Ink, in dark mode. A call to action, the site's links in columns, then a
   base row with the copyright, privacy policy and the Eightstep mark. A
   soft warm glow sits behind the call to action, as on the blog artwork.
   Top padding comes from the pt-150 utility.
   ========================================================================== */
.footer {
  background:
    radial-gradient(70% 480px at 50% 0%, color-mix(in srgb, var(--neutral-700) 55%, transparent), transparent),
    var(--surface-inverse);
  color: var(--text-inverse);
}

/* Focus rings need the ink as their gap */
.footer :focus-visible { box-shadow: var(--focus-ring-inverse); }

.footer__cta {
  display: grid;
  justify-items: start;
  gap: var(--space-8);
  padding-bottom: var(--space-16);
  border-bottom: 1px solid var(--border-inverse);
}

.footer__pitch {
  display: grid;
  gap: var(--space-5);
}

/* Plain text from the CMS: balance evens out the line breaks */
.footer__title {
  max-width: 14ch;
  font-size: var(--text-display);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-display);
  letter-spacing: var(--tracking-tight);
  text-wrap: balance;
}

.footer__lead {
  max-width: 44ch;
  color: var(--text-inverse-muted);
  font-size: var(--text-lead);
}

/* ---------- Links ---------- */
.footer__main {
  display: grid;
  gap: var(--space-12);
  padding-block: var(--space-16);
}

.footer__about {
  display: grid;
  align-content: start;
  gap: var(--space-4);
  max-width: 30ch;
  color: var(--text-inverse-muted);
}

.footer__address {
  font-size: var(--text-sm);
  font-style: normal;
}

.footer__nav {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-10) var(--space-6);
}

.footer__heading {
  margin-bottom: var(--space-4);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
}

.footer__list {
  display: grid;
  gap: var(--space-3);
  margin: 0;
  padding: 0;
  list-style: none;
}

.footer__link {
  border-radius: var(--radius-xs);
  color: var(--text-inverse-muted);
  font-size: var(--text-sm);
  text-decoration: none;
  transition: color var(--duration-fast) var(--ease-out);
}
.footer__link:hover { color: var(--text-inverse); }

/* ---------- Base row ---------- */
.footer__base {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3) var(--space-6);
  padding-block: var(--space-6) var(--space-10);
  border-top: 1px solid var(--border-inverse);
  color: var(--text-inverse-muted);
  font-size: var(--text-sm);
}

.footer__mark {
  display: block;
  margin-left: auto;
  border-radius: var(--radius-xs);
}
.footer__mark img { display: block; }

@media (min-width: 640px) {
  .footer__nav { grid-template-columns: repeat(3, 1fr); }
}

@media (min-width: 1024px) {
  /* The pitch on the left, the button level with the bottom of it on the right */
  .footer__cta {
    grid-template-columns: 1fr auto;
    align-items: end;
    padding-bottom: var(--space-32);
  }

  .footer__main {
    grid-template-columns: 1fr 2fr;
    padding-block: var(--space-16) var(--space-32);
  }
}
