/* ============================================================
   SILICA WORKS - featured work index
   ------------------------------------------------------------
   A quiet list of projects. Hovering a row steals height from
   its neighbours in inverse proportion to distance, so the list
   breathes around the cursor; the title swaps to its category in
   the page's display face, and three plates fan out behind it.

   Adapted from the silverpoint register, retuned for this page:
   paper ground, ink type, Söhne for the titles and Shadows Into Light for
   the category the way the "Who we are" mark uses it. Heights
   and plate transforms are written by js/featured.js; this file
   owns the resting state.
   ============================================================ */

.sw-featured {
  position: relative;
  /* The title, head row and list stack top to bottom, each sized
     to its own content, rather than the centred column .sw-section
     sets for the one-line sections. */
  display: flex;
  flex-direction: column;
  /* Top-aligned, not centred: the list is taller than a screen at
     small heights, and centring would push the CTA off the bottom
     of the section and under the fixed nav. */
  justify-content: flex-start;
  gap: 0;
  /* The content runs past one screen, so the 100vh min-height from
     .sw-section is not wanted here. */
  min-height: auto;
  /* 12rem of bottom clearance rather than .sw-section's 10rem - the
     CTA is the last thing in the section and the nav bar floats. */
  /* Top padding pulled in from clamp(6rem, 12vh, 9rem): the eyebrow
     row that used to sit above the title is gone, so the old value
     left the heading floating well down the section. */
  padding: clamp(3rem, 6vh, 4.5rem) 2.5rem 12rem;
  /* The plates fan wide, so they are clipped to the section rather
     than allowed to widen the page. */
  overflow: hidden;
}

.sw-featured-title {
  /* No header above it any more, so the title opens the section and
     does not need the gap that was clearing the eyebrow row. */
  margin-top: 0;
  /* The same bold the slider heading carried. The Söhne faces are
     declared as separate FAMILIES in styles.css (sohne-normal /
     -medium / -bold) rather than as weights of one family, so the
     family has to be named here - font-weight alone would leave this
     on Inter Tight and let the browser synthesize a fake bold. */
  font-family: "sohne-bold", "Inter Tight", sans-serif;
  font-weight: 800;
  text-transform: uppercase;
  /* Up from the clamp(2rem, 6vw, 4.5rem) the base title sets - this
     one opens the section on its own now, so it carries more size.

     The cap and the vw rate do different jobs here. The three words
     share one row until 1000px, so the RATE has to clear the
     narrowest row: at 8.6vw they were 3px apart around 1024px. The
     CAP only bites above ~1100px, where there is width to spare, so
     it can go well past the old 6.5rem without crowding anything.

     Pulled back a step from 7.6vw/8.5rem: the row was reading as
     the loudest thing on the page. The rate keeps its clearance at
     1024px, and the cap comes down where the spare width is. */
  font-size: clamp(2.5rem, 6.8vw, 7.25rem);

  /* The three words span the full measure: "Work" hard left, "showing"
     hard right, "worth" between them. space-between does the
     spreading, so the gap grows with the section rather than being
     set to a fixed value. */
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  /* The pill is taken out of the row and hung above it, so it cannot
     eat into the width the three words are sharing. */
  position: relative;
  /* The heavier face sets wider, so the tracking comes back in. A
     touch further now that it sets larger - tracking that reads as
     neutral at 72px looks loose at 104px. */
  letter-spacing: -0.04em;
  line-height: 1;
}

/* ------------------------------------------------------------
   The three title words
   ------------------------------------------------------------
   space-between on the heading pins "Work" left and "showing" right, and
   both hold there - no slide, no lean. The middle word is the only
   one that moves: js/featured.js tweens it from an offset start to
   its resting place between the two anchors as the section scrolls
   past. It is given its own transform and nothing else reads that
   transform, so the tween cannot fight the layout.
   ------------------------------------------------------------ */
.sw-ft-word {
  display: block;
  white-space: nowrap;
}

/* Either word may carry the draggable pill - the last word on the featured
   heading, the middle word on the archive one - and the pill is
   absolutely placed, so both are made containing blocks. Positioning
   against the word rather than the heading is what lets the pill
   track it, including while the middle word is mid-slide. */
.sw-ft-word--b,
.sw-ft-word--c {
  position: relative;
}

/* ------------------------------------------------------------
   "featured" - leans with the scroll
   ------------------------------------------------------------
   Scroll velocity skews the travelling word over - up or down,
   whichever way the page is going - and a spring rights it when the
   scrolling stops. The same lean the nav bar's marquee carries,
   minus the strip. The two anchors are deliberately left out of it:
   a leaning anchor is not holding still. js/featured.js drives it.
   ------------------------------------------------------------ */
/* No clip. The word never travels now - it only leans - so there is
   nothing to hide, and overflow: hidden would shave the glyph tops
   off at the top of the lean instead. */
/* All three words carry this wrapper now, so the skew has an element
   of its own and never shares a transform with the x-scrub.

   The wrappers are block, not inline-block. An inline-block sits on
   the baseline, and the line box around it then has to reserve the
   parent font's descender space underneath - about 0.2em of extra
   depth. Since the heading centres its items, that pushed the glyphs
   visibly high. block takes them out of baseline layout entirely, so
   all three words are 1em boxes and centre identically. */
.sw-ft-slide {
  display: block;
}

.sw-ft-slide > span {
  display: block;
  white-space: nowrap;
  /* The lean pivots on the baseline, so the word tips like type on a
     slope rather than shearing about its middle. */
  transform-origin: 50% 100%;
  will-change: transform;
}



/* Only the middle word is tweened - the first and last words are anchors and
   never move. will-change keeps it on its own layer for the length of
   the scroll rather than promoting and demoting each frame. */
.sw-ft-word--b {
  will-change: transform;
}

/* The wrap is the positioning context for the plates, so they
   centre on the rows rather than on the whole section. The head row
   that used to sit above it is gone - the list opens the block on
   its own now, so the clearance the head used to provide is carried
   here instead. */
.sw-index-wrap {
  position: relative;
  /* Generous air between the heading and the list. The heading sets
     very large, so the gap under it has to be large too or the index
     reads as welded to the title rather than as its own block. */
  margin-top: clamp(8rem, 18vh, 15rem);
}

.sw-index-list {
  position: relative;
  z-index: 1;
}

.sw-index-row {
  position: relative;
  display: grid;
  /* The year opens the row, the label closes it hard right. The
     year's track is sized to its content; the label takes the rest
     and sets flush to the right edge.

     The columns are ordered here rather than in the markup, so the
     DOM keeps the project's name ahead of its date - the reading
     order a screen reader wants, whichever way the row is drawn. */
  grid-template-columns: auto 1fr;
  align-items: center;
  column-gap: 1.25rem;
  /* The row height is animated from this measured base, so the
     resting state sets the rhythm. Kept tight so the list reads as
     a ruled index rather than a stack of banners. */
  padding: clamp(1.1rem, 1.9vw, 1.6rem) 0;
  /* A hairline under every row, so the list reads as a ruled index
     rather than floating titles. These are dividers BETWEEN rows
     only - the outer edges of the block are left open, so the list
     sits on the page rather than in a box.

     Left as the resting rule only - the hovered state draws its own
     ink line over the top of this one via ::after, so the two never
     fight over the same pixel row. */
  border-bottom: 1px solid #e8e8e4;
  cursor: pointer;
  /* The label swaps in place, so the row has to clip it */
  overflow: hidden;
  /* Flush left. The indent existed only to clear the accent bar that
     used to run down the left edge; with the bar gone the labels
     line up with the heading above them. */
  padding-left: 0;
}

/* The last row drops the STATIC hairline only. That rule is drawn at
   rest, so leaving it on would close the foot of the list in a hard
   line and put the block back in a box.

   Its hover rule is deliberately left alone: that one only appears
   under the cursor, so the last row answers a hover exactly like
   every row above it. */
.sw-index-row:last-child {
  border-bottom: 0;
}

/* ============================================================
   The row divider - ink wipes in from the left
   ------------------------------------------------------------
   Built on an ::after layer over the paper hairline. It animates
   transform only and leaves the row's height alone, so nothing
   here can shift the list under the cursor.
   ============================================================ */
.sw-index-row::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  /* The row still clips its overflow, so the rule sits on the last
     2px INSIDE the box rather than over the border itself - at -1px
     it would be clipped away entirely. It reads as one thicker rule
     regardless, since the hairline is directly under it. */
  bottom: 0;
  height: 2px;
  background: #14140f;
  pointer-events: none;
  z-index: 2;
  /* Scaled to nothing at rest and grown from its left edge, so the
     hovered row reads as being underlined by hand. scaleX on the
     compositor: no layout, no repaint of the hairline. */
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 0.5s cubic-bezier(0.22, 1, 0.36, 1);
}

.sw-index-row:hover::after {
  transform: scaleX(1);
}

/* The last row keeps its divider like every other row, so the list
   reads as evenly ruled all the way down. Only the static hairline
   is dropped from it (see .sw-index-row:last-child above) - that one
   is drawn at rest and would close the block off in a hard line,
   whereas this rule only appears under the cursor. */

/* Motion is decoration here - the divider is still fully drawn
   without it. */
@media (prefers-reduced-motion: reduce) {
  .sw-index-row::after {
    transition: none;
    transform: scaleX(1);
  }
}

/* No wash and no tint behind the rows - the list sits on the page's
   own ground, and the ink rule under each row is the only thing
   separating them. */

/* Both carry a positioning context of their own - the label for its
   accent rule, the meta for nothing in particular but kept level
   with it. There is no longer a wash underneath to stack against. */
.sw-ix-lab,
.sw-ix-meta {
  position: relative;
}

/* The two columns, swapped against the markup: year left, label
   right. */
.sw-ix-meta { order: 1; }
.sw-ix-lab {
  order: 2;
  /* The label column is the wide one, so the type has to be pushed
     to its far edge - without this it would set left inside a track
     running the width of the row. */
  text-align: right;
}

/* The index numerals are gone. The markup keeps them (they are
   aria-hidden, so nothing is read out twice) in case the list ever
   wants a numbered column back. */
.sw-ix-num {
  display: none;
}

/* The left-hand block: the year, with the project's tags stacked
   under it. Column, not row - the tags sit beneath the date rather
   than beside it, so the left edge reads as one small metadata
   group against the title opposite. */
.sw-ix-meta {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  /* Aligned to the top of the row rather than centred on it, so the
     year sits level with the title's first line however many lines
     the description opposite runs to. */
  justify-content: flex-start;
  align-self: start;
  gap: 0.6rem;
  text-align: left;
}

.sw-ix-cat,
/* The year sets in Shadows Into Light, the same face the row's
   category carries - so the two ends of the row speak in one voice
   instead of pairing a handwritten label with uppercase meta type.

   The face ships a single weight, so font-weight here would only get
   a synthesized fake bold. A light handwriting face also reads
   smaller and looser than a sans at the same size, so the year runs
   well above the 0.75rem it originally set at. */
.sw-ix-yr {
  font-family: "Shadows Into Light", "Inter Tight", cursive;
  font-weight: 400;
  font-size: 1.75rem;
  /* Lighter than the 0.025em the category labels carry. Handwritten
     figures are more easily confused than letters - a 3 thickened
     into an 8, a 6 into a 0 - and the stroke closes the counters
     that tell them apart. The size increase is what gives the year
     its presence; the stroke is kept to a hint of weight. */
  -webkit-text-stroke: 0.012em currentColor;
  /* Opened up rather than closed. Figures read as one number by
     grouping, and this face's letterforms nearly touch at the tight
     tracking the meta line used to set. */
  letter-spacing: 0.04em;
  text-transform: none;
  color: #14140f;
  white-space: nowrap;
}

/* ------------------------------------------------------------
   The tags
   ------------------------------------------------------------
   Small chamfered tags under the year. Filled in near-black rather
   than outlined: the lime rule that used to run under each title is
   gone, so these are now the only solid marks in a list that is
   otherwise all rules and type, and they anchor its right edge.
   ------------------------------------------------------------ */
.sw-ix-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}

/* Chamfered and filled, matching the cursor tag and the nav's
   corners - the same object family, so the tags read as part of the
   page's own furniture rather than generic pills.

   The notch is cut with clip-path, which border-radius cannot
   describe. It is smaller than the cursor's 11px because these boxes
   are a fraction of that size; a bevel scaled to the cursor would
   eat the corners entirely. A border cannot be used with clip-path
   (it would be sliced through), so the fill does the work. */
.sw-ix-tag {
  --sw-tag-notch: 6px;
  font-size: 0.625rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  background: #141414;
  color: #f4f4f2;
  border: 0;
  padding: 0.3rem 0.65rem;
  white-space: nowrap;
  line-height: 1;
  clip-path: polygon(
    var(--sw-tag-notch) 0,
    100% 0,
    100% calc(100% - var(--sw-tag-notch)),
    calc(100% - var(--sw-tag-notch)) 100%,
    0 100%,
    0 var(--sw-tag-notch)
  );
}

/* ------------------------------------------------------------
   The description
   ------------------------------------------------------------
   One quiet line under the title, set in the body face rather than
   either display face - it is the only running text in the row and
   should not compete with the label above it.
   ------------------------------------------------------------ */
.sw-ix-desc {
  /* The label sets at a display size; this resets to a fixed size
     rather than inheriting an em of it. Matched to .sw-section-body
     in styles.css - the "Who we are" copy - so all the running text
     on the page reads at one size. */
  font-size: 1.0625rem;
  font-family: "Inter Tight", sans-serif;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  line-height: 1.6;
  color: #76766f;
  margin-top: 0.7rem;
  /* The label box holds its title on one line; the description is
     running text and has to be let out of that. */
  white-space: normal;
  /* Held to a readable measure and pushed to the label's right edge,
     so it stacks under the title rather than running the full width
     of the row. */
  max-width: 34ch;
  margin-left: auto;
  /* Two lines at most, so a long line cannot change the row's
     height relative to its neighbours. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* The year holds the right edge on its own now that the category is
   hidden, so it sets at the same mid-grey as the numeral rather than
   the lighter tint it used when the two shared the column. */
.sw-ix-yr {
  /* Shadows Into Light ships no tabular figures, so the years cannot
     be relied on to measure alike - a fixed min-width is what keeps
     the right edge of the list a true column. Grown with the year's
     jump to 1.75rem and its opened tracking. */
  min-width: 5.25rem;
}

/* The category is the row's main label now, so repeating it in the
   meta column would print the same words twice on one line. Hidden
   outright rather than left to a hover rule - it is never wanted.
   The markup stays so the column can be restored if the label ever
   goes back to the project title. */
.sw-ix-cat {
  display: none;
}

/* The label box. Only one label shows now, so there is nothing to
   stack or clip - it is a plain line of type. */
.sw-ix-lab {
  position: relative;
  display: block;
  font-size: clamp(1.2rem, 2.4vw, 2.1rem);
  line-height: 1.1;
  white-space: nowrap;
}

/* The project title. No longer shown - the category is the row's
   label now - but kept in the markup and readable by screen readers
   and search engines, since it is the only place the project's real
   name appears. Not display:none, which would take it out of the
   accessibility tree along with the layout. */
.sw-lab-a {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.sw-lab-b {
  display: block;
  transform-origin: left center;
}

/* The row's label: the category, in Shadows Into Light - the same display
   accent the "Who we are" mark carries, so the list reads in the
   page's own voice rather than a second typeface. It sets small for
   its size, so it takes a bump to hold the line's weight.

   In flow, not absolute. With the title taken out of the layout this
   is the only thing left to give the row its height, so positioning
   it would collapse every row to its padding. */
.sw-lab-b {
  position: relative;
  /* Shrink to the word so the accent rule underneath measures the
     label and not the whole grid track. Being shrunk, it no longer
     answers to the column's text-align, so the auto margin is what
     pushes it to the right edge. */
  width: fit-content;
  margin-left: auto;
  font-family: "Shadows Into Light", "Inter Tight", cursive;
  /* The face ships a single weight, so asking for 700 would only get
     a synthesized fake bold. The stroke below is what adds the weight
     instead - it thickens the actual letterforms. */
  font-weight: 400;
  /* A light handwriting face reads smaller at a given size than the
     sans it replaced, so this still sets above 1em even with the
     row's base size brought down. */
  font-size: 1.45em;
  text-transform: none;
  letter-spacing: 0.01em;
  -webkit-text-stroke: 0.025em currentColor;
  color: #14140f;
  /* Kept as breathing room under the word now that the accent rule
     that used to sit here is gone - it stops the descenders the
     handwriting face swings low from touching the row's edge. */
  padding-bottom: 0.08em;
}

/* ------------------------------------------------------------
   The plates, exactly as the silverpoint register sets them: a
   4/5 box the script scatters from, scale 0 until the list is
   entered. Shifted to the right-hand end here, and painted OVER
   the rows so a hovered project's work covers the titles.
   ------------------------------------------------------------ */
.sw-index-preview {
  position: absolute;
  top: 50%;
  /* Left of centre, mirroring where the labels sit: they set hard
     right now, so the stack moved across to keep them readable
     rather than covering them. */
  left: 38%;
  transform: translate(-50%, -50%);
  /* Down from min(22rem, 40vw). The plates sit over the rows, so a
     smaller stack leaves more of the list readable behind them. */
  width: min(17rem, 30vw);
  aspect-ratio: 4 / 5;
  /* Above the rows */
  z-index: 3;
  pointer-events: none;
}

.sw-pv {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: scale(0);
  will-change: transform;
  background: #edede8;
  /* Bevelled on all eight sides at the same 14px the showreel
     (.sw-reveal-frame, css/intro.css) and the showcase plates
     (.sw-sc-frame, css/showcase.css) take, so every image on the
     page is cut the same way. */
  --sw-plate-notch: 14px;
  clip-path: polygon(
    var(--sw-plate-notch) 0,
    calc(100% - var(--sw-plate-notch)) 0,
    100% var(--sw-plate-notch),
    100% calc(100% - var(--sw-plate-notch)),
    calc(100% - var(--sw-plate-notch)) 100%,
    var(--sw-plate-notch) 100%,
    0 calc(100% - var(--sw-plate-notch)),
    0 var(--sw-plate-notch)
  );
  /* The white keyline is gone: it was a spread box-shadow, which is
     drawn from the rectangular border box and so would sit square
     behind the bevel and undo it. The plates separate on the drop
     alone now.

     drop-shadow rather than box-shadow for the same reason - a
     filter shadow is taken from the CLIPPED silhouette, so it
     follows all eight sides. Same reasoning as .sw-sc-frame. */
  filter: drop-shadow(0 18px 34px rgba(0, 0, 0, 0.16));
}

/* The per-row image is a touch affordance only - on pointer
   devices the fanned plates do this job. */
.sw-ix-media {
  display: none;
}

/* ------------------------------------------------------------
   Narrow screens - the fanned stack needs a pointer and room it
   does not have here, so it goes and each row carries its own
   image instead, revealed by tapping the row.
   ------------------------------------------------------------ */
@media (max-width: 1000px) {
  .sw-featured {
    /* Matched to the tighter desktop opening - 4rem here would have
       left more space above the title on a phone than on a laptop. */
    padding: 2.5rem 1.5rem 8rem;
  }

  /* The title wraps to two lines below about 500px. Holding it on one
     line would mean dropping to roughly 1.85rem - smaller than it set
     before it was enlarged - so it breaks instead. The tighter
     leading keeps the lines reading as one block rather than two
     stacked headings.

     The row also stacks here: at this width the title needs the whole
     measure, and holding the pill out to the right would squeeze the
     heading into a narrow column beside it. */
  .sw-featured-title {
    line-height: 0.95;
    flex-direction: column;
    align-items: flex-start;
    gap: 1rem;
  }

  /* Number and title on the first line with the year hard right,
     the image spanning both columns underneath. */
  .sw-index-row {
    grid-template-columns: 1fr auto;
    gap: 0 1rem;
    align-items: baseline;
    /* The row animates its own height open, so the inline height
       GSAP writes on desktop must not apply here. */
    height: auto !important;
    padding: 1rem 0;
  }

  /* The year drops a step and gives up its reserved column width.
     That width exists to hold a straight right edge down a wide
     list; at this width the year sits in an auto track beside a
     1fr label, so reserving 5.25rem only squeezes the title. */
  .sw-ix-yr {
    font-size: 1.4rem;
    min-width: 0;
  }

  /* The label may wrap at this width. */
  .sw-ix-lab {
    white-space: normal;
  }
  .sw-index-preview { display: none; }

  /* The label sets at its own size here rather than the 1.15em bump
     the desktop line carries - at phone widths the bump pushes a
     two-word category onto a second line.

     It also goes back to the left edge: the right-hand setting needs
     a wide row to read as a deliberate column, and at this width it
     would just look like ragged text against the year. */
  .sw-lab-b {
    font-size: 1em;
    margin-left: 0;
  }

  .sw-ix-lab {
    text-align: left;
  }

  /* The description goes back to the left edge with the title above
     it, and loses the measure cap - at this width the column is
     already narrower than 34ch. */
  .sw-ix-desc {
    margin-left: 0;
    max-width: none;
    /* Just under the body size here. .sw-section-body does not shrink
       on narrow screens, but this sits in a two-column row rather
       than a full-measure column, so it takes a small step down. */
    font-size: 1rem;
  }

  /* The year and its tags sit on one line here rather than stacked:
     the row is a two-column grid at this width and a tall left
     column would push the title's column out of line with it. */
  .sw-ix-meta {
    flex-direction: row;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 0.4rem;
  }

  /* The image panel. Collapsed to nothing until its row is open -
     grid-template-rows animates cleanly where height:auto cannot. */
  .sw-ix-media {
    display: grid;
    /* The full width of the row. The numeral column it used to start
       after is gone, so the label and the image now share the same
       left edge. */
    grid-column: 1 / -1;
    grid-template-rows: 0fr;
    /* No top margin while closed, so a shut row measures the same
       as it did before the panel existed. */
    margin-top: 0;
    transition:
      grid-template-rows 0.55s cubic-bezier(0.22, 1, 0.36, 1),
      margin-top 0.55s cubic-bezier(0.22, 1, 0.36, 1);
  }

  .sw-ix-media > img {
    /* The grid row is the thing being animated, so the image needs
       a zero min-height to actually collapse inside it. */
    min-height: 0;
    width: 100%;
    height: 100%;
    /* Deliberately short of filling the screen: an open row has to
       leave the rows either side of it in view, or the list stops
       reading as a list. A 4/3 crop capped at 38vh keeps the next
       title on screen even on a small phone. */
    aspect-ratio: 4 / 3;
    max-height: 38vh;
    object-fit: cover;
    display: block;
    background: #edede8;
    /* The touch stand-in for the fanned plates above, so it takes
       their bevel too - the same 14px cut as every other image on
       the page. */
    --sw-plate-notch: 14px;
    clip-path: polygon(
      var(--sw-plate-notch) 0,
      calc(100% - var(--sw-plate-notch)) 0,
      100% var(--sw-plate-notch),
      100% calc(100% - var(--sw-plate-notch)),
      calc(100% - var(--sw-plate-notch)) 100%,
      var(--sw-plate-notch) 100%,
      0 calc(100% - var(--sw-plate-notch)),
      0 var(--sw-plate-notch)
    );
    opacity: 0;
    transform: scale(1.03);
    transition:
      opacity 0.45s ease,
      transform 0.7s cubic-bezier(0.22, 1, 0.36, 1);
  }

  .sw-index-row.is-open .sw-ix-media {
    grid-template-rows: 1fr;
    margin-top: 1.1rem;
  }

  .sw-index-row.is-open .sw-ix-media > img {
    opacity: 1;
    transform: scale(1);
  }

  /* The open row's year marks itself, so the open state reads
     without relying on the image alone. It used to darken from grey
     to ink; the year now sets in full ink at rest, so that cue was
     doing nothing. Lime on paper is too pale to carry it at this
     size, so the year is underlined instead - ink on ink, and it
     cannot fail a contrast check. */
  .sw-index-row.is-open .sw-ix-yr {
    box-shadow: inset 0 -0.18em 0 var(--sw-accent, #d9ff3d);
    transition: box-shadow 0.4s cubic-bezier(0.22, 1, 0.36, 1);
  }
}

@media (hover: none), (pointer: coarse) {
  .sw-index-preview { display: none; }
  /* The row is a tap target now, so it keeps a pointer cursor and
     suppresses the tap highlight the reveal replaces. */
  .sw-index-row {
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
}

/* Motion-sensitive visitors get the panel opening with no travel */
@media (prefers-reduced-motion: reduce) {
  .sw-ix-media,
  .sw-ix-media > img {
    transition: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  /* The fanning plates are the list's only hover motion now, and
     they are pure decoration, so they go entirely. The rows keep
     their full resting treatment - none of it moves. */
  .sw-index-preview { display: none; }
  .sw-ix-yr { transition: none; }
}


/* ============================================================
   THE DARK GROUND
   ------------------------------------------------------------
   The featured index is the one section on the page with a ground
   of its own. Everything else is white; the footer is the accent
   green. That gave the scroll exactly one colour event, at the
   very end, and nothing tonal in between - seven white screens and
   then the green.

   This is the second event. It also does the work the section's
   content cannot yet do: this is the index of the studio's actual
   projects, and it should read as the centrepiece rather than as
   one more list on white.

   Inverting a section is not a filter - every rule that assumed
   ink-on-paper has to be restated, so they are all collected here
   rather than scattered as overrides through the file. The values
   are the same tokens the light version uses, swapped: paper
   becomes ink, ink becomes paper, and the two greys trade places.

   Kept as one block at the foot of the file so the inversion can
   be removed in one piece if the section goes back to white.
   ============================================================ */
.sw-featured {
  background: var(--sw-ink);
  /* The section's own bevelled edges are not wanted - this is a
     full-width band, and the page reads it as a change of ground
     rather than as a plate laid on the page. */
  color: var(--sw-paper);
}

/* The heading. Both anchors and the travelling word. */
.sw-featured .sw-ft-word {
  color: var(--sw-paper);
}

/* The row hairline. #e8e8e4 was a light grey on white; this is the
   same step away from the ground, in the other direction. */
.sw-featured .sw-index-row {
  border-bottom-color: #2b2b26;
}

/* The hover underline wipes in PAPER now, not ink - it has to read
   against the dark ground it is drawn on. */
.sw-featured .sw-index-row::after {
  background: var(--sw-paper);
}

/* The row's own type: the label at full paper, the meta a step
   down, exactly as the light version sets ink then grey. */
.sw-featured .sw-ix-num,
.sw-featured .sw-ix-lab,
.sw-featured .sw-lab-a,
.sw-featured .sw-lab-b,
.sw-featured .sw-ix-cat,
.sw-featured .sw-ix-yr {
  color: var(--sw-paper);
}

.sw-featured .sw-ix-desc {
  color: #9a9a92;
}

/* The category chips were ink boxes with paper type. On this ground
   that is the ground's own colour, so they invert too: paper box,
   ink type. They stay the one high-contrast mark in the row. */
.sw-featured .sw-ix-tag {
  background: var(--sw-paper);
  color: var(--sw-ink);
}

/* ============================================================
   "Our full capabilities" - same setting, softer ink
   ------------------------------------------------------------
   .sw-hww-title borrows .sw-featured-title for its face, weight,
   size and space-between spread, and keeps all of it. Everything
   structural lives in css/slider.css next to the section it
   belongs to; only the colour lives here, because this file loads
   after slider.css and the rule would otherwise lose to
   .sw-featured-title at equal specificity.

   ONLY the colour changes. #14140f is the page's ink and it is
   also the featured index's own GROUND - so at 98px in extrabold
   it puts a section's worth of background on the type, and it
   read as a slab rather than as a heading.

   #3f3f36 is a warm charcoal well off the ink: enough lighter to
   take the density out at this size, dark enough that the heading
   still reads as near-black rather than as grey type. It sits in
   the same warm-grey family as the body copy's #55554e, a couple
   of steps darker, so the page's greys stay one family rather
   than the heading inventing a neutral of its own. 10.63:1 on
   white, against the ink's 18.47:1.

   The face and weight are deliberately untouched - dropping to a
   lighter cut would break the pair, and the colour carries the
   softening on its own.

   THE SIZE IS STEPPED UP a little past .sw-featured-title's
   clamp(2.5rem, 6.8vw, 7.25rem). "Our full capabilities" is two
   short words against one long one, so at the inherited size it
   set 1028px of ink in a 1360px measure at 1440px - comfortable,
   with 332px of gap still to spend. 7.6vw takes some of that back
   and gives the heading more presence without crowding the row.

   The rate is what matters here, not the cap. The three words
   share one row down to 1000px, so the vw rate has to clear the
   NARROWEST row: at 1001px, 7.6vw sets 798px of ink in a 921px
   measure, leaving 123px of gap across two spaces - about 61px
   each. That is the tight end of what still reads as spread, and
   it is where this value is pinned. Going past it closes the row
   into a dense line.

   Sized by measurement, not by eye - if the wording changes
   materially, re-measure at 1001px before touching this. A long
   single word like "capabilities" is the constraint.

   It lives here rather than in css/slider.css with the rest of the
   title's structure for the same reason the colour does: this file
   loads after slider.css, so .sw-featured-title's own font-size
   would beat it there at equal specificity.
   ============================================================ */
.sw-hww-title {
  color: #3f3f36;
  font-size: clamp(2.75rem, 7.6vw, 8.25rem);
}

/* The words carry their own colour in the dark-ground block below,
   so the heading's colour alone does not reach them. */
.sw-hww-title .sw-ft-word {
  color: inherit;
}

/* Full black variant, used on home.html's capabilities title. */
.sw-hww-title.sw-hww-title--ink {
  color: #000;
}

/* ============================================================
   PAPER VARIANT - home.html
   ------------------------------------------------------------
   .sw-featured--paper takes the section back to the page's own
   ground, puts the title on the left and the year and tags on the
   right, and swaps the fanned plates for one picture that trails
   the pointer (the aperture page's selected-work preview; driven
   by the [data-work-pv] branch of js/featured.js).

   Every rule is scoped to the modifier, so index.html keeps the
   dark ground and the plates untouched. Kept at the foot of the
   file so it lands after the dark block it undoes.
   ============================================================ */
.sw-featured--paper {
  background: var(--sw-paper);
  color: var(--sw-ink);
}

.sw-featured--paper .sw-ft-word,
.sw-featured--paper .sw-ix-num,
.sw-featured--paper .sw-ix-lab,
.sw-featured--paper .sw-lab-a,
.sw-featured--paper .sw-lab-b,
.sw-featured--paper .sw-ix-cat,
.sw-featured--paper .sw-ix-yr {
  color: var(--sw-ink);
}

.sw-featured--paper .sw-index-row {
  border-bottom-color: #e8e8e4;
}

.sw-featured--paper .sw-index-row::after {
  background: var(--sw-ink);
}

.sw-featured--paper .sw-ix-desc {
  color: #76766f;
}

.sw-featured--paper .sw-ix-tag {
  background: #141414;
  color: #f4f4f2;
}

/* Title left, info right - the reverse of the base setting. */
.sw-featured--paper .sw-index-row {
  grid-template-columns: minmax(0, 1fr) auto;
}

.sw-featured--paper .sw-ix-lab {
  order: 1;
  text-align: left;
}

.sw-featured--paper .sw-lab-b {
  margin-left: 0;
}

.sw-featured--paper .sw-ix-meta {
  order: 2;
  align-items: flex-end;
  text-align: right;
}

.sw-featured--paper .sw-ix-tags {
  justify-content: flex-end;
}

/* The year keeps its reserved width for a straight column, but
   sets against the right edge of it now. */
.sw-featured--paper .sw-ix-yr {
  text-align: right;
}

/* Out of the layout everywhere the hover fill is not styled, so a
   window resized narrow after load cannot turn it into a grid cell. */
.sw-ix-fill {
  display: none;
}

/* Clicking a row no longer deals a plate, so on a pointer screen
   the row stops promising a click. Touch keeps its tap target.

   The ink underline is replaced here by a direction-aware fill: a
   .sw-ix-fill injected by js/featured.js, sliding in from the edge
   the pointer entered by, and running out past the section's side
   gutters to the page edges as the aperture index does. The row
   stops clipping so the fill can reach them. */
@media (hover: hover) and (pointer: fine) and (min-width: 1001px) {
  .sw-featured--paper .sw-index-row {
    cursor: default;
    overflow: visible;
    isolation: isolate;
  }

  .sw-featured--paper .sw-index-row::after {
    display: none;
  }

  .sw-featured--paper .sw-ix-fill {
    display: block;
    position: absolute;
    top: 0;
    bottom: -1px;
    left: -2.5rem;
    right: -2.5rem;
    z-index: -1;
    overflow: hidden;
    pointer-events: none;
  }

  .sw-featured--paper .sw-ix-fill > span {
    position: absolute;
    inset: 0;
    background: var(--sw-ink);
    will-change: transform;
  }

  /* The row's type turns over with the ink under it. */
  .sw-featured--paper .sw-lab-b,
  .sw-featured--paper .sw-ix-yr,
  .sw-featured--paper .sw-ix-tag {
    transition: color 0.45s cubic-bezier(0.19, 1, 0.22, 1),
      background-color 0.45s cubic-bezier(0.19, 1, 0.22, 1);
  }

  .sw-featured--paper .sw-index-row.is-hot .sw-lab-b,
  .sw-featured--paper .sw-index-row.is-hot .sw-ix-yr {
    color: var(--sw-paper);
  }

  .sw-featured--paper .sw-index-row.is-hot .sw-ix-tag {
    background: var(--sw-accent);
    color: var(--sw-ink);
  }
}

/* ------------------------------------------------------------
   The follow preview - sized, cut and filled exactly as the
   aperture page's .ap-work-pv. Placed at the section's top-left
   and moved by x/y from js/featured.js.
   ------------------------------------------------------------ */
.sw-work-pv {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 6;
  width: clamp(15rem, 23vw, 26rem);
  aspect-ratio: 4 / 3;
  pointer-events: none;
  visibility: hidden;
}

.sw-work-pv-in {
  --n: clamp(8px, 1.1vw, 16px);
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background: #22221d;
  clip-path: polygon(var(--n) 0, calc(100% - var(--n)) 0, 100% var(--n),
    100% calc(100% - var(--n)), calc(100% - var(--n)) 100%,
    var(--n) 100%, 0 calc(100% - var(--n)), 0 var(--n));
}

.sw-work-pv-in img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  will-change: clip-path, transform;
}

@media (max-width: 1000px) {
  .sw-work-pv { display: none; }

  /* The row is a two-column grid here too: label left, year and
     tags on one line to the right. */
  .sw-featured--paper .sw-ix-meta {
    align-items: baseline;
    justify-content: flex-end;
  }
}

@media (hover: none), (pointer: coarse), (prefers-reduced-motion: reduce) {
  .sw-work-pv { display: none; }
}
