/* ==========================================================================
   COMPONENTS — the shared pieces every page assembles from.
   Loads last. Nothing here invents a color, size, or duration; it all comes
   from tokens.css.
   ========================================================================== */

/* ==========================================================================
   BUTTON
   Inter Medium, sentence case, never all caps. Hover is a color shift plus a
   1px lift — small and fast, per the motion rules.
   ========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-1);
  padding: var(--sp-2) var(--sp-4);
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  font-weight: var(--fw-medium);
  line-height: 1.25;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition:
    background-color var(--dur-hover) var(--ease-out),
    border-color var(--dur-hover) var(--ease-out),
    color var(--dur-hover) var(--ease-out),
    transform var(--dur-hover) var(--ease-out),
    box-shadow var(--dur-hover) var(--ease-out);
}
.btn:hover { text-decoration: none; }
/* Button text is small to begin with; the default sup shrinks ™ to the point
   where it reads as a stray tilde. */
.btn sup { font-size: 0.72em; }

/* Primary — burgundy fill. One per view; this is the site's main action. */
.btn--primary {
  background: var(--burgundy);
  border-color: var(--burgundy);
  color: var(--white);
}
.btn--primary:hover {
  background: var(--burgundy-deep);
  border-color: var(--burgundy-deep);
  color: var(--white);
  transform: translateY(-1px);
  box-shadow: var(--shadow-md);
}
.btn--primary:active {
  transform: translateY(0);
  box-shadow: none;
}

/* Secondary — outline. Pairs beside a primary, never competes with it. */
.btn--secondary {
  background: transparent;
  border-color: var(--burgundy);
  color: var(--burgundy);
}
.btn--secondary:hover {
  background: var(--cream);
  border-color: var(--burgundy-deep);
  color: var(--burgundy-deep);
  transform: translateY(-1px);
}
.btn--secondary:active { transform: translateY(0); }

/* Warm variant — terracotta, for genuinely lower-priority actions only. */
.btn--warm {
  background: transparent;
  border-color: var(--terracotta);
  color: #A8482A;
}
.btn--warm:hover {
  background: rgba(217, 119, 87, 0.10);
  transform: translateY(-1px);
}

/* Quiet text action — reads as a link with a button's hit area. */
.btn--quiet {
  padding-inline: 0;
  background: transparent;
  border-color: transparent;
  color: var(--burgundy);
}
.btn--quiet:hover { color: var(--burgundy-deep); text-decoration: underline; }

/* Size + shape modifiers. */
.btn--sm { padding: 10px var(--sp-3); font-size: var(--fs-sm); }
.btn--lg { padding: var(--sp-3) var(--sp-5); font-size: var(--fs-body-lg); }
.btn--block { display: flex; width: 100%; }

.btn[disabled], .btn[aria-disabled="true"] {
  background: var(--disabled-bg);
  border-color: var(--disabled-bg);
  color: var(--disabled-ink);
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
  pointer-events: none;
}

/* On charcoal, the outline button inverts to cream. */
.on-dark .btn--secondary {
  border-color: rgba(244, 239, 230, 0.5);
  color: var(--text-on-dark);
}
.on-dark .btn--secondary:hover {
  background: rgba(244, 239, 230, 0.08);
  border-color: var(--cream);
  color: var(--cream);
}

/* Button row — CTAs sit side by side on desktop, stack full-width on phones. */
.btn-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
}
.btn-row--center { justify-content: center; }
@media (max-width: 479px) {
  .btn-row .btn { width: 100%; }
}

/* Arrow that nudges on hover — the one flourish buttons get. */
.btn__arrow {
  display: inline-block;
  transition: transform var(--dur-hover) var(--ease-out);
}
.btn:hover .btn__arrow { transform: translateX(3px); }
@media (prefers-reduced-motion: reduce) {
  .btn:hover .btn__arrow { transform: none; }
}

/* ==========================================================================
   HEADER / NAV
   Sticky, solid white, hairline base. Deliberately NO backdrop-filter: it
   makes the header a containing block for position:fixed children, which
   collapses the mobile menu panel. Same applies to transform, filter,
   contain and perspective — do not add any of them to .site-header.
   ========================================================================== */

.site-header {
  position: sticky;
  top: 0;
  z-index: var(--z-header);
  background: var(--white);
  border-bottom: 1px solid var(--line);
  transition: box-shadow var(--dur-hover) var(--ease-out);
}
.site-header.is-stuck { box-shadow: var(--shadow-md); }

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

/* Wordmark → home. */
.brand {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  color: var(--charcoal);
  text-decoration: none;
  flex-shrink: 0;
}
.brand:hover { text-decoration: none; }
.brand__mark { width: 34px; height: 34px; flex-shrink: 0; }
.brand__text { display: flex; flex-direction: column; line-height: 1.1; }
.brand__name {
  font-family: var(--font-heading);
  font-size: 1.0625rem;
  font-weight: var(--fw-semibold);
  letter-spacing: -0.01em;
}
.brand__role {
  font-size: 0.6875rem;
  font-weight: var(--fw-medium);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--text-muted);
  font-style: normal;
}

/* Desktop nav links. */
.nav {
  display: flex;
  align-items: center;
  gap: clamp(var(--sp-2), 1.6vw, var(--sp-4));
  margin-left: auto;
}

.nav__link {
  position: relative;
  padding-block: var(--sp-1);
  color: var(--text);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  text-decoration: none;
  white-space: nowrap;
}
.nav__link:hover { color: var(--burgundy); text-decoration: none; }

/* The ™ on INSIGHTS must not grow the link's line box, or its active
   underline would sit lower than every other link's. */
.nav__link sup { font-size: 0.55em; line-height: 0; vertical-align: super; }

/* Active + hover underline. Scales from the left on transform only. */
.nav__link::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 2px;
  background: var(--burgundy);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--dur-hover) var(--ease-out);
}
.nav__link:hover::after { transform: scaleX(0.4); }

/* Active page state. Driven by data-page on <body> matching data-nav on the
   link, so each page file differs by exactly one attribute. main.js also
   sets aria-current="page" on the same link for screen readers. */
body[data-page="home"]     .nav__link[data-nav="home"],
body[data-page="insights"] .nav__link[data-nav="insights"],
body[data-page="about"]    .nav__link[data-nav="about"],
body[data-page="services"] .nav__link[data-nav="services"],
body[data-page="work"]     .nav__link[data-nav="work"],
body[data-page="faq"]      .nav__link[data-nav="faq"] {
  color: var(--burgundy);
  font-weight: var(--fw-semibold);
}
body[data-page="home"]     .nav__link[data-nav="home"]::after,
body[data-page="insights"] .nav__link[data-nav="insights"]::after,
body[data-page="about"]    .nav__link[data-nav="about"]::after,
body[data-page="services"] .nav__link[data-nav="services"]::after,
body[data-page="work"]     .nav__link[data-nav="work"]::after,
body[data-page="faq"]      .nav__link[data-nav="faq"]::after {
  transform: scaleX(1);
}

.site-header .btn--primary { flex-shrink: 0; }

/* Hamburger. */
.nav-toggle {
  display: none;
  width: 44px;
  height: 44px;
  margin-right: -10px;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 5px;
  border-radius: var(--radius-sm);
  flex-shrink: 0;
}
.nav-toggle span {
  display: block;
  width: 22px;
  height: 2px;
  background: var(--charcoal);
  border-radius: 2px;
  transition: transform var(--dur-panel) var(--ease-out),
              opacity var(--dur-panel) var(--ease-out);
}
.nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* Scrim behind the open mobile panel. */
.nav-scrim {
  position: fixed;
  inset: 0;
  z-index: var(--z-overlay);
  background: rgba(29, 2, 7, 0.4);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--dur-panel) var(--ease-out), visibility var(--dur-panel);
}
.nav-scrim.is-open { opacity: 1; visibility: visible; }

/* ---- Mobile layout ------------------------------------------------------ */

@media (max-width: 899px) {
  .site-header__inner { min-height: var(--header-h-sm); }
  .nav-toggle { display: flex; }

  /* The nav becomes a panel sliding in from the right. */
  .nav {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    width: min(340px, 86vw);
    z-index: calc(var(--z-overlay) + 1);
    flex-direction: column;
    align-items: stretch;
    justify-content: flex-start;
    gap: 0;
    margin: 0;
    padding: calc(var(--header-h-sm) + var(--sp-4)) var(--sp-4) var(--sp-5);
    background: var(--white);   /* fully opaque — no blur, see note above */
    border-left: 1px solid var(--line);
    overflow-y: auto;
    overscroll-behavior: contain;
    transform: translateX(100%);
    visibility: hidden;
    transition: transform var(--dur-panel) var(--ease-out), visibility var(--dur-panel);
  }
  .nav.is-open { transform: translateX(0); visibility: visible; }

  .nav__link {
    padding: var(--sp-2) 0;
    font-size: var(--fs-body-lg);
    border-bottom: 1px solid var(--line);
  }
  .nav__link::after { display: none; }

  body[data-page] .nav__link[aria-current="page"] {
    color: var(--burgundy);
    font-weight: var(--fw-semibold);
  }

  /* The nav CTA lives in the header on desktop and inside the panel on
     mobile, so the markup carries both and CSS picks one. */
  .site-header > .container > .btn--primary { display: none; }
  .nav__cta { margin-top: var(--sp-4); }
}

@media (min-width: 900px) {
  .nav__cta { display: none; }
  .nav-scrim { display: none; }
}

/* Scroll lock while the panel is open. */
body.is-nav-open { overflow: hidden; }

@media (prefers-reduced-motion: reduce) {
  .nav { transition: none; }
}

/* ==========================================================================
   SECTION HEADER — eyebrow + heading + optional intro. Used at the top of
   most content blocks so section intros stay identical page to page.
   ========================================================================== */

.section-head { display: flex; flex-direction: column; gap: var(--sp-2); }
.section-head--center { align-items: center; text-align: center; }
.section-head--center .measure { margin-inline: auto; }
.section-head + * { margin-top: var(--sp-5); }

/* ==========================================================================
   CARD — white, 1px border, 16px radius, 32px padding. Flat by default;
   hover deepens the border and lifts 2px. No scaling, no tilting.
   ========================================================================== */

.card {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  padding: var(--sp-4);
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
}

.card--interactive {
  transition: transform var(--dur-hover) var(--ease-out),
              border-color var(--dur-hover) var(--ease-out),
              box-shadow var(--dur-hover) var(--ease-out);
}
.card--interactive:hover {
  transform: translateY(-2px);
  border-color: var(--line-strong);
  box-shadow: var(--shadow-md);
}
@media (prefers-reduced-motion: reduce) {
  .card--interactive:hover { transform: none; }
}

.card--cream { background: var(--cream); border-color: transparent; }
.card--dark  { background: var(--charcoal); border-color: transparent; }
.card--accent { border-color: var(--burgundy); }

.card__num {
  font-family: var(--font-heading);
  font-size: var(--fs-h3);
  font-weight: var(--fw-semibold);
  color: var(--taupe);
  line-height: 1;
}

/* ==========================================================================
   CTA BLOCK — the "Book a strategy call" component, dropped at the bottom of
   every page. One include, one set of links to maintain.
   ========================================================================== */

.cta-block { background: var(--charcoal); }

.cta-block__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-3);
  text-align: center;
  padding-block: var(--section-y);
}

.cta-block__title { color: var(--text-on-dark); max-width: 20ch; }
.cta-block__copy  { color: var(--text-on-dark-mut); max-width: 56ch; }
.cta-block__note  { font-size: var(--fs-sm); color: var(--text-on-dark-mut); }
.cta-block .btn-row { margin-top: var(--sp-2); }

/* ---- Photo variant ------------------------------------------------------
   The site-wide closing CTA: a fixed-attachment photo with a heavy overlay.
   Same background on every page; only the copy changes.

   The overlay is not decoration — the photo is bright and busy, so the text
   only clears contrast because of it. Never lighten it below ~0.72. */

.cta-block--photo {
  position: relative;
  background-color: var(--charcoal);
  background-image: url("../assets/cta-bg.jpg");
  background-size: cover;
  background-position: center 20%;
  background-repeat: no-repeat;
  background-attachment: fixed;
}

.cta-block--photo::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg, rgba(29, 2, 7, 0.88) 0%, rgba(29, 2, 7, 0.82) 45%, rgba(29, 2, 7, 0.90) 100%);
}

/* Lifts the copy above the ::before overlay. */
.cta-block--photo > .container { position: relative; z-index: 1; }

/* Over a photo the muted body tone loses too much contrast, so this variant
   uses the full-strength text colour rather than the dimmed one. */
.cta-block--photo .cta-block__copy { color: var(--text-on-dark); }

/* iOS Safari does not support background-attachment: fixed — it renders the
   image at wildly the wrong scale. Scroll with the section instead. Also
   avoids the repaint cost of a fixed background on low-powered devices. */
@media (max-width: 899px), (hover: none) {
  .cta-block--photo {
    background-attachment: scroll;
    background-position: center 25%;
  }
}

/* Cream variant, for pages that end on a dark section already. */
.cta-block--cream { background: var(--cream); }
.cta-block--cream .cta-block__title { color: var(--charcoal); }
.cta-block--cream .cta-block__copy,
.cta-block--cream .cta-block__note { color: var(--text-muted); }

/* ==========================================================================
   FOOTER
   ========================================================================== */

.site-footer {
  background: var(--charcoal);
  padding-block: var(--section-y-tight) var(--sp-5);
}

.site-footer__top {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) repeat(2, minmax(0, 1fr));
  gap: var(--sp-6) var(--sp-5);
  padding-bottom: var(--sp-5);
  border-bottom: 1px solid var(--line);
}

@media (max-width: 899px) {
  .site-footer__top { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .site-footer__brand { grid-column: 1 / -1; }
}
@media (max-width: 479px) {
  .site-footer__top { grid-template-columns: minmax(0, 1fr); gap: var(--sp-5); }
}

.site-footer .brand { color: var(--text-on-dark); }
.site-footer .brand__role { color: var(--taupe); }

.site-footer__positioning {
  margin-top: var(--sp-3);
  max-width: 34ch;
  color: var(--text-on-dark-mut);
  font-size: var(--fs-sm);
  line-height: var(--lh-body);
}

.footer-heading {
  font-family: var(--font-body);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--taupe);
  margin-bottom: var(--sp-2);
}

.footer-list + .footer-heading { margin-top: var(--sp-4); }

.footer-list { list-style: none; display: flex; flex-direction: column; gap: 10px; }
.footer-list a {
  color: var(--text-on-dark-mut);
  font-size: var(--fs-sm);
  text-decoration: none;
}
.footer-list a:hover { color: var(--cream); text-decoration: underline; }

.social-list {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
}
.social-list a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  color: var(--text-on-dark-mut);
  transition: color var(--dur-hover) var(--ease-out),
              border-color var(--dur-hover) var(--ease-out),
              background-color var(--dur-hover) var(--ease-out);
}
.social-list a:hover {
  color: var(--charcoal);
  background: var(--cream);
  border-color: var(--cream);
  text-decoration: none;
}
.social-list svg { width: 18px; height: 18px; fill: currentColor; }

.site-footer__bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2);
  padding-top: var(--sp-3);
  font-size: var(--fs-sm);
  color: var(--text-on-dark-mut);
}
.site-footer__bottom a { color: var(--text-on-dark-mut); }
.site-footer__bottom a:hover { color: var(--cream); }

/* ==========================================================================
   PAGE HEADER — the standard top-of-page block for interior pages, so Home
   is the only page that gets a bespoke hero.
   ========================================================================== */

.page-head {
  background: var(--cream);
  padding-block: var(--section-y-tight);
  border-bottom: 1px solid rgba(29, 2, 7, 0.06);
}
.page-head__inner { display: flex; flex-direction: column; gap: var(--sp-2); }

/* The ch constraint goes on the heading itself, not the wrapper: `ch` is
   measured against the element's own font, so on the wrapper it would resolve
   against 18px body text and crush a 56px H1 to a third of its width. */
.page-head__inner h1 { max-width: 17ch; }

.page-head__intro { max-width: var(--measure); margin-top: var(--sp-3); }

/* ==========================================================================
   TAG — small label pinned to a card. Used for "Signature partnership".
   ========================================================================== */

.tag {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  padding: 5px var(--sp-2);
  border-radius: var(--radius-pill);
  background: var(--burgundy);
  color: var(--white);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  line-height: 1.4;
}
.tag--gold { background: var(--gold); color: var(--charcoal); }

/* ==========================================================================
   CHECK LIST — gold tick bullets. The tick is decorative, so it is drawn in
   a span the screen reader skips rather than as list-style text.
   ========================================================================== */

.check-list { list-style: none; display: flex; flex-direction: column; gap: var(--sp-1); }

.check-list li {
  position: relative;
  padding-left: 30px;
  line-height: var(--lh-body);
}
.check-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.44em;
  width: 18px;
  height: 18px;
  border-radius: var(--radius-pill);
  background: var(--gold) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23FFFFFF' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E") center / 12px 12px no-repeat;
}

/* ==========================================================================
   STATEMENT — a single emphasised sentence standing alone between blocks.
   Bigger than body, quieter than a heading.
   ========================================================================== */

.statement {
  font-size: var(--fs-quote);
  font-weight: var(--fw-medium);
  line-height: 1.4;
  color: var(--charcoal);
  max-width: 30ch;
}
.statement strong { font-weight: var(--fw-medium); }
.statement--center { margin-inline: auto; text-align: center; }

/* ==========================================================================
   OFFER CARD — the pricing ladder as a row of accordions. Collapsed, a card
   shows only its tag, name and price; the detail opens on click. Cards open
   independently so two can be compared side by side.
   ========================================================================== */

/* Anchor offer on the left, the rest stacked on the right.

   A plain 2×2 grid was the obvious layout and the wrong one: the always-open
   signature card makes the first row tall, so a collapsed card beside it sat
   in a tall empty bordered box. Stacking the other three means a closed card
   costs only its own header height. */

.offer-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--sp-4);
  align-items: start;
}
@media (max-width: 899px) { .offer-layout { grid-template-columns: minmax(0, 1fr); } }

.offer-stack { display: flex; flex-direction: column; gap: var(--sp-3); }

.offer-card {
  display: flex;
  flex-direction: column;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
  transition: border-color var(--dur-hover) var(--ease-out),
              box-shadow var(--dur-hover) var(--ease-out);
}
.offer-card:hover { border-color: var(--line-strong); box-shadow: var(--shadow-md); }

.offer-card--signature {
  border-color: var(--burgundy);
  border-width: 2px;
  background: var(--cream);
}
.offer-card--signature:hover { border-color: var(--burgundy-deep); }

/* ---- Header (the toggle) ---- */

.offer-card__heading { margin: 0; font: inherit; }

.offer-card__head {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sp-1);
  width: 100%;
  padding: var(--sp-4);
  text-align: left;
  cursor: pointer;
}

.offer-card .tag {
  padding: 4px 10px;
  font-size: 0.6875rem;
  letter-spacing: 0.08em;
}

.offer-card__name {
  font-family: var(--font-heading);
  font-size: var(--fs-h4);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-snug);
  color: var(--charcoal);
}

.offer-card__price {
  font-family: var(--font-heading);
  font-size: 1.375rem;
  font-weight: var(--fw-extrabold);
  line-height: 1.15;
  color: var(--burgundy);
}
.offer-card__price small {
  font-size: 0.85rem;
  font-weight: var(--fw-medium);
  color: var(--text-muted);
}

/* Chevron pinned to the top-right of the header. */
.offer-card__chev {
  position: absolute;
  top: var(--sp-4);
  right: var(--sp-4);
  width: 18px;
  height: 18px;
  fill: none;
  stroke: var(--burgundy);
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform var(--dur-panel) var(--ease-out);
}
.offer-card__head { position: relative; padding-right: calc(var(--sp-4) + 24px); }
.offer-card.is-open .offer-card__chev { transform: rotate(180deg); }
@media (prefers-reduced-motion: reduce) { .offer-card__chev { transition: none; } }

/* ---- Panel ----
   grid-template-rows 0fr → 1fr is the one height animation on the site; it
   needs a min-height:0 child with overflow hidden to collapse cleanly. */

.offer-card__panel {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--dur-panel) var(--ease-out);
}
.offer-card.is-open .offer-card__panel { grid-template-rows: 1fr; }

/* visibility, not just overflow: a 0-height clipped panel still keeps its
   links in the tab order, so keyboard users would tab into an invisible
   button. Transitioning visibility holds it visible until the collapse
   finishes, then switches it off. */
.offer-card__panel-inner {
  min-height: 0;
  overflow: hidden;
  visibility: hidden;
  transition: visibility var(--dur-panel) var(--ease-out);
}
.offer-card.is-open .offer-card__panel-inner { visibility: visible; }

.offer-card__body {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  padding: 0 var(--sp-4) var(--sp-4);
}
.offer-card__body > p + p { margin-top: 0; }

.offer-card__sub {
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  color: var(--text-muted);
  line-height: var(--lh-body);
}

.offer-card__body .btn { margin-top: var(--sp-1); align-self: stretch; }

/* No JS: every panel is open, so no offer is ever hidden. */
html:not(.js) .offer-card__panel { grid-template-rows: 1fr; }
html:not(.js) .offer-card__panel-inner { visibility: visible; }
html:not(.js) .offer-card__chev { display: none; }

@media (prefers-reduced-motion: reduce) {
  .offer-card__panel { transition: none; }
}

/* ==========================================================================
   SECTION SUBHEAD — the one line that sits under a section heading. Given
   real air above it so it reads as a subheading, not a caption.
   ========================================================================== */

.section-sub {
  margin-top: var(--sp-4);
  font-size: var(--fs-body-lg);
  font-weight: var(--fw-medium);
  line-height: var(--lh-snug);
  color: var(--burgundy);
}
.section-sub--muted { color: var(--text-muted); }

/* ==========================================================================
   ACCORDION — plain disclosure list. Same mechanics as the offer cards
   (grid-template-rows 0fr→1fr, visibility for tab order), without the
   pricing furniture.
   ========================================================================== */

.accordion { list-style: none; display: flex; flex-direction: column; }

.accordion__item { border-top: 1px solid var(--line); }
.accordion__item:last-child { border-bottom: 1px solid var(--line); }

.accordion__heading { margin: 0; font: inherit; }

.accordion__head {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  width: 100%;
  padding: var(--sp-3) 0;
  text-align: left;
  cursor: pointer;
  font-family: var(--font-heading);
  font-size: var(--fs-h4);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-snug);
  color: var(--charcoal);
  transition: color var(--dur-hover) var(--ease-out);
}
.accordion__head:hover { color: var(--burgundy); }

.accordion__chev {
  flex-shrink: 0;
  width: 18px;
  height: 18px;
  fill: none;
  stroke: var(--burgundy);
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform var(--dur-panel) var(--ease-out);
}
.accordion__item.is-open .accordion__chev { transform: rotate(180deg); }

.accordion__panel {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--dur-panel) var(--ease-out);
}
.accordion__item.is-open .accordion__panel { grid-template-rows: 1fr; }

.accordion__panel-inner {
  min-height: 0;
  overflow: hidden;
  visibility: hidden;
  transition: visibility var(--dur-panel) var(--ease-out);
}
.accordion__item.is-open .accordion__panel-inner { visibility: visible; }

.accordion__body { padding-bottom: var(--sp-3); color: var(--text-muted); }

/* No JS: everything is open, so no answer is ever unreachable. */
html:not(.js) .accordion__panel { grid-template-rows: 1fr; }
html:not(.js) .accordion__panel-inner { visibility: visible; }
html:not(.js) .accordion__chev { display: none; }

@media (prefers-reduced-motion: reduce) {
  .accordion__panel, .accordion__chev { transition: none; }
}

/* ==========================================================================
   MARQUEE — the trust band. Two identical tracks scroll side by side; when
   the first has travelled its own width the pair resets, so the loop is
   seamless. Transform only.
   ========================================================================== */

.trust-band {
  background: var(--charcoal);
  padding-block: var(--sp-3);
  overflow: hidden;
}

.marquee { display: flex; width: 100%; overflow: hidden; }

.marquee__track {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  gap: var(--sp-5);
  padding-right: var(--sp-5);
  list-style: none;
  animation: marquee-scroll 34s linear infinite;
}
.marquee:hover .marquee__track,
.marquee:focus-within .marquee__track { animation-play-state: paused; }

.marquee__track li {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-5);
  white-space: nowrap;
  font-family: var(--font-heading);
  font-size: var(--fs-body);
  font-weight: var(--fw-medium);
  color: var(--text-on-dark);
}
/* Gold separator dot after every item. */
.marquee__track li::after {
  content: "";
  width: 5px;
  height: 5px;
  border-radius: var(--radius-pill);
  background: var(--gold);
  flex-shrink: 0;
}

@keyframes marquee-scroll {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-100%, 0, 0); }
}

/* Reduced motion: no scrolling. The list wraps and centres instead, and the
   duplicate track is removed so nothing is announced twice. */
@media (prefers-reduced-motion: reduce) {
  .marquee { justify-content: center; }
  .marquee__track {
    animation: none;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--sp-2) var(--sp-4);
    padding-right: 0;
  }
  .marquee__track li { gap: var(--sp-4); }
  .marquee__track[aria-hidden="true"] { display: none; }
}

/* ==========================================================================
   PROCESS — numbered steps. Used on Home; Services will want it too.
   ========================================================================== */

.process {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--sp-5);
  counter-reset: step;
}
@media (max-width: 899px) { .process { grid-template-columns: minmax(0, 1fr); gap: var(--sp-4); } }

.process__step {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  padding-top: var(--sp-3);
  border-top: 2px solid var(--line-strong);
}

.process__num {
  font-family: var(--font-heading);
  font-size: 2.5rem;
  font-weight: var(--fw-extrabold);
  line-height: 1;
  color: var(--taupe);
}
.process__step h3 { font-size: var(--fs-h4); }
.process__step p { color: var(--text-muted); }

/* ==========================================================================
   CAROUSEL — one slide visible, arrows + dots, optional autoplay.
   The track moves on transform only. Slides that are off-screen are hidden
   from assistive tech but never removed, so no content depends on JS.
   ========================================================================== */

.carousel { position: relative; }

.carousel__viewport { overflow: hidden; border-radius: var(--radius-lg); }

.carousel__track {
  display: flex;
  transition: transform var(--dur-panel) var(--ease-out);
}
/* Before JS runs there is no transform, so slide 1 shows and the rest sit
   off to the right — never a blank box. */
.carousel__slide { flex: 0 0 100%; min-width: 0; }

@media (prefers-reduced-motion: reduce) {
  .carousel__track { transition: none; }
}

.carousel__controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-3);
  margin-top: var(--sp-4);
}

.carousel__arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-pill);
  color: var(--charcoal);
  background: var(--white);
  transition: background-color var(--dur-hover) var(--ease-out),
              border-color var(--dur-hover) var(--ease-out),
              color var(--dur-hover) var(--ease-out);
}
.carousel__arrow:hover {
  background: var(--burgundy);
  border-color: var(--burgundy);
  color: var(--white);
}
.carousel__arrow svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2; }

.carousel__dots { display: flex; gap: 10px; list-style: none; }
.carousel__dot {
  width: 9px;
  height: 9px;
  padding: 0;
  border-radius: var(--radius-pill);
  background: var(--line-strong);
  transition: background-color var(--dur-hover) var(--ease-out),
              transform var(--dur-hover) var(--ease-out);
}
.carousel__dot[aria-selected="true"] { background: var(--burgundy); transform: scale(1.3); }
@media (prefers-reduced-motion: reduce) { .carousel__dot { transform: none !important; } }

/* Testimonial slide layout. */
.testimonial {
  display: grid;
  grid-template-columns: 260px minmax(0, 1fr);
  gap: var(--sp-5);
  align-items: center;
  padding: var(--sp-5);
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
}
@media (max-width: 899px) {
  .testimonial { grid-template-columns: minmax(0, 1fr); gap: var(--sp-3); padding: var(--sp-4); }
}

.testimonial__media {
  width: 100%;
  aspect-ratio: 1 / 1;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--cream);
}
.testimonial__media img { width: 100%; height: 100%; object-fit: cover; }
@media (max-width: 899px) {
  .testimonial__media { width: 120px; aspect-ratio: 1 / 1; border-radius: var(--radius-pill); }
}

/* Fallback for a person with no photo — initials, never someone else's face. */
.testimonial__initials {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  background: var(--cream);
  color: var(--burgundy);
  font-family: var(--font-heading);
  font-size: 3rem;
  font-weight: var(--fw-semibold);
  letter-spacing: 0.02em;
}

.testimonial__quote-head {
  font-family: var(--font-heading);
  font-size: var(--fs-h3);
  font-weight: var(--fw-medium);
  line-height: var(--lh-snug);
  color: var(--burgundy);
}
.testimonial__quote { color: var(--text-muted); line-height: var(--lh-body); }
.testimonial__cite { display: block; margin-top: var(--sp-3); font-style: normal; }
.testimonial__name { font-weight: var(--fw-semibold); color: var(--charcoal); }
/* The name links to the person's own profile — underlined in taupe so it
   reads as a link without pulling attention off the quote. */
.testimonial__name a {
  color: var(--charcoal);
  text-decoration: underline;
  text-decoration-color: var(--taupe);
  text-decoration-thickness: 1px;
}
.testimonial__name a:hover { color: var(--burgundy); text-decoration-color: var(--burgundy); }
.testimonial__role { display: block; font-size: var(--fs-sm); color: var(--text-muted); }

/* ==========================================================================
   THUMB GRID — portfolio tiles that open a lightbox. The overlay label sits
   permanently over the image (not hover-only), so touch users read it too.
   ========================================================================== */

.thumb-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--sp-4);
}
@media (max-width: 899px) { .thumb-grid { grid-template-columns: minmax(0, 1fr); } }

/* Flex column so the white note stretches to fill the grid row. Without it a
   card with shorter copy leaves the charcoal card background showing along
   its bottom edge, since grid rows stretch every tile to the tallest. */
.thumb {
  display: flex;
  flex-direction: column;
  width: 100%;
  text-align: left;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--charcoal);
  border: 1px solid var(--line);
  transition: transform var(--dur-hover) var(--ease-out),
              box-shadow var(--dur-hover) var(--ease-out);
}
.thumb:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); text-decoration: none; }
@media (prefers-reduced-motion: reduce) { .thumb:hover { transform: none; } }

/* These are spans inside an <a>, so each needs an explicit box. */
.thumb__media { display: block; position: relative; aspect-ratio: 4 / 5; }
/* Absolutely positioned so the tile's 4:5 box is the only thing setting its
   size. The source thumbnails are not all the same ratio, and a statically
   positioned image lets its own intrinsic height leak into the layout. */
.thumb__media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--dur-hover) var(--ease-out);
}
.thumb:hover .thumb__media img { transform: scale(1.02); }
@media (prefers-reduced-motion: reduce) { .thumb:hover .thumb__media img { transform: none; } }

/* The tiles sit on real ad creative, which has its own light text near the
   bottom. The gradient has to be dark enough at label height to win. */
.thumb__overlay {
  position: absolute;
  inset: auto 0 0 0;
  padding: var(--sp-6) var(--sp-3) var(--sp-3);
  background: linear-gradient(
    to top,
    rgba(29, 2, 7, 0.94) 0%,
    rgba(29, 2, 7, 0.88) 40%,
    rgba(29, 2, 7, 0.55) 70%,
    rgba(29, 2, 7, 0) 100%
  );
  color: var(--white);
}
.thumb__brand {
  display: block;
  font-family: var(--font-heading);
  font-size: var(--fs-h4);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-snug);
}
.thumb__kind {
  display: block;
  margin-top: 2px;
  font-size: var(--fs-sm);
  font-style: italic;
  color: var(--taupe);
}
.thumb__note {
  display: block;
  flex: 1 1 auto;
  padding: var(--sp-3);
  background: var(--white);
  color: var(--text-muted);
  font-size: var(--fs-sm);
  line-height: var(--lh-body);
}
.thumb__cue {
  display: block;
  margin-top: var(--sp-2);
  color: var(--burgundy);
  font-weight: var(--fw-medium);
}

/* ==========================================================================
   LIGHTBOX — in-page modal. Scrolls vertically through the rest of a set.
   Closed state is `hidden`, so with JS off the markup is inert and the page
   below is unaffected.
   ========================================================================== */

.lightbox {
  position: fixed;
  inset: 0;
  z-index: var(--z-overlay);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: var(--sp-5) var(--sp-3);
  background: rgba(29, 2, 7, 0.82);
  overflow-y: auto;
  overscroll-behavior: contain;
}
.lightbox[hidden] { display: none; }

.lightbox__panel {
  position: relative;
  width: min(760px, 100%);
  margin: auto;
  padding: var(--sp-5) var(--sp-4) var(--sp-4);
  background: var(--white);
  border-radius: var(--radius-lg);
}

.lightbox__close {
  position: absolute;
  top: var(--sp-2);
  right: var(--sp-2);
  width: 40px;
  height: 40px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-pill);
  background: var(--cream);
  color: var(--charcoal);
  font-size: 1.25rem;
  line-height: 1;
  transition: background-color var(--dur-hover) var(--ease-out),
              color var(--dur-hover) var(--ease-out);
}
.lightbox__close:hover { background: var(--burgundy); color: var(--white); }

.lightbox__head { margin-bottom: var(--sp-4); padding-right: 48px; }
.lightbox__kind { font-style: italic; color: var(--text-muted); font-size: var(--fs-sm); }
.lightbox__note { margin-top: var(--sp-2); color: var(--text-muted); }

.lightbox__items { display: flex; flex-direction: column; gap: var(--sp-3); }
.lightbox__items img {
  width: 100%;
  border-radius: var(--radius-md);
  border: 1px solid var(--line);
  background: var(--cream);
}

.lightbox__doc {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  padding: var(--sp-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--cream);
}

/* Scroll lock. position:fixed rather than overflow:hidden because iOS Safari
   ignores the latter on <body>. main.js stores the offset in `top` and
   restores the exact scroll position on close. */
body.is-lightbox-open {
  position: fixed;
  width: 100%;
  overflow: hidden;
}

/* ==========================================================================
   HERO SHELL — the section background every page hero sits on: cream-to-
   apricot wash, warm gold light upper-right, burgundy shadow bottom-left,
   plus the paper grain. Lived in home.css until the INSIGHTS page needed the
   same backdrop; moved here rather than copied, per the note in that file.

   This rule is the backdrop ONLY. The home page's two-column arrangement
   (.hero__grid, .hero__copy, .hero__figure) stays in home.css, and the
   INSIGHTS page's centred arrangement lives in insights.css.
   ========================================================================== */

.hero {
  /* Held in a variable because the portrait cancels the bottom padding with a
     negative margin of exactly this size — see .hero__figure. */
  --hero-pad: clamp(var(--sp-5), 4.5vw, var(--sp-7));

  position: relative;
  isolation: isolate;
  padding-block: var(--hero-pad);
  overflow: hidden;

  /* Warm light from the upper right, a burgundy shadow bottom-left, over a
     cream-to-apricot wash. Three low-opacity layers rather than one flat
     fill — that is the whole difference between "premium" and "pink". */
  background:
    radial-gradient(58% 52% at 80% 12%, rgba(191, 145, 66, 0.22), transparent 62%),
    radial-gradient(66% 58% at 4% 96%, rgba(156, 15, 42, 0.11), transparent 62%),
    linear-gradient(158deg, #FFFAEC 0%, var(--cream) 44%, #F8DEC2 100%);
}

/* Barely-there paper grain. At 0.03 it reads as texture, not noise — check on
   a calibrated screen before touching this value. */
.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: 0.03;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ==========================================================================
   STATIC GALLERY — a project's ad creative scrolling past, marquee-style.

   Same two-track mechanism as .marquee above: JS clones the track, the pair
   sits in one flex row, and both translate -100% of their own width, so the
   moment track 1 leaves, track 2 is exactly where it started. Transform only.

   Every tile is a <button>, not an <img> in an <a> — it opens the in-page
   viewer, and a button is what that actually is. Only the first track is in
   the tab order; main.js marks the clone aria-hidden and untabbable.
   ========================================================================== */

.gallery {
  position: relative;
  display: flex;
  width: 100%;
  overflow: hidden;
  /* Both edges fade into the card rather than being chopped off by it. The
     mask is the whole reason the strip reads as "passing through" instead of
     "clipped". Feathering is small — 6% — so no tile is unreadable for long. */
  -webkit-mask-image: linear-gradient(to right, transparent 0, #000 6%, #000 94%, transparent 100%);
          mask-image: linear-gradient(to right, transparent 0, #000 6%, #000 94%, transparent 100%);
}

.gallery__track {
  display: flex;
  flex: 0 0 auto;
  align-items: stretch;
  gap: var(--sp-3);
  padding-right: var(--sp-3);
  list-style: none;
  animation: gallery-scroll 46s linear infinite;
}

/* Pause while she is looking at one — hover and keyboard focus both count. */
.gallery:hover .gallery__track,
.gallery:focus-within .gallery__track { animation-play-state: paused; }

.gallery__item { display: flex; flex: 0 0 auto; }

.gallery__btn {
  display: block;
  flex: 0 0 auto;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--cream);
  border: 1px solid var(--line);
  transition: transform var(--dur-hover) var(--ease-out),
              box-shadow var(--dur-hover) var(--ease-out);
}
.gallery__btn:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); }

/* Sized by height so a 4:5 and a 1:1 static still line up along the strip.
   max-width:none is deliberate — the global img rule would cap the width and
   quietly shrink the taller ones below the intended height. */
.gallery__btn img {
  display: block;
  width: auto;
  max-width: none;
  height: clamp(240px, 26vw, 380px);
  object-fit: contain;
}

@keyframes gallery-scroll {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-100%, 0, 0); }
}

/* Reduced motion: nothing moves on its own. The strip becomes an ordinary
   horizontal scroller she drags herself, and the clone is dropped so no
   static is announced or scrolled past twice. */
@media (prefers-reduced-motion: reduce) {
  .gallery {
    overflow-x: auto;
    overscroll-behavior-x: contain;
    -webkit-mask-image: none;
            mask-image: none;
  }
  .gallery__track { animation: none; }
  .gallery__track[aria-hidden="true"] { display: none; }
  .gallery__btn:hover { transform: none; }
}

/* ==========================================================================
   VIEWER — full-screen single-image modal with prev/next.

   Distinct from .lightbox above: that one stacks a whole set vertically, this
   one shows one static at a time and steps through the project's set. Both
   restore the exact scroll position on close; see main.js.
   ========================================================================== */

.viewer {
  position: fixed;
  inset: 0;
  z-index: var(--z-overlay);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-5) clamp(var(--sp-3), 8vw, var(--sp-8));
  background: rgba(29, 2, 7, 0.9);
}
.viewer[hidden] { display: none; }

.viewer__figure {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-2);
  max-width: 100%;
  max-height: 100%;
  margin: 0;
}

.viewer__img {
  display: block;
  max-width: 100%;
  /* Leaves room for the caption line under it at short viewport heights. */
  max-height: calc(100vh - var(--sp-8));
  width: auto;
  height: auto;
  border-radius: var(--radius-md);
  background: var(--cream);
}

.viewer__caption {
  color: var(--text-on-dark-mut);
  font-size: var(--fs-sm);
  text-align: center;
}
.viewer__count { color: var(--taupe); }

/* Controls — the same pill treatment as the lightbox close, so the two
   modals read as one family. */
.viewer__close,
.viewer__nav {
  position: absolute;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-pill);
  background: var(--cream);
  color: var(--charcoal);
  transition: background-color var(--dur-hover) var(--ease-out),
              color var(--dur-hover) var(--ease-out);
}
.viewer__close:hover,
.viewer__nav:hover { background: var(--burgundy); color: var(--white); }

.viewer__close {
  top: var(--sp-2);
  right: var(--sp-2);
  width: 44px;
  height: 44px;
  font-size: 1.375rem;
  line-height: 1;
}

.viewer__nav {
  top: 50%;
  transform: translateY(-50%);
  width: 48px;
  height: 48px;
}
.viewer__nav--prev { left: clamp(var(--sp-1), 2vw, var(--sp-4)); }
.viewer__nav--next { right: clamp(var(--sp-1), 2vw, var(--sp-4)); }
.viewer__nav svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 2.2; }

/* On a phone the arrows would sit on top of the image at 50%; drop them to
   the bottom corners where a thumb already is. */
@media (max-width: 599px) {
  .viewer { padding: var(--sp-6) var(--sp-2) var(--sp-7); }
  .viewer__nav { top: auto; bottom: var(--sp-2); transform: none; }
  .viewer__img { max-height: calc(100vh - 210px); }
}

@media (prefers-reduced-motion: reduce) {
  .viewer__nav { transform: none; top: auto; bottom: var(--sp-3); }
}

/* ==========================================================================
   DOC READER — a PDF opened inside the site rather than in a new tab.

   The panel is a plain <iframe> pointed at the file, so the browser's own PDF
   viewer does the rendering and there is no library to ship. Some mobile
   browsers refuse to render a PDF in a frame at all, which is what the
   fallback link in the footer is for — it is the escape hatch, never the
   primary route. The src is set on open and cleared on close, so no PDF is
   fetched until it is asked for.
   ========================================================================== */

.docreader {
  position: fixed;
  inset: 0;
  z-index: var(--z-overlay);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(var(--sp-2), 3vw, var(--sp-4));
  background: rgba(29, 2, 7, 0.9);
}
.docreader[hidden] { display: none; }

.docreader__panel {
  display: flex;
  flex-direction: column;
  width: min(1000px, 100%);
  height: 100%;
  overflow: hidden;
  background: var(--white);
  border-radius: var(--radius-lg);
}

.docreader__bar {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-2) var(--sp-2) var(--sp-3);
  border-bottom: 1px solid var(--line);
  background: var(--cream);
}

.docreader__title {
  flex: 1 1 auto;
  min-width: 0;
  font-family: var(--font-heading);
  font-size: var(--fs-h4);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-snug);
  color: var(--charcoal);
  /* Long research titles must not push the close button off the bar. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.docreader__close {
  flex-shrink: 0;
  width: 40px;
  height: 40px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-pill);
  background: var(--white);
  color: var(--charcoal);
  font-size: 1.25rem;
  line-height: 1;
  border: 1px solid var(--line);
  transition: background-color var(--dur-hover) var(--ease-out),
              color var(--dur-hover) var(--ease-out);
}
.docreader__close:hover { background: var(--burgundy); border-color: var(--burgundy); color: var(--white); }

/* min-height:0 so the frame can shrink inside the flex column instead of
   overflowing the panel and pushing the bar off screen. */
.docreader__frame {
  flex: 1 1 auto;
  min-height: 0;
  width: 100%;
  border: 0;
  background: var(--cream-deep);
}

.docreader__foot {
  flex-shrink: 0;
  padding: var(--sp-1) var(--sp-3);
  border-top: 1px solid var(--line);
  font-size: var(--fs-sm);
  color: var(--text-muted);
  text-align: center;
}
