/* ==========================================================================
   08 PROCESS — the page's only light band. Not five numbered circles on a
   line: a depth scale. The five steps sit on one graduated axis and only the
   two that move material carry a reading. Amber may fill a shape here but may
   never set text — on bone it measures 1.9:1. 0 images.
   ========================================================================== */

.process {
  position: relative;
  background: var(--surface-invert);
  color: var(--text-on-invert);
}
.process::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: var(--grain-image);
  background-size: var(--grain-size) var(--grain-size);
  opacity: var(--grain-opacity-invert);
  pointer-events: none;
}

.process__inner { position: relative; z-index: var(--z-content); }

/* the light band flips every ink in the annotation layer */
.process .sec-title { color: var(--text-on-invert); }
.process .sec-lead { color: var(--text-on-invert-muted); }
.process .sec-spec { color: var(--text-on-invert-muted); }
.process .sec-spec b { color: var(--text-on-invert-accent); }
.process .eyebrow { color: var(--text-on-invert-muted); --bracket-color: var(--border-on-invert-strong); }
.process .eyebrow__idx { color: var(--text-on-invert); }
/* the light band recolours the tick language locally — the composed rules are
   now declared per-element, so the inks a section sets are the inks it gets */
.process {
  --tick-ink: var(--tick-ink-invert);
  --tick-ink-major: var(--tick-ink-invert-major);
}

/* --------------------------------------------------------------------------
   THE SCALE
   -------------------------------------------------------------------------- */
.process__steps {
  position: relative;
  display: grid;
  gap: var(--space-lg);
}

/* THE AXIS AT NARROW WIDTHS. Below 900 the scale used to disappear entirely —
   no axis, no graduations — which removed the clearest statement of the
   positioning on the width most visitors use. Same tick construction as the
   stat band and the desktop axis, stood on end and run through the marker
   gutter; the gap is bridged so the axis is continuous between steps.
   */
.process__steps::before {
  content: "";
  position: absolute;
  z-index: var(--z-below);
  inset-block: 0;
  inset-inline-start: 0;
  width: var(--marker-dot-lg);
  background: var(--tick-rule-vertical);
  background-position-x: calc(var(--marker-dot-lg) / 2);
}

.process__step {
  display: grid;
  /* a fixed gutter, not auto: an auto column sizes to the marker in THAT step,
     so the small dots and the large ones would sit on different axes */
  grid-template-columns: var(--marker-dot-lg) minmax(0, 1fr);
  grid-template-areas:
    "marker depth"
    "marker title"
    "marker desc";
  column-gap: var(--space-md);
  align-items: center;
}


.process__depth {
  grid-area: depth;
  font-family: var(--font-mono);
  font-size: var(--text-spec);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-mono-tight);
  color: var(--text-on-invert-accent);
}
.process__depth:empty { display: none; }

.process__marker {
  grid-area: marker;
  width: var(--marker-dot);
  height: var(--marker-dot);
  border-radius: var(--radius-round);
  background: var(--surface-invert-ink);
  align-self: center;
  justify-self: center;
  transition: transform var(--dur-fast) var(--ease-lift);
}
.process__step--major .process__marker {
  width: var(--marker-dot-lg);
  height: var(--marker-dot-lg);
  background: var(--surface-accent);
}
.process__step:hover .process__marker { transform: scale3d(var(--scale-media-hover), var(--scale-media-hover), 1); }

.process__title {
  grid-area: title;
  display: flex;
  align-items: baseline;
  gap: var(--space-2xs);
  font-size: var(--text-h4);
  color: var(--text-on-invert);
  margin-block-end: var(--space-3xs);
}
.process__idx {
  font-family: var(--font-mono);
  font-size: var(--text-label);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-mono-label);
  color: var(--text-on-invert-muted);
}

.process__desc {
  grid-area: desc;
  font-size: var(--text-body-sm);
  line-height: var(--leading-body);
  color: var(--text-on-invert-muted);
}

.process__foot {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-sm);
  margin-block-start: var(--space-stack);
  padding-block-start: var(--space-md);
}
.process__foot::before {
  content: "";
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  height: var(--tick-rule-h);
  background: var(--tick-rule);
}
.process__foot-note { font-size: var(--text-body-sm); color: var(--text-on-invert-muted); }

.process :focus-visible { outline-color: var(--focus-ring-color-invert); }

@media (min-width: 900px) {
  /* four rows: reading · marker on the axis · title · description.
     subgrid keeps all five titles and descriptions on one baseline; without
     it they auto-size per column and read as a mistake rather than a stagger. */
  /* the track count follows the step count. A five-track scale carrying four
     steps insets the first marker and leaves a quarter of the axis bare after
     the last, which reads as a missing step rather than as a scale. */
  .process__steps {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    grid-template-rows: auto var(--marker-dot-lg) auto auto;
    column-gap: var(--grid-gap);
    row-gap: var(--space-2xs);
  }
  /* The track count follows the step count, and it is stated in the markup
     rather than counted with :has(). Firefox has no :has() before 121 and
     Firefox 115 ESR is still the managed-desktop build; there the selector is
     invalid, the whole rule is dropped, a five-step scale keeps four tracks
     and .process__step:nth-child(5) below asks for a fifth column that does
     not exist — an implicit track, the axis short by a fifth, and the last
     step off the end of it. A class cannot fail that way in any engine. */
  .process__steps--5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  .process__step {
    grid-row: 1 / span 4;
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: subgrid;
    grid-template-areas: "depth" "marker" "title" "desc";
    text-align: center;
    justify-items: center;
  }
  .process__step:nth-child(1) { grid-column: 1; }
  .process__step:nth-child(2) { grid-column: 2; }
  .process__step:nth-child(3) { grid-column: 3; }
  .process__step:nth-child(4) { grid-column: 4; }
  .process__step:nth-child(5) { grid-column: 5; }

  /* the axis itself: same tick construction as the stat band, running the
     full width of the scale behind the markers */
  .process__steps::before {
    position: static;
    grid-column: 1 / -1;
    grid-row: 2;
    align-self: center;
    width: auto;
    height: var(--tick-rule-h);
    background: var(--tick-rule);
    background-position: 0 0;
  }

  .process__depth { align-self: end; padding-block-end: var(--space-2xs); }
  .process__depth:empty { display: block; }
  .process__title { justify-content: center; margin-block-end: 0; }
  .process__foot { justify-content: center; text-align: center; }
}

/* --------------------------------------------------------------------------
   NO ROW SUBGRID — Chrome before 117, Safari before 16. Firefox has had it
   since 71 and is not affected.
   Without it `grid-template-rows: subgrid` is dropped and the step becomes its
   own four-row grid inside a four-row span of the scale's. The scale's row 2
   still holds the continuous axis, but the step's marker row no longer lines
   up with it, so the rule crosses the titles and the markers sit off it — the
   one thing this section must not do, because the axis IS the argument.
   The fallback keeps the columns and the readings and drops the continuous
   rule: five markers, no line between them. The empty depth line is reserved
   rather than removed so the markers still land on one level across the row.
   -------------------------------------------------------------------------- */
@supports not (grid-template-rows: subgrid) {
  @media (min-width: 900px) {
    .process__steps { grid-template-rows: auto; }
    .process__steps::before { content: none; }
    .process__step {
      grid-row: auto;
      grid-template-rows: auto var(--marker-dot-lg) auto auto;
      /* the step is stretched by the tallest step in the row, and a grid
         container distributes that free space across its auto tracks — which
         put every step's marker at a different height even after the reading
         line was reserved. Packed to the start, the tracks are content-sized
         and only the reading line varies. */
      align-content: start;
    }
    /* Measured out rather than calculated: a hidden non-breaking space gives
       the empty reading exactly one line box at this element's own font-size
       and line-height, so the reservation cannot drift from --text-spec. */
    .process__depth:empty { display: block; visibility: hidden; }
    .process__depth:empty::before { content: "\00a0"; }
  }
}

/* ==========================================================================
   10 RECENT WORK — the photograph IS the section (M1, refs 01 and 06).
   100vw, no container, no chamfer, no inset frame, no card. Three unequal
   tiles butted with a 1px seam, an 11px mono label parked bottom-left, and
   zero padding at the foot so the band butts §11 directly. 3 images.
   ========================================================================== */

.work {
  background: var(--surface-page);
  padding-block: var(--space-section) 0;
  overflow: hidden;
}

.work__head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-md);
  margin-block-end: var(--space-stack);
}

.work__social {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-md);
  font-family: var(--font-mono);
  font-size: var(--text-caption);
  color: var(--text-muted);
}
.work__social a { transition: color var(--dur-fast) var(--ease-state); }
.work__social a:hover { color: var(--text-primary); }
.work__social-link { display: inline-flex; align-items: center; gap: var(--space-3xs); }

/* --------------------------------------------------------------------------
   THE BAND — the one place on the page where an image is not in a box
   -------------------------------------------------------------------------- */
/* NO 100vw HERE. The band is already a direct child of <section class="work">,
   which is a child of <body> and therefore exactly as wide as the page — so
   `width: auto` IS the full bleed, in every engine, with no arithmetic to get
   wrong. The 100vw version measured 1500px against a 1485px body on Windows
   Chrome and hung 7.5px off each edge, where .work's overflow: hidden cut 15px
   of photograph off the band and shifted both seams; above --width-page it
   overhung by half the excess. Neither is visible until it is measured, which
   is why it survived. */
.workband {
  display: grid;
  gap: var(--bleed-seam);
  background: var(--bleed-seam-ink);
}

.workband__tile {
  position: relative;
  display: block;
  overflow: hidden;
  aspect-ratio: var(--ratio-bleed);
  background: var(--surface-media);
}
.workband__tile picture { display: contents; }
.workband__tile img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--dur-slow) var(--ease-entrance);
}
.workband__tile::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--scrim-bleed);
  pointer-events: none;
}
.workband__tile:hover img { transform: scale3d(var(--scale-bleed-hover), var(--scale-bleed-hover), 1); }
.workband__tile:focus-visible { outline: none; box-shadow: var(--focus-ring-inset); }

.workband__label {
  position: absolute;
  z-index: var(--z-content);
  inset-block-end: var(--bleed-label-inset);
  /* the band bleeds to the viewport edge, so under viewport-fit=cover this
     label is the one piece of copy that can land under a landscape notch */
  inset-inline-start: max(var(--bleed-label-inset), env(safe-area-inset-left, 0px));
  max-width: calc(100% - var(--bleed-label-inset) * 2);
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  font-weight: var(--weight-medium);
  line-height: var(--leading-micro);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-on-media);
}
.workband__label b { color: var(--text-accent); font-weight: var(--weight-medium); }

@media (min-width: 768px) {
  .workband {
    grid-template-columns: 38fr 34fr 28fr;
    height: var(--bleed-band-h);
  }
  .workband__tile { aspect-ratio: auto; height: 100%; }
  /* one tile, one track. The 3-track grid puts a lone tile in a 38fr column
     and leaves two thirds of a 100vw band empty. */
  .workband--single { grid-template-columns: minmax(0, 1fr); }
}

/* ==========================================================================
   03 LIMITS — the page's spine. One plate divided into four cells, not four
   cards: a plate is not a link and must not behave like one. Every card on
   this site lifts on hover; this block deliberately does not, which is most
   of what stops it reading as a card grid. 0 images.
   ========================================================================== */

.refusal { background: var(--surface-page); overflow: hidden; }

/* A real surface step, not a 4/255 one: --surface-sunken on --surface-page is
   invisible, and the bleed variant strips the border, so the plate has to
   carry its own tone or it reads as loose text on the page ground. */
.refusal__plate {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  background: var(--surface-raised);
  border: var(--border-width-hair) solid var(--border-soft);
  border-radius: var(--radius-inset);
  clip-path: var(--chamfer-clip);
}

/* The accent is each cell's OPENING rule, never an inline-start bar: on a
   two-column plate that bar lands on the column seam and draws exactly the
   vertical divider docs/uniqueness.md move 3 killed on the stat band, while
   the first and third bars fall off the viewport edge under --bleed. */
.refusal__cell {
  display: grid;
  gap: var(--space-2xs);
  align-content: start;
  padding: var(--card-pad-lg);
  border-block-start: var(--border-width-bar) solid var(--surface-accent);
}

.refusal__idx {
  font-size: var(--text-spec);
  letter-spacing: var(--tracking-mono-label);
  color: var(--text-accent);
}
.refusal__claim {
  font-size: var(--text-h3);
  font-weight: var(--weight-display);
  line-height: var(--leading-snug);
  color: var(--text-primary);
}
.refusal__why {
  max-width: var(--width-measure);
  font-size: var(--text-body-sm);
  line-height: var(--leading-body);
  color: var(--text-muted);
}
.refusal__why a {
  color: var(--text-secondary);
  text-decoration: underline;
  text-decoration-color: var(--border-accent);
  text-underline-offset: var(--space-3xs);
  transition: color var(--dur-fast) var(--ease-state);
}
.refusal__why a:hover { color: var(--text-primary); }

.refusal__rule { margin-block-start: var(--space-md); }

/* The bleed variant: the plate crosses both container edges and loses its side
   borders and its chamfer (same exemption work.css takes for .workband — a
   100vw box has no visible corner to cut). The block-start and block-end
   hairlines stay, so the plate still closes against the page. */
/* The band is a direct child of <section class="refusal"> on every page that
   sets --bleed, and the section is a child of <body>, so it is already the
   full page width and needs no vw arithmetic at all. The previous
   `width: 100vw` overhung the viewport by half a scrollbar on Windows and by
   half the excess above --width-page, and .refusal's overflow: hidden was
   what hid it. Same correction as .workband; reasoning in base.css .bleed. */
.refusal--bleed .refusal__band { width: auto; margin-inline: 0; }
.refusal--bleed .refusal__plate {
  border-inline: 0;
  border-radius: var(--radius-sharp);
  clip-path: none;
}
/* the plate crosses both viewport edges, so its own padding is the only thing
   holding the copy clear of a landscape notch under viewport-fit=cover */
.refusal--bleed .refusal__cell {
  padding-inline: max(var(--card-pad-lg), var(--gutter));
  padding-inline: max(var(--card-pad-lg), var(--gutter), env(safe-area-inset-left, 0px)) max(var(--card-pad-lg), var(--gutter), env(safe-area-inset-right, 0px));
}

/* --------------------------------------------------------------------------
   THE LIGHT BAND. Every other page on the site carries exactly one tonal break
   — the bone Process band — and the city pages have no Process block, so they
   ran their whole length on one tone. The plate that takes it is this one: it
   is the page's spine, it has no hover state and no photograph, and it is the
   only block whose ink list is short enough to flip without re-inking a
   component. Construction copied from process.css: bone ground, grain at
   --grain-opacity-invert, every annotation ink swapped for its -on-invert pair.
   The accent stays a FILL here (the cell's opening rule) and never sets text —
   on bone it measures 1.9:1. docs/art-direction.md.
   -------------------------------------------------------------------------- */
.refusal--light {
  position: relative;
  background: var(--surface-invert);
  color: var(--text-on-invert);
  --tick-ink: var(--tick-ink-invert);
  --tick-ink-major: var(--tick-ink-invert-major);
  --chamfer-edge-ink: var(--chamfer-edge-ink-invert);
}
.refusal--light::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: var(--grain-image);
  background-size: var(--grain-size) var(--grain-size);
  opacity: var(--grain-opacity-invert);
  pointer-events: none;
}
.refusal--light > * { position: relative; z-index: var(--z-content); }

.refusal--light .sec-title { color: var(--text-on-invert); }
.refusal--light .sec-spec { color: var(--text-on-invert-muted); }
.refusal--light .sec-spec b { color: var(--text-on-invert-accent); }
.refusal--light .eyebrow { color: var(--text-on-invert-muted); --bracket-color: var(--border-on-invert-strong); }
.refusal--light .eyebrow__idx { color: var(--text-on-invert); }

.refusal--light .refusal__plate {
  background: var(--surface-invert-raised);
  border-color: var(--border-on-invert-strong);
}
.refusal--light .refusal__idx { color: var(--text-on-invert-accent); }
.refusal--light .refusal__claim { color: var(--text-on-invert); }
.refusal--light .refusal__why { color: var(--text-on-invert-muted); }
.refusal--light .refusal__why a {
  color: var(--text-on-invert);
  text-decoration-color: var(--text-on-invert-accent);
}
.refusal--light .refusal__why a:hover { color: var(--text-on-invert-accent); }

@media (min-width: 768px) {
  /* 2x2, never 4-up: the reasons run 20-50 words and are unequal, so four
     columns set the longest cell at eleven lines beside a three-line one.
     1fr rows even the pair: a one-line reason otherwise sits at half the
     height of its neighbour. In one column the rows stack, so they don't. */
  .refusal__plate { grid-template-columns: repeat(2, minmax(0, 1fr)); grid-auto-rows: 1fr; }

  /* THE COLUMN SEAM. At 1920 a cell is 960px wide and holds 572px of text, so
     without a seam the plate read as two rows of prose under two long accent
     rules rather than as one plate divided into four. This is a hairline in the
     plate's own border ink, not the accent divider docs/uniqueness.md move 3
     killed: it is the same edge the plate already draws around itself, carried
     inward. Rows need no seam — the accent opening rule already separates them. */
  .refusal__cell:nth-child(even) { border-inline-start: var(--border-width-hair) solid var(--border-soft); }
  .refusal--light .refusal__cell:nth-child(even) { border-inline-start-color: var(--border-on-invert-strong); }
}

/* --------------------------------------------------------------------------
   THE PLATE IS PLACED, NOT PRINTED. clip-path removes box-shadow outright, so
   on the bone variant the site's one light plate sat flat on the ground it was
   meant to lift off. --shadow-chamfer-invert is the drop-shadow pair made for
   a chamfered object on a light surface and was referenced nowhere until now;
   it goes on the band rather than the plate because a filter on a clipped
   element is applied after the clip, which is what makes the chamfer cast.
   -------------------------------------------------------------------------- */
.refusal--light .refusal__band { filter: var(--shadow-chamfer-invert); }

/* --------------------------------------------------------------------------
   THE HEAD AS THE PLATE'S FIRST CELL. Standing above the plate, the section
   head left #limits 741px tall around 374px of ink — 136px of bone over the
   eyebrow, 169px under the plate, and an empty 1180x290 beside a five-word h2
   — on the one block on the page that flips to bone, which made the emptiest
   block the brightest. Set as the plate's opening cell it becomes the block's
   first column and the accent opening rule runs unbroken across all three.
   -------------------------------------------------------------------------- */
.refusal--head-in-plate .refusal__head {
  max-width: none;
  margin-block-end: 0;
  padding: var(--card-pad-lg);
  border-block-start: var(--border-width-bar) solid var(--surface-accent);
}
/* the plate's own border is the boundary here, so the head does not draw the
   graduated tick rule .sec-head carries when it stands on the page ground */
.refusal--head-in-plate .refusal__head::before { content: none; }
.refusal--bleed .refusal__head { padding-inline: max(var(--card-pad-lg), var(--gutter)); }

@media (min-width: 768px) {
  /* While the plate is two columns wide the head spans them and the refusals
     take the row underneath: three columns of a 785px plate set 260px tracks
     and broke "two-year-old car." over four lines. Rows are auto here, not
     1fr — the 2x2 rule's even rows would otherwise stretch the head cell to
     the height of the refusals beside it and put the bone straight back. */
  .refusal--head-in-plate .refusal__plate { grid-auto-rows: auto; }
  .refusal--head-in-plate .refusal__head { grid-column: 1 / -1; }
}

@media (min-width: 1024px) {
  /* three equal columns: head, refusal, refusal. The 2x2 rule above cannot
     see the head, so it would have set the two refusals under it. */
  .refusal--head-in-plate .refusal__plate {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    grid-auto-rows: 1fr;
  }
  .refusal--head-in-plate .refusal__head { grid-column: auto; }
  /* every cell now opens a column, so every cell takes the seam — :nth-child
     (even) counted from the plate and with the head at index 1 it landed on
     the first refusal only */
  .refusal--head-in-plate .refusal__cell { border-inline-start: var(--border-width-hair) solid var(--border-soft); }
  .refusal--light.refusal--head-in-plate .refusal__cell { border-inline-start-color: var(--border-on-invert-strong); }
}

/* ==========================================================================
   14 FOOTER — dense four-column: Studio, Services, Service area, Hours.
   NAP identical to the quote panel and to the JSON-LD. 0 images.
   ========================================================================== */

.footer {
  background: var(--surface-sunken);
  padding-block: var(--space-lg) var(--space-lg);
}
.footer__rule { margin-block-end: var(--space-stack); }

.footer__top {
  display: grid;
  gap: var(--space-stack);
  padding-block-end: var(--space-stack);
  border-block-end: var(--border-width-hair) solid var(--border-hairline);
}


.footer__brand { display: grid; gap: var(--space-sm); align-content: start; }
.footer__mark {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  font-family: var(--font-display);
  font-size: var(--text-h3);
  font-weight: var(--weight-display);
  letter-spacing: var(--tracking-label);
  color: var(--text-primary);
}
/* the identity block is the one place the gauge is allowed to lead, so it runs
   at --brandmark-h rather than the header's --icon-md */
.footer__mark-icon { width: var(--brandmark-h); height: var(--brandmark-h); }
.footer__mark-word { white-space: nowrap; }
.footer__mark-dot { color: var(--text-accent); }
.footer__line { font-size: var(--text-body-sm); line-height: var(--leading-body); color: var(--text-muted); max-width: var(--width-prose); }

.footer__cols { display: grid; gap: var(--space-stack); }

.footer__col-head {
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-muted);
  margin-block-end: var(--space-xs);
}

.footer__list { display: grid; gap: var(--space-2xs); }
.footer__list a,
.footer__list span {
  font-size: var(--text-body-sm);
  display: inline-block;
}
.footer__list a {
  color: var(--text-muted);
  transition: color var(--dur-fast) var(--ease-state), transform var(--dur-fast) var(--ease-lift);
}
.footer__list a:hover { color: var(--text-primary); transform: translate3d(var(--space-3xs), 0, 0); }
/* A span in this list is a fact, not a destination — the address lines. It was
   inheriting the link colour and the link box, so it read as a target that did
   nothing on click. One step quieter is the whole difference. */
.footer__list span { color: var(--text-faint); }

.footer__area-more {
  margin-block-start: var(--space-2xs);
  max-width: var(--width-measure);
  font-size: var(--text-caption);
  line-height: var(--leading-body);
  color: var(--text-faint);
}

.footer__hours-row {
  display: flex;
  justify-content: space-between;
  gap: var(--space-sm);
  padding-block: var(--space-3xs);
  border-block-end: var(--border-width-hair) solid var(--border-hairline);
  font-family: var(--font-mono);
  font-size: var(--text-caption);
  color: var(--text-muted);
}
.footer__hours-row b { color: var(--text-secondary); font-weight: var(--weight-medium); }

.footer__bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
  padding-block-start: var(--space-md);
}
.footer__copy { font-size: var(--text-caption); color: var(--text-muted); }
.footer__social, .footer__legal { display: flex; flex-wrap: wrap; gap: var(--space-md); font-family: var(--font-mono); font-size: var(--text-caption); color: var(--text-muted); }
.footer__social a, .footer__legal a { transition: color var(--dur-fast) var(--ease-state); }
.footer__social a:hover, .footer__legal a:hover { color: var(--text-primary); }
.footer__social-link { display: inline-flex; align-items: center; gap: var(--space-3xs); }

.footer__disclaimer {
  margin-block-start: var(--space-sm);
  font-size: var(--text-micro);
  line-height: var(--leading-snug);
  color: var(--text-muted);
  max-width: var(--width-measure);
}

@media (min-width: 768px) {
  .footer__cols { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-lg); }
}
@media (min-width: 1024px) {
  .footer__top { grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); gap: var(--space-2xl); }
}
