/* ============================================================================
   CrochetCalc Global Shell — Wave 1B
   ============================================================================

   Header, primary navigation, mega menus, mobile drawer, breadcrumb and footer.
   Built entirely on the Wave 1A tokens in design-system.css; this file defines
   no colours, spacing or type of its own.

   NAMESPACE  `ccs-` (CrochetCalc Shell)
   -------------------------------------
   main.css still carries the previous shell rules under .site-header, .nav__*
   and .footer__* - including three competing mobile-nav blocks and 520
   !important declarations. Rather than fight that cascade, the new shell uses
   different class names, so the old rules simply stop matching. Nothing in
   main.css needed to be deleted, which keeps this wave reversible.

   ICONS ARE CSS, NOT MARKUP
   -------------------------
   The old nav used eight emoji as its icon system. They are replaced with the
   Wave 1A icon language (24x24 grid, 1.5 stroke, round caps) delivered as
   mask-image data URIs. Defined once in this cached file rather than inlined
   into all 57 pages, so the icon set costs zero per-page bytes and inherits
   currentColor.
   ========================================================================= */

/* ==========================================================================
   1. SHELL TOKENS
   ========================================================================== */

:root {
  --ccs-header-h: 68px;          /* desktop, inside the 64-76px target      */
  --ccs-header-h-mobile: 60px;   /* mobile, inside the 56-64px target       */
  --ccs-nav-max: 1280px;
}

/* The sticky header would otherwise sit on top of every anchor target: an
   in-page jump landed with its heading hidden behind the bar. */
html {
  scroll-padding-top: calc(var(--ccs-header-h) + var(--cc-space-4));
}

/* ==========================================================================
   2. HEADER
   ========================================================================== */

.ccs-header {
  position: sticky;
  top: 0;
  z-index: 60;
  height: var(--ccs-header-h);      /* fixed from first paint - no CLS */
  background: var(--cc-color-canvas);
  border-bottom: 1px solid var(--cc-color-border);
}

.ccs-header__inner {
  position: relative;      /* containing block for the mega panels */
  display: flex;
  align-items: center;
  gap: var(--cc-space-5);
  height: 100%;
  max-width: var(--ccs-nav-max);
  margin-inline: auto;
  padding-inline: var(--cc-space-5);
}

/* --- Brand --------------------------------------------------------------
   Wordmark in the display face with a drawn hook-and-loop mark. Explicit
   dimensions so the logo cannot shift layout as it paints. */
.ccs-brand {
  display: inline-flex;
  align-items: center;
  gap: var(--cc-space-2);
  text-decoration: none;
  color: var(--cc-color-text);
  flex: 0 0 auto;
  height: 44px;
}
.ccs-brand__mark {
  width: 26px;
  height: 26px;
  flex: 0 0 auto;
  color: var(--cc-color-brand);
}
.ccs-brand__name {
  font-family: var(--cc-font-display);
  font-size: 1.2rem;
  font-weight: var(--cc-weight-bold);
  letter-spacing: var(--cc-tracking-tight);
  white-space: nowrap;
}
.ccs-brand:hover .ccs-brand__name { color: var(--cc-color-brand-strong); }

/* --- Primary nav ---------------------------------------------------------
   Centred between the brand and the utility actions. */
.ccs-nav { display: flex; align-items: center; margin-inline: auto; }
.ccs-header__actions { display: flex; align-items: center; gap: var(--cc-space-1); flex: 0 0 auto; margin-left: auto; }
.ccs-nav__list {
  display: flex;
  align-items: center;
  gap: var(--cc-space-1);
  list-style: none;
  margin: 0;
  padding: 0;
}
.ccs-nav__item { display: flex; }

.ccs-nav__link,
.ccs-nav__trigger {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 44px;
  padding-inline: var(--cc-space-3);
  font-family: var(--cc-font-body);
  font-size: 0.95rem;
  font-weight: var(--cc-weight-medium);
  color: var(--cc-color-text);
  background: none;
  border: 0;
  border-radius: var(--cc-radius-sm);
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
}
.ccs-nav__link:hover,
.ccs-nav__trigger:hover { background: var(--cc-color-surface-subtle); }

/* Current section. A 2px rule under the label, not a coloured pill - the
   state reads in greyscale and does not turn nav into buttons. */
.ccs-nav__link[aria-current="page"],
.ccs-nav__item--current > .ccs-nav__trigger {
  font-weight: var(--cc-weight-semibold);
  box-shadow: inset 0 -2px 0 var(--cc-color-brand);
}

.ccs-nav__chev {
  width: 11px; height: 11px;
  flex: 0 0 auto;
  transition: transform var(--cc-duration-fast) var(--cc-ease-standard);
}
.ccs-nav__trigger[aria-expanded="true"] .ccs-nav__chev { transform: rotate(180deg); }

/* ==========================================================================
   3. MEGA MENU (desktop)
   ========================================================================== */

.ccs-mega {
  position: absolute;
  top: calc(100% - 4px);
  left: 50%;
  transform: translateX(-50%);
  width: max-content;
  max-width: min(920px, calc(100% - var(--cc-space-6)));
  background: var(--cc-color-surface);
  border: 1px solid var(--cc-color-border);
  border-radius: var(--cc-radius-lg);
  box-shadow: var(--cc-shadow-sm);
  padding: var(--cc-space-4);
  z-index: 70;
  /* Closed state. display:none would break the open animation and hide the
     panel from measurement, so visibility carries it - and visibility:hidden
     also removes the links from the tab order, which is the point. */
  visibility: hidden;
  opacity: 0;
  transition: opacity var(--cc-duration-fast) var(--cc-ease-standard),
              visibility var(--cc-duration-fast);
}
.ccs-nav__item.is-open > .ccs-mega { visibility: visible; opacity: 1; }

/* A hover bridge: the 6px gap between trigger and panel would otherwise close
   the menu when the pointer crosses it. */
.ccs-mega::before {
  content: "";
  position: absolute;
  inset: -10px 0 auto 0;
  height: 10px;
}

.ccs-mega__grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(190px, 1fr));
  gap: var(--cc-space-4);
}
.ccs-mega__grid--3 { grid-template-columns: repeat(3, minmax(190px, 1fr)); }

.ccs-mega__group { min-width: 0; }
.ccs-mega__title {
  display: flex;
  align-items: center;
  gap: var(--cc-space-2);
  margin: 0 0 var(--cc-space-1);
  padding: 0 var(--cc-space-2);
  font-size: var(--cc-text-xs);
  font-weight: var(--cc-weight-semibold);
  letter-spacing: var(--cc-tracking-wide);
  text-transform: uppercase;
  color: var(--cc-color-text-muted);
}
.ccs-mega__desc {
  margin: 0 0 var(--cc-space-2);
  padding: 0 var(--cc-space-2);
  font-size: var(--cc-text-xs);
  line-height: 1.45;
  color: var(--cc-color-text-muted);
}
.ccs-mega__list { list-style: none; margin: 0; padding: 0; }

.ccs-mega__link {
  display: block;
  padding: 7px var(--cc-space-2);
  border-radius: var(--cc-radius-sm);
  text-decoration: none;
  color: var(--cc-color-text);
  min-height: 44px;
}
.ccs-mega__link:hover { background: var(--cc-color-surface-subtle); }
.ccs-mega__link b {
  display: block;
  font-size: 0.9rem;
  font-weight: var(--cc-weight-medium);
  line-height: 1.3;
}
.ccs-mega__link span {
  display: block;
  font-size: var(--cc-text-xs);
  line-height: 1.35;
  color: var(--cc-color-text-muted);
  margin-top: 1px;
}
.ccs-mega__link:hover b { text-decoration: underline; text-decoration-thickness: 2px; }

.ccs-mega__foot {
  margin-top: var(--cc-space-3);
  padding-top: var(--cc-space-3);
  border-top: 1px solid var(--cc-color-border);
}
.ccs-mega__foot a {
  display: inline-flex;
  align-items: center;
  gap: var(--cc-space-2);
  min-height: 44px;
  padding-inline: var(--cc-space-2);
  font-size: 0.9rem;
  font-weight: var(--cc-weight-medium);
  color: var(--cc-color-brand-strong);
  text-decoration: none;
}
.ccs-mega__foot a::after {
  content: "\2192";
  transition: transform var(--cc-duration-base) var(--cc-ease-standard);
}
.ccs-mega__foot a:hover { text-decoration: underline; text-decoration-thickness: 2px; }
.ccs-mega__foot a:hover::after { transform: translateX(3px); }

/* ==========================================================================
   4. SEARCH + MENU CONTROLS
   ========================================================================== */

.ccs-search {
  display: inline-flex;
  align-items: center;
  gap: var(--cc-space-2);
  height: 40px;
  padding-inline: var(--cc-space-3);
  font-family: var(--cc-font-body);
  font-size: 0.9rem;
  color: var(--cc-color-text-secondary);
  background: var(--cc-color-surface);
  border: 1px solid var(--cc-color-border-control);
  border-radius: var(--cc-radius-md);
  cursor: pointer;
  white-space: nowrap;
}
.ccs-search:hover { border-color: var(--cc-color-text-secondary); color: var(--cc-color-text); }
.ccs-search__hint {
  font-family: var(--cc-font-mono);
  font-size: 0.7rem;
  color: var(--cc-color-text-muted);
  border: 1px solid var(--cc-color-border);
  border-radius: 3px;
  padding: 1px 5px;
}

/* Mobile-only icon button versions */
.ccs-iconbtn {
  display: none;
  align-items: center;
  justify-content: center;
  width: 44px; height: 44px;
  flex: 0 0 auto;
  color: var(--cc-color-text);
  background: none;
  border: 0;
  border-radius: var(--cc-radius-sm);
  cursor: pointer;
}
.ccs-iconbtn:hover { background: var(--cc-color-surface-subtle); }

/* ==========================================================================
   5. ICON LANGUAGE  (mask-image, inherits currentColor)
   Wave 1A contract: 24x24 grid, 1.5 stroke, round caps and joins, no fill.
   ========================================================================== */

.ccs-i {
  display: inline-block;
  flex: 0 0 auto;
  width: 18px; height: 18px;
  background-color: currentColor;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center;   mask-position: center;
  -webkit-mask-size: contain;      mask-size: contain;
}
.ccs-i--sm { width: 14px; height: 14px; }
.ccs-i--lg { width: 22px; height: 22px; }

/* swatch + ruler - yarn & gauge */
.ccs-i--gauge { -webkit-mask-image: var(--ccs-ic-gauge); mask-image: var(--ccs-ic-gauge); }
/* stitch marks - stitches & shaping */
.ccs-i--stitch { -webkit-mask-image: var(--ccs-ic-stitch); mask-image: var(--ccs-ic-stitch); }
/* measurement frame - project planning */
.ccs-i--frame { -webkit-mask-image: var(--ccs-ic-frame); mask-image: var(--ccs-ic-frame); }
/* cost bars - colour & business */
.ccs-i--bars { -webkit-mask-image: var(--ccs-ic-bars); mask-image: var(--ccs-ic-bars); }
/* yarn skein - yarn guides */
.ccs-i--yarn { -webkit-mask-image: var(--ccs-ic-yarn); mask-image: var(--ccs-ic-yarn); }
/* hook - gauge & hooks guides */
.ccs-i--hook { -webkit-mask-image: var(--ccs-ic-hook); mask-image: var(--ccs-ic-hook); }
/* pattern brackets - stitches & patterns guides */
.ccs-i--pattern { -webkit-mask-image: var(--ccs-ic-pattern); mask-image: var(--ccs-ic-pattern); }
/* finished square - projects & finishing guides */
.ccs-i--project { -webkit-mask-image: var(--ccs-ic-project); mask-image: var(--ccs-ic-project); }
.ccs-i--search { -webkit-mask-image: var(--ccs-ic-search); mask-image: var(--ccs-ic-search); }
.ccs-i--menu { -webkit-mask-image: var(--ccs-ic-menu); mask-image: var(--ccs-ic-menu); }
.ccs-i--close { -webkit-mask-image: var(--ccs-ic-close); mask-image: var(--ccs-ic-close); }

:root {
  --ccs-ic-gauge: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='3' width='18' height='18' rx='1.5'/%3E%3Cpath d='M9 3v18M15 3v18M3 9h18M3 15h18'/%3E%3C/svg%3E");
  --ccs-ic-stitch: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 8v8M8 8v8M12 8v8M16 8v8M20 8v8'/%3E%3Cpath d='M2 12h20'/%3E%3C/svg%3E");
  --ccs-ic-frame: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='5' width='18' height='14' rx='1.5'/%3E%3Cpath d='M3 9h18'/%3E%3Cpath d='M7 13h4M7 16h8'/%3E%3C/svg%3E");
  --ccs-ic-bars: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 20V12M10 20V6M16 20V15M22 20H2'/%3E%3C/svg%3E");
  --ccs-ic-yarn: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='8'/%3E%3Cpath d='M6 8c4 2 8 4 11 8M8 5c3 3 6 6 8 11'/%3E%3C/svg%3E");
  --ccs-ic-hook: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 3v11a4 4 0 0 0 8 0'/%3E%3Cpath d='M17 14a2.5 2.5 0 0 1-5 0'/%3E%3Cpath d='M7 3h4'/%3E%3C/svg%3E");
  --ccs-ic-pattern: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 4H5v16h3M16 4h3v16h-3'/%3E%3Cpath d='M11 9h2M11 13h2'/%3E%3C/svg%3E");
  --ccs-ic-project: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='4' y='4' width='16' height='16' rx='1.5'/%3E%3Cpath d='M4 12h16M12 4v16'/%3E%3Cpath d='M7.5 7.5h1M15.5 15.5h1'/%3E%3C/svg%3E");
  --ccs-ic-search: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='m20 20-3.5-3.5'/%3E%3C/svg%3E");
  --ccs-ic-menu: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round'%3E%3Cpath d='M4 7h16M4 12h16M4 17h16'/%3E%3C/svg%3E");
  --ccs-ic-close: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round'%3E%3Cpath d='M6 6l12 12M18 6L6 18'/%3E%3C/svg%3E");
}

/* ==========================================================================
   6. MOBILE  (<= 900px)
   ========================================================================== */

.ccs-drawer__head,
.ccs-drawer__foot { display: none; }

@media (max-width: 900px) {
  .ccs-header { height: var(--ccs-header-h-mobile); }
  html { scroll-padding-top: calc(var(--ccs-header-h-mobile) + var(--cc-space-4)); }
  .ccs-header__inner { padding-inline: var(--cc-space-4); gap: var(--cc-space-2); }

  /* Search moves into the top bar. Previously it lived inside the drawer, so
     searching cost two taps and a menu the user did not want. */
  .ccs-search { display: none; }
  .ccs-iconbtn { display: inline-flex; }
  .ccs-nav { margin: 0; }

  /* --- Drawer ---------------------------------------------------------- */
  /* THE CLOSED DRAWER MUST NOT EXIST OUTSIDE THE VIEWPORT.
     It used to be parked at translateX(100%), which put a position:fixed
     element at x = 100vw..200vw. Two things follow, and together they are why
     this survived every check:
       - overflow-x:hidden on html/body CANNOT clip a fixed-position element,
         because a fixed box is laid out against the viewport, not against the
         scrolling ancestor;
       - a fixed box does not contribute to documentElement.scrollWidth, so
         every overflow test reported a clean 390 while the page was really
         twice that wide.
     Mobile browsers size the visual viewport to contain it and zoom out to
     fit, which renders the page narrow with blank space down the right.
     The drawer is now display:none when closed, so it has no geometry at all,
     and the open animation moves only on the Y axis - nothing ever extends
     past the right edge, at any point in the transition. */
  .ccs-nav__list {
    display: none;
    position: fixed;
    inset: var(--ccs-header-h-mobile) 0 0 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    background: var(--cc-color-canvas);
    border-top: 1px solid var(--cc-color-border);
    padding: var(--cc-space-3) var(--cc-space-4) var(--cc-space-8);
    overflow-y: auto;             /* the drawer scrolls, not the page */
    overscroll-behavior: contain;
    z-index: 90;
  }
  .ccs-nav__list.is-open {
    display: flex;
    animation: ccs-drawer-in var(--cc-duration-base) var(--cc-ease-standard);
  }
  @keyframes ccs-drawer-in {
    from { opacity: 0; transform: translateY(-6px); }
    to   { opacity: 1; transform: none; }
  }

  .ccs-nav__item { display: block; width: 100%; }
  .ccs-nav__item + .ccs-nav__item { border-top: 1px solid var(--cc-color-border); }

  .ccs-nav__link,
  .ccs-nav__trigger {
    width: 100%;
    height: auto;
    min-height: 52px;
    justify-content: flex-start;
    padding: var(--cc-space-3) var(--cc-space-2);
    font-size: 1.05rem;
    border-radius: 0;
  }
  .ccs-nav__trigger { justify-content: space-between; }
  .ccs-nav__link[aria-current="page"],
  .ccs-nav__item--current > .ccs-nav__trigger { box-shadow: inset 3px 0 0 var(--cc-color-brand); }

  /* Mega menu becomes an in-flow accordion panel. */
  .ccs-mega {
    position: static;
    top: auto;
    left: auto;
    transform: none;
    width: auto;
    max-width: none;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    padding: 0 0 var(--cc-space-3);
    background: none;
    visibility: visible;
    opacity: 1;
    display: none;              /* collapsed: progressive disclosure */
  }
  .ccs-nav__item.is-open > .ccs-mega { display: block; }
  .ccs-mega::before { content: none; }
  .ccs-mega__grid, .ccs-mega__grid--3 { grid-template-columns: 1fr; gap: 0; }

  /* Second-level accordion: the four category groups inside each menu. */
  .ccs-mega__group { border-top: 1px solid var(--cc-color-border); }
  .ccs-mega__group:first-child { border-top: 0; }
  .ccs-mega__title {
    display: flex;
    width: 100%;
    align-items: center;
    gap: var(--cc-space-3);
    min-height: 48px;
    margin: 0;
    padding: var(--cc-space-2) var(--cc-space-2);
    font-size: 0.8rem;
    color: var(--cc-color-text);
    background: none;
    border: 0;
    cursor: pointer;
    text-align: left;
  }
  .ccs-mega__title .ccs-mega__chev { margin-left: auto; transition: transform var(--cc-duration-fast) var(--cc-ease-standard); }
  .ccs-mega__group.is-open .ccs-mega__chev { transform: rotate(180deg); }
  .ccs-mega__desc { display: none; }
  .ccs-mega__list { display: none; padding-bottom: var(--cc-space-2); }
  .ccs-mega__group.is-open .ccs-mega__list { display: block; }
  .ccs-mega__link { padding: var(--cc-space-2) var(--cc-space-4); min-height: 48px; }
  .ccs-mega__link span { display: none; }   /* descriptions off on mobile */
  .ccs-mega__foot { margin: 0; padding: var(--cc-space-2) var(--cc-space-2) 0; }
}

@media (min-width: 901px) {
  .ccs-mega__chev { display: none; }
  /* Desktop group titles are headings, not buttons. */
  .ccs-mega__title { pointer-events: none; }
}

/* Scroll lock while the drawer is open. */
body.ccs-menu-open { overflow: hidden; }

/* ==========================================================================
   7. BREADCRUMB
   ========================================================================== */

.ccs-breadcrumbs {
  max-width: var(--cc-container-content);
  margin-inline: auto;
  padding: var(--cc-space-4) var(--cc-space-5) 0;
  font-size: var(--cc-text-sm);
}
.ccs-breadcrumbs ol {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 var(--cc-space-2);
  list-style: none;
  margin: 0;
  padding: 0;
}
.ccs-breadcrumbs li { display: flex; align-items: center; gap: var(--cc-space-2); }
.ccs-breadcrumbs li + li::before { content: "\203A"; color: var(--cc-color-text-muted); }
.ccs-breadcrumbs a {
  display: inline-flex;
  align-items: center;
  min-height: 32px;               /* clears the 24px target minimum */
  color: var(--cc-color-text-secondary);
  text-decoration: none;
}
.ccs-breadcrumbs a:hover { color: var(--cc-color-text); text-decoration: underline; }
.ccs-breadcrumbs [aria-current="page"] {
  display: inline-flex;
  align-items: center;
  min-height: 32px;
  color: var(--cc-color-text);
  font-weight: var(--cc-weight-medium);
}

/* ==========================================================================
   8. FOOTER
   ========================================================================== */

.ccs-footer {
  margin-top: var(--cc-space-8);
  background: var(--cc-color-surface);
  border-top: 1px solid var(--cc-color-border);
}
.ccs-footer__inner {
  max-width: var(--ccs-nav-max);
  margin-inline: auto;
  padding: var(--cc-space-7) var(--cc-space-5) var(--cc-space-5);
}
.ccs-footer__top {
  display: grid;
  gap: var(--cc-space-6);
  grid-template-columns: minmax(240px, 1.4fr) repeat(4, minmax(140px, 1fr));
}
@media (max-width: 1023px) { .ccs-footer__top { grid-template-columns: repeat(2, minmax(0,1fr)); } }
@media (max-width: 599px)  { .ccs-footer__top { grid-template-columns: 1fr; gap: var(--cc-space-5); } }

.ccs-footer__brand { max-width: 40ch; }
@media (max-width: 1023px) { .ccs-footer__brand { grid-column: 1 / -1; max-width: none; } }
.ccs-footer__blurb {
  margin: var(--cc-space-3) 0 0;
  font-size: var(--cc-text-sm);
  line-height: 1.55;
  color: var(--cc-color-text-secondary);
}
.ccs-footer__social {
  display: flex;
  gap: var(--cc-space-2);
  margin-top: var(--cc-space-4);
  padding: 0;
  list-style: none;
}
.ccs-footer__social a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px; height: 44px;     /* was well under the target minimum */
  color: var(--cc-color-text-secondary);
  border: 1px solid var(--cc-color-border);
  border-radius: var(--cc-radius-md);
}
.ccs-footer__social a:hover { color: var(--cc-color-text); border-color: var(--cc-color-border-control); }

/* UNAVOIDABLE LEGACY DEFENCE.
   These four labels are <h2>, and main.css (plus the duplicated inline block)
   carry `h2 { font-size: clamp(1.4rem,5.5vw,2rem) !important; line-height:
   ... !important }` under @media (max-width:768px). No amount of specificity
   beats !important, so the footer headings rendered at 22px in the display
   serif instead of a 12px label. The only fix short of editing main.css - which
   Wave 1B deliberately does not touch, to stay reversible - is to answer in
   kind, scoped to this one class. Remove these when main.css is cleaned up. */
.ccs-footer__title {
  margin: 0 0 var(--cc-space-2);
  font-family: var(--cc-font-body) !important;
  font-size: var(--cc-text-xs) !important;
  line-height: 1.4 !important;
  font-weight: var(--cc-weight-semibold);
  letter-spacing: var(--cc-tracking-wide);
  text-transform: uppercase;
  color: var(--cc-color-text-muted);
}
.ccs-footer__list { list-style: none; margin: 0; padding: 0; }
.ccs-footer__list a {
  display: flex;
  align-items: center;
  min-height: 40px;              /* every footer link now clears 24px */
  font-size: 0.9rem;
  color: var(--cc-color-text-secondary);
  text-decoration: none;
}
.ccs-footer__list a:hover { color: var(--cc-color-text); text-decoration: underline; text-decoration-thickness: 2px; }

.ccs-footer__bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--cc-space-2) var(--cc-space-4);
  margin-top: var(--cc-space-6);
  padding-top: var(--cc-space-4);
  border-top: 1px solid var(--cc-color-border);
  font-size: var(--cc-text-sm);
  color: var(--cc-color-text-muted);
}
.ccs-footer__bottom a {
  display: inline-flex;
  align-items: center;
  min-height: 40px;
  color: var(--cc-color-text-secondary);
  text-decoration: none;
}
.ccs-footer__bottom a:hover { color: var(--cc-color-text); text-decoration: underline; }
.ccs-footer__copy { margin: 0; margin-right: auto; }

/* ==========================================================================
   9. FOCUS  — inherits the Wave 1A two-ring indicator
   ========================================================================== */

.ccs-brand:focus-visible,
.ccs-nav__link:focus-visible,
.ccs-nav__trigger:focus-visible,
.ccs-mega__link:focus-visible,
.ccs-mega__title:focus-visible,
.ccs-mega__foot a:focus-visible,
.ccs-search:focus-visible,
.ccs-iconbtn:focus-visible,
.ccs-breadcrumbs a:focus-visible,
.ccs-footer__list a:focus-visible,
.ccs-footer__social a:focus-visible,
.ccs-footer__bottom a:focus-visible {
  outline: var(--cc-focus-outer-width) solid var(--cc-color-focus);
  outline-offset: var(--cc-focus-offset);
  box-shadow: 0 0 0 var(--cc-focus-inner-width) var(--cc-color-focus-inner);
  border-radius: var(--cc-radius-sm);
}
@media (forced-colors: active) {
  .ccs-nav__trigger:focus-visible,
  .ccs-nav__link:focus-visible,
  .ccs-mega__link:focus-visible { outline: 3px solid CanvasText; box-shadow: none; }
}

/* ==========================================================================
   10. MOTION + PRINT
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  .ccs-nav__list, .ccs-mega, .ccs-nav__chev, .ccs-mega__chev,
  .ccs-mega__foot a::after { transition: none !important; }
  .ccs-nav__list.is-open { animation: none !important; }
}

@media print {
  .ccs-header, .ccs-footer, .ccs-search, .ccs-iconbtn { display: none !important; }
  .ccs-breadcrumbs { padding-inline: 0; }
  html { scroll-padding-top: 0; }
}

/* ==========================================================================
   11. CONTENT RESPONSIVENESS
   Tables and diagrams use the legacy .data-table / .figure__scroll class names
   from the existing article template. These rules belong with that template
   and should move when it is rebuilt; they live here because shell.css is
   already on every page and this needs no extra request.
   ========================================================================== */

/* --- Diagrams ------------------------------------------------------------
   Every diagram is an SVG declared at 760-1120px and was locked to that width
   inside a scroll region, so on a 390px phone the reader saw a third of it
   through a keyhole. They now scale to fit their column and never produce a
   sideways scrollbar. Scaling a 960px diagram into 350px does make its labels
   too small to read, which is why each figure carries a full-size link - the
   file is an SVG, so the browser opens it zoomable and infinitely sharp. */
.figure__scroll { overflow-x: auto; }
.figure__scroll img,
.figure__scroll svg,
.figure img,
.figure svg {
  max-width: 100%;
  height: auto;
}

.figure__fullsize {
  display: inline-flex;
  align-items: center;
  gap: var(--cc-space-2);
  min-height: 40px;
  font-size: var(--cc-text-sm);
  color: var(--cc-color-brand-strong);
  text-decoration: none;
}
.figure__fullsize::after { content: "\2197"; }
.figure__fullsize:hover { text-decoration: underline; text-decoration-thickness: 2px; }
.figure__fullsize:focus-visible {
  outline: var(--cc-focus-outer-width) solid var(--cc-color-focus);
  outline-offset: var(--cc-focus-offset);
  box-shadow: 0 0 0 var(--cc-focus-inner-width) var(--cc-color-focus-inner);
  border-radius: var(--cc-radius-sm);
}

/* --- Tables --------------------------------------------------------------
   Below 600px a 5-column reference table cannot be read by panning a 350px
   window across 650px of content. Each row becomes a card and each cell is
   introduced by its own column heading, taken from data-label. Nothing is
   hidden and no horizontal scrolling is needed. */
/* main.css sets `.table-scroll > .data-table { min-width: max-content }`,
   which forbids the table from ever fitting its column - it is what produced a
   scrollbar even when the table was only 5px too wide, and it fought the
   stacked layout on phones. Letting the table fit and wrap is better than a
   sideways scroll at every width; the wrapper stays as a safety net for a
   table that genuinely cannot compress. */
.table-scroll > table.data-table { min-width: 0; width: 100%; }
.data-table td, .data-table th { overflow-wrap: break-word; }

/* Nothing on the page should be able to set the page width. */
.form__hint, .cc-hint { overflow-wrap: anywhere; }

/* A page-end CTA is `<a class="btn">Long label <span>-&gt;</span></a>`. The
   label does not wrap, so on a 320-360px screen the trailing arrow was pushed
   past the right edge of both the button and the viewport. */
.btn { max-width: 100%; }
@media (max-width: 640px) {
  .btn { white-space: normal; overflow-wrap: anywhere; }
}

/* The stitch counter's project bar lays label, select and hint out as three
   flex items in a row, so on a narrow phone the hint is pushed past the right
   edge of its own label - it was still 2px outside the viewport at 360px.
   The same fix exists on fix/mobile-nav-offscreen, which is not merged;
   duplicating it here keeps this branch self-sufficient, and the two produce
   the same result if both ever land. */
@media (max-width: 640px) {
  .project-bar { flex-direction: column; align-items: stretch; gap: 0.75rem; }
  .project-select-label { flex-direction: column; align-items: stretch; gap: 0.35rem; }
  .project-select-label select { min-width: 0; width: 100%; min-height: 44px; }
  .project-select-label .form__hint { max-width: 100%; }
  .project-actions { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .project-actions .btn { width: 100%; justify-content: center; }
}

@media (max-width: 599px) {
  .table-scroll {
    overflow-x: visible;
    border: 0;
    padding: 0;
  }
  .table-scroll > table.data-table { min-width: 0; width: 100%; }
  .data-table {
    display: block;
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
  }
  .data-table thead {              /* headings move into each cell instead */
    position: absolute;
    width: 1px; height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .data-table tbody { display: block; }
  .data-table tbody tr {
    display: block;
    margin-bottom: var(--cc-space-3);
    padding: var(--cc-space-1) var(--cc-space-3);
    background: var(--cc-color-surface);
    border: 1px solid var(--cc-color-border);
    border-radius: var(--cc-radius-md);
  }
  .data-table tbody td,
  .data-table tbody th {
    display: flex;
    flex-wrap: wrap;                 /* a long value drops to its own line */
    gap: 0 var(--cc-space-4);
    align-items: baseline;
    justify-content: space-between;
    width: auto;
    min-width: 0;
    padding: var(--cc-space-2) 0;
    border: 0;
    border-bottom: 1px solid var(--cc-color-border);
    text-align: right;
  }
  .data-table tbody tr > *:last-child { border-bottom: 0; }
  .data-table tbody td[data-label]::before,
  .data-table tbody th[data-label]::before {
    content: attr(data-label);
    flex: 0 1 auto;
    min-width: 0;
    max-width: 55%;
    font-size: var(--cc-text-sm);
    font-weight: var(--cc-weight-semibold);
    color: var(--cc-color-text-secondary);
    text-align: left;
  }
  /* A row whose cells carry no label has nothing to stack against. */
  .data-table tbody td:not([data-label]) { display: block; text-align: left; }

  /* Zebra striping tints the cells, not the card, so on alternate rows the
     padding stayed white and the stripe looked like a mistake. Cards already
     separate the rows, so the stripe has no job here. */
  .data-table tbody tr:nth-child(even) td,
  .data-table tbody tr:nth-child(even) th,
  .data-table tbody tr:hover td { background: transparent; }
}
