/* =============================================================================
   34-categories.css — THE CUPBOARD
   Eleven collections, set as an editorial spread.
   -----------------------------------------------------------------------------

   WHAT THIS REPLACES
   Four equal boxes on a flat panel, each holding a bold 16px name, a grey
   count and an 84px thumbnail floated hard right. The photography — eleven
   moody, centred, 800px product shots already sitting in the term thumbnails
   — was doing nothing at 84px.

   WHAT IT IS NOW
   The BIBLE's first rule is "never a flat panel where an image could carry
   meaning", so every tile is full-bleed photography under a multi-stop scrim
   with the type set ON it, exactly as the hero does it. Nothing about a tile
   is decoration: the picture IS the tile.

   THE FOUR THINGS THAT MAKE IT A COMPOSITION AND NOT A TILING

   1 — ONE COLUMN LINE HELD ALL THE WAY DOWN.  Every row the PHP planner
       emits keeps an edge on the centre line of the twelve-column grid, so
       x = 6 is one unbroken vertical from the first row to the last:

           [ ---- FEATURE 6x2 ---- ][ 3 ][ 3 ]
           [                       ][ 3 ][ 3 ]
           [ 3x2 ][ 3x2 ]          [ --- MAJOR 6x2 --- ]
           [     ][     ]          [                   ]
           [ 3 ][ 3 ]              [ ----- BAND 6 ---- ]

       A mosaic with no shared line reads as loose tiling. One line carried
       the whole height is what makes a page read as designed.

   2 — FIVE ARCHETYPES, EACH WITH ITS OWN SPACE.  Feature, major, portrait,
       band, square. Not one rectangle repeated six times, and — the point
       the first pass got wrong — the feature does not inherit a quarter
       tile's padding. Section 5 gives every archetype its own inset scale
       and its own type size, so an 85px display line sits on a 52px inset
       and a 22px name sits on a 24px one.

   3 — SIZE CARRIES HIERARCHY.  The terms arrive ordered by product count and
       the planner deals them onto the slots by tile AREA, so the spread is a
       picture of the shop's real shape: Teapots holds 511 of 581 pieces and
       takes the feature. Reading order is untouched, so the index numerals
       still count 01..N down the page like a contact sheet.

   4 — THE MARGIN IS BIGGER THAN THE GUTTER.  56px of outer air against a
       flat 22px gutter at >= 1280. When those two are the same number the
       grid has no frame and every tile looks like it fell off the edge.

   COLOUR — ONE GREEN, AND ONLY ONE
   #9ec98a (--color-accent) is the single hue in this section: the italic
   word in the display line, the link out, the feature's flag, and — only
   ever on the tile the pointer is actually over — the rule under the name,
   the pool at the bottom of the scrim and the ring on the arrow. Nothing
   here uses --color-primary; two greens in one view is one too many.

   HOW THIS FILE SITS IN THE CASCADE
   - main.css styles `.categories-section`, `.categories-grid` and
     `.category-card` for the OLD four-box list at 0-1-0 and 0-2-0,
     including inside its own 1200/768/480 media queries. This file loads
     after all of it, and every rule here is written parent-scoped
     (`.categories-section .category-card`, 0-2-0), so it wins on both
     specificity and order. No `!important` anywhere.
   - 05-motion.css owns the section's vertical rhythm and its scroll reveal
     through `body .categories-section …` (0-2-1) and a `:where()` hide rule.
     Both are deliberately left alone: `.section-header`,
     `.categories-section-subtitle` and `.category-card` are the exact hooks
     it keys on, so they stay on the markup and stay unstyled for margin here.
   ============================================================================= */


/* -----------------------------------------------------------------------------
   1. SECTION GROUND & LOCAL TOKENS

   The scrim is the section's whole atmosphere, so it is expressed once as a
   ladder of --night-2 mixes rather than as a raw rgba() in six gradients. Same
   colour the journey resolves to at its bottom edge; the tiles therefore sit
   on the page in the same air the film left behind.
   -------------------------------------------------------------------------- */

.categories-section {
  position: relative;
  isolation: isolate;
  overflow: clip;                 /* never `hidden`: no new scroll container */

  /* Veil ladder — every stop of every scrim in this file comes from here. */
  --cat-veil-14: color-mix(in srgb, var(--night-2) 14%, transparent);
  --cat-veil-18: color-mix(in srgb, var(--night-2) 18%, transparent);
  --cat-veil-30: color-mix(in srgb, var(--night-2) 30%, transparent);
  --cat-veil-46: color-mix(in srgb, var(--night-2) 46%, transparent);
  --cat-veil-54: color-mix(in srgb, var(--night-2) 54%, transparent);
  --cat-veil-66: color-mix(in srgb, var(--night-2) 66%, transparent);
  --cat-veil-82: color-mix(in srgb, var(--night-2) 82%, transparent);
  --cat-veil-95: color-mix(in srgb, var(--night-2) 95%, transparent);

  /* Ink ladder for chrome on photography. */
  --cat-ink-52: color-mix(in srgb, var(--paper) 52%, transparent);
  --cat-ink-68: color-mix(in srgb, var(--paper) 68%, transparent);
  --cat-ink-24: color-mix(in srgb, var(--paper) 24%, transparent);

  /* The gutter is a flat number, not a clamp, at every desktop width: the
     eye reads a constant gutter against a growing margin as a frame. */
  --cat-gap: 22px;
  --cat-row: clamp(150px, 18.6vw, 272px);

  /* The page ground, warmed by one step through the middle of the section so
     the spread sits in a shallow pool of light rather than on a flat slab.
     main.css paints this --color-bg-light end to end; that is the "flat
     surface" the brief is complaining about. */
  background:
    linear-gradient(
      180deg,
      var(--color-bg) 0%,
      color-mix(in srgb, var(--color-bg-light) 76%, var(--color-bg)) 34%,
      color-mix(in srgb, var(--color-bg-light) 76%, var(--color-bg)) 68%,
      var(--color-bg) 100%
    );
}

/* THE FRAME. Two things at once. The outer margin has to be unmistakably
   larger than the gutter — 101px against 22px at 1440 — or the grid reads as
   edge-to-edge wallpaper with no frame around it. And it has to be the SAME
   margin the rest of the page stands on: `clamp(24px, 7vw, 108px)` is the
   journey's own spine, which 32-features.css, the carousel, the promo split
   and the journal all sit on. The old 24px gutter here was the one section
   that ran wider than the hero it follows. */
.categories-section .container {
  position: relative;
  z-index: 1;
  padding-inline: clamp(24px, 7vw, 108px);
}

/* One soft bloom of brand green behind the feature tile — the outro's device,
   at the same strength. It is the only colour in the section that is not
   photography, and it is never seen directly, only felt. */
.categories-section .cat-bloom {
  position: absolute;
  z-index: 0;
  top: 18%;
  left: -12%;
  width: min(62vw, 900px);
  height: min(62vw, 900px);
  border-radius: 50%;
  background: radial-gradient(
    circle,
    color-mix(in srgb, var(--color-accent) 5%, transparent) 0%,
    color-mix(in srgb, var(--color-accent) 2%, transparent) 44%,
    transparent 70%
  );
  filter: blur(30px);
  pointer-events: none;
}


/* -----------------------------------------------------------------------------
   2. THE HEADER

   Kicker, display line, and one HUD link. The kicker is the site's signature —
   34x1px rule, 0.7rem, 0.17em — and it is what labels this section as a
   chapter of the same book as the hero.
   -------------------------------------------------------------------------- */

/* A masthead, not a title bar: display line left, lede and the one link out
   in a narrow measure on the right, both columns sitting on the same baseline. */
.categories-section .section-header {
  display: grid;
  /* Two equal columns on the section's own gutter, so the masthead's second
     column starts exactly on the spread's centre line. The one column line
     that runs the height of the grid starts in the header. */
  grid-template-columns: repeat(2, minmax(0, 1fr));
  align-items: end;
  gap: var(--cat-gap);
  padding-bottom: 0;
  border-bottom: 0;
}

.categories-section .cat-head-lead {
  min-width: 0;
}

.categories-section .cat-head-aside {
  display: flex;
  min-width: 0;
  flex-direction: column;
  align-items: flex-start;
  gap: clamp(18px, 1.8vw, 28px);
  padding-bottom: clamp(4px, 0.6vw, 10px);
}

/* 05-motion.css puts the section's gutter on the lede, because the lede used
   to be the last thing before the grid. It is now the second column of the
   header, so the gutter moves back onto the header itself. Both rules are
   written at motion.css's own weight (0-2-1) and this file loads after it. */
body .categories-section .section-header { margin-bottom: var(--rhythm-gutter); }
body .categories-section .categories-section-subtitle { margin-bottom: 0; }

.categories-section .cat-kicker {
  display: flex;
  align-items: center;
  gap: clamp(12px, 1.1vw, 16px);
  margin: 0;
  color: var(--color-text-light);
  font-family: var(--font-primary);
  font-size: 0.7rem;
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: 0.17em;
  text-transform: uppercase;
}

.categories-section .cat-kicker::before {
  content: "";
  flex: none;
  width: 34px;
  height: 1px;
  background: currentColor;
  opacity: 0.62;
}

/* The display line, to the hero's specification: Fraunces 300, tight leading,
   negative tracking, balanced wrap, one italic word in accent. */
.categories-section .section-title {
  max-width: 15ch;
  margin: clamp(18px, 1.9vw, 30px) 0 0;
  color: var(--color-dark);
  font-family: var(--font-heading);
  font-size: clamp(2.15rem, 4.2vw, 4rem);
  font-weight: 300;
  line-height: 0.94;
  letter-spacing: -0.04em;
  text-wrap: balance;
}

.categories-section .section-title em {
  color: var(--color-accent);
  font-style: italic;
}

.categories-section .categories-section-subtitle {
  max-width: 40ch;
  color: var(--color-text-light);
  font-size: clamp(0.94rem, 1.02vw, 1.03rem);
  line-height: 1.68;
}

/* The one link out. HUD text on a hairline, with the arrow travelling on the
   same curve as everything else in the section. */
.categories-section .section-link {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding-bottom: 9px;
  border-bottom: 1px solid color-mix(in srgb, var(--color-accent) 34%, transparent);
  color: var(--color-accent);
  font-family: var(--font-primary);
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  white-space: nowrap;
  transition: color 0.24s var(--ease-brand), border-color 0.24s var(--ease-brand);
}

.categories-section .section-link:hover {
  border-bottom-color: var(--color-accent);
  color: var(--ink);
}

.categories-section .cat-link-arrow {
  width: 15px;
  height: 15px;
  flex: none;
  transition: transform 0.42s var(--ease-brand);
}

.categories-section .section-link:hover .cat-link-arrow {
  transform: translateX(4px);
}


/* -----------------------------------------------------------------------------
   3. THE SPREAD

   Twelve columns, one fixed row height, spans read off the attributes PHP
   planned. Rows are a fixed height rather than an aspect-ratio so that a
   6x2 feature, a 3x2 portrait and the squares beside them share exactly one
   baseline grid — which is the only reason the composition locks up flush.
   -------------------------------------------------------------------------- */

.categories-section .categories-grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  grid-auto-rows: var(--cat-row);
  gap: var(--cat-gap);
}

.categories-section .categories-grid > [data-span="3"]  { grid-column: span 3; }
.categories-section .categories-grid > [data-span="4"]  { grid-column: span 4; }
.categories-section .categories-grid > [data-span="6"]  { grid-column: span 6; }
.categories-section .categories-grid > [data-span="12"] { grid-column: span 12; }
.categories-section .categories-grid > [data-rows="2"]  { grid-row: span 2; }


/* -----------------------------------------------------------------------------
   4. THE TILE
   -------------------------------------------------------------------------- */

.categories-section .category-card {
  position: relative;
  display: block;
  min-height: 0;
  padding: 0;
  overflow: clip;
  border: 1px solid color-mix(in srgb, var(--paper) 9%, transparent);
  border-radius: var(--radius-md);
  background: var(--color-surface-2);
  /* Depth in this system is surface tone plus one lit edge — 25-controls.css
     settles that for every rectangle in the store, and a photographic tile is
     no exception. */
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--paper) 8%, transparent);
  isolation: isolate;
  text-align: left;   /* main.css centres .category-card under 768px */
  text-decoration: none;
  transition:
    transform 0.5s var(--ease-brand),
    box-shadow 0.5s var(--ease-brand),
    border-color 0.32s var(--ease-brand);
}

.categories-section a.category-card:hover {
  transform: translateY(-3px);
  border-color: color-mix(in srgb, var(--color-accent) 46%, transparent);
  box-shadow:
    inset 0 1px 0 color-mix(in srgb, var(--paper) 12%, transparent),
    var(--shadow-lg);
}


/* --- 4a. The photograph ---------------------------------------------------
   Graded down at rest — the eleven source images range from a black-ground
   copper kettle to a bright yellow gift box, and without a common grade the
   spread reads as eleven stock photos rather than one shop. Saturation and
   brightness come back on hover, which is what makes the hover feel like the
   tile waking up rather than a filter switching off.
   ------------------------------------------------------------------------- */

.categories-section .cat-tile-media {
  position: absolute;
  z-index: 0;
  inset: 0;
  display: block;
  overflow: clip;
  background: var(--color-surface-2);
}

.categories-section .cat-tile-img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  transform: scale(1.015);
  filter: saturate(0.78) contrast(1.07) brightness(0.76);
  transition:
    transform 1.1s var(--ease-brand),
    filter 0.62s var(--ease-brand);
}

.categories-section a.category-card:hover .cat-tile-img {
  transform: scale(1.075);
  filter: saturate(1) contrast(1.02) brightness(0.94);
}

/* The grade is also a hierarchy. The feature is allowed to be the brightest
   thing on the page; the second-largest tile is pulled a step under it so the
   two 6x2 shapes never compete for the same eye — without that, one warm gift
   box out-shouts a 511-piece shelf. */
.categories-section .cat-tile--feature .cat-tile-img {
  filter: saturate(0.84) contrast(1.05) brightness(0.87);
}

.categories-section .cat-tile--major .cat-tile-img {
  filter: saturate(0.7) contrast(1.08) brightness(0.66);
}

.categories-section a.cat-tile--feature:hover .cat-tile-img {
  filter: saturate(1) contrast(1.01) brightness(1);
}

.categories-section a.cat-tile--major:hover .cat-tile-img {
  filter: saturate(0.92) contrast(1.03) brightness(0.84);
}

/* A portrait crop of a square product shot keeps its middle 56%, which is a
   close crop, not a mistake — but it has to be aimed. The subject in these
   shots sits a little above centre, so the crop is pulled up to sit it in the
   upper two thirds with the scrim's long ramp underneath it. */
.categories-section .cat-tile--tall .cat-tile-img {
  object-position: center 44%;
}

/* --- 4b. The scrim --------------------------------------------------------
   Two gradients, six stops. Vertical carries the type block; the diagonal
   weights the top-left so the kicker, numeral and flag have ground of their
   own without a second panel being drawn for them.
   ------------------------------------------------------------------------- */

.categories-section .cat-tile-veil {
  position: absolute;
  z-index: 1;
  inset: 0;
  display: block;
  pointer-events: none;
  background:
    /* the type block: nothing until a third of the way down, then a long
       ramp into near-solid so a name never sits on a busy mid-tone */
    linear-gradient(
      180deg,
      transparent 30%,
      var(--cat-veil-30) 54%,
      var(--cat-veil-66) 74%,
      var(--cat-veil-82) 88%,
      var(--cat-veil-95) 100%
    ),
    /* the chrome band: the numeral and the flag live in the top eighth, and
       three of the eleven photographs are pale up there */
    linear-gradient(
      180deg,
      var(--cat-veil-54) 0%,
      var(--cat-veil-18) 17%,
      transparent 33%
    ),
    /* corner weight, so the left column of type has ground under all of it */
    linear-gradient(
      78deg,
      var(--cat-veil-66) 0%,
      var(--cat-veil-18) 42%,
      transparent 68%
    );
  transition: opacity 0.5s var(--ease-brand);
}

/* The feature is twice the height of a square tile, so a scrim tuned for a
   268px frame would blacken half a photograph. Its ramp starts far lower and
   ends softer. */
.categories-section .cat-tile--feature .cat-tile-veil,
.categories-section .cat-tile--major .cat-tile-veil {
  background:
    linear-gradient(
      180deg,
      transparent 40%,
      var(--cat-veil-30) 62%,
      var(--cat-veil-66) 80%,
      var(--cat-veil-95) 100%
    ),
    linear-gradient(
      180deg,
      var(--cat-veil-46) 0%,
      var(--cat-veil-14) 14%,
      transparent 28%
    ),
    linear-gradient(
      74deg,
      var(--cat-veil-66) 0%,
      var(--cat-veil-18) 46%,
      transparent 72%
    );
}

/* A breath of the section's one green pooling at the bottom of a hovered
   tile. It is never visible on more than one tile at a time. */
.categories-section .cat-tile-veil::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    0deg,
    color-mix(in srgb, var(--color-accent) 16%, transparent) 0%,
    transparent 40%
  );
  opacity: 0;
  transition: opacity 0.5s var(--ease-brand);
}

.categories-section a.category-card:hover .cat-tile-veil { opacity: 0.9; }
.categories-section a.category-card:hover .cat-tile-veil::after { opacity: 1; }


/* --- 4c. Chrome: the index numeral and the feature flag -------------------
   The hero closes on "01 / 06" and opens on "01 · THE LEAF BEGINS". This is
   the same voice, counting the shelves. Eleven numerals across a spread read
   as a contact sheet, which is the point.
   ------------------------------------------------------------------------- */

.categories-section .cat-tile-num {
  position: absolute;
  z-index: 3;
  top: clamp(13px, 1.15vw, 20px);
  right: clamp(13px, 1.15vw, 20px);
  color: var(--cat-ink-52);
  font-family: var(--font-primary);
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  font-variant-numeric: tabular-nums;
  text-shadow: 0 1px 14px color-mix(in srgb, var(--night-2) 78%, transparent);
  transition: color 0.32s var(--ease-brand);
}

.categories-section .cat-tile--feature .cat-tile-num {
  top: clamp(20px, 2.2vw, 32px);
  right: clamp(22px, 2.4vw, 34px);
}

.categories-section a.category-card:hover .cat-tile-num { color: var(--cat-ink-68); }

/* Only ever rendered on the feature, and only when it genuinely holds the
   most stock — a manual running order can put anything first. */
.categories-section .cat-tile-flag {
  position: absolute;
  z-index: 3;
  top: clamp(20px, 2.2vw, 32px);
  left: clamp(28px, 3.6vw, 52px);
  display: flex;
  align-items: center;
  gap: 12px;
  color: var(--color-accent);
  font-family: var(--font-primary);
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.17em;
  text-transform: uppercase;
  text-shadow: 0 1px 14px color-mix(in srgb, var(--night-2) 82%, transparent);
}

.categories-section .cat-tile-flag::before {
  content: "";
  flex: none;
  width: 34px;
  height: 1px;
  background: currentColor;
  opacity: 0.7;
}


/* --- 4d. The type block, generic ------------------------------------------
   Every value here is the SQUARE tile's. Section 5 restates the four other
   archetypes; nothing inherits a size it did not earn.
   ------------------------------------------------------------------------- */

.categories-section .cat-tile-body {
  position: absolute;
  z-index: 3;
  right: clamp(50px, 4vw, 64px);   /* clears the arrow's corner */
  bottom: clamp(14px, 1.35vw, 22px);
  left: clamp(16px, 1.5vw, 24px);
  display: block;
  transition: transform 0.5s var(--ease-brand);
}

.categories-section a.category-card:hover .cat-tile-body {
  transform: translateY(-4px);
}

.categories-section .cat-tile-name {
  display: block;
  color: var(--ink);
  font-family: var(--font-heading);
  font-size: clamp(1.15rem, 1.5vw, 1.45rem);
  font-weight: 300;
  line-height: 1.04;
  letter-spacing: -0.025em;
  text-wrap: balance;
  text-shadow: 0 1px 30px color-mix(in srgb, var(--night-2) 62%, transparent);
}

/* The hairline that draws itself out on hover. Paper at rest so eleven of
   them do not turn the spread green; the section's one accent arrives only
   under the pointer. */
.categories-section .cat-tile-rule {
  display: block;
  width: 30px;
  height: 1px;
  margin: clamp(9px, 0.85vw, 13px) 0 clamp(8px, 0.7vw, 11px);
  background: var(--cat-ink-24);
  transform: scaleX(0.4);
  transform-origin: left center;
  transition:
    transform 0.55s var(--ease-brand),
    background-color 0.4s var(--ease-brand);
}

.categories-section a.category-card:hover .cat-tile-rule,
.categories-section a.category-card:focus-visible .cat-tile-rule {
  transform: scaleX(1);
  background: var(--color-accent);
}

.categories-section .cat-tile-meta {
  display: block;
  color: var(--cat-ink-68);
  font-family: var(--font-primary);
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
  text-shadow: 0 1px 16px color-mix(in srgb, var(--night-2) 72%, transparent);
}

/* Sub-collections, feature only, two at most (the template caps them). A
   single rail that never wraps: wrapping put a hanging separator at the start
   of the second line, which `:first-child` cannot clear. The rail runs off
   its own right edge under an alpha ramp instead, so an unusually long pair
   of names trims rather than breaks. `black` here is a mask channel, not a
   colour: the mask only ever reads its alpha. */
.categories-section .cat-tile-subs {
  display: flex;
  flex-wrap: nowrap;
  gap: 14px;
  margin-top: clamp(14px, 1.3vw, 22px);
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, black calc(100% - 24px), transparent 100%);
          mask-image: linear-gradient(90deg, black calc(100% - 24px), transparent 100%);
}

.categories-section .cat-tile-sub {
  flex: none;
  padding-left: 14px;
  white-space: nowrap;
  border-left: 1px solid var(--cat-ink-24);
  color: var(--cat-ink-52);
  font-family: var(--font-primary);
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.11em;
  text-transform: uppercase;
}

.categories-section .cat-tile-sub:first-child {
  padding-left: 0;
  border-left: 0;
}


/* -----------------------------------------------------------------------------
   5. THE FIVE ARCHETYPES

   One block per tile shape. Each states its own type size AND its own inset,
   because those two things are the same decision: an 85px display line on a
   24px inset is a label pinned to the floor, not a headline.
   -------------------------------------------------------------------------- */

/* --- 5a. FEATURE — 6x2, the deepest shelf --------------------------------- */

.categories-section .cat-tile--feature .cat-tile-body {
  left: clamp(28px, 3.6vw, 52px);
  right: clamp(64px, 5.9vw, 92px);
  bottom: clamp(26px, 3.1vw, 46px);
}

.categories-section .cat-tile--feature .cat-tile-name {
  font-size: clamp(2.4rem, 5.9vw, 5.4rem);
  line-height: 0.9;
  letter-spacing: -0.045em;
}

.categories-section .cat-tile--feature .cat-tile-rule {
  width: 64px;
  margin: clamp(20px, 1.9vw, 30px) 0 clamp(13px, 1.15vw, 18px);
}

.categories-section .cat-tile--feature .cat-tile-meta {
  font-size: 0.72rem;
  letter-spacing: 0.17em;
}

/* --- 5b. MAJOR — the second 6x2 ------------------------------------------- */

.categories-section .cat-tile--major .cat-tile-body {
  left: clamp(24px, 2.5vw, 36px);
  right: clamp(64px, 5.4vw, 88px);
  bottom: clamp(22px, 2.3vw, 34px);
}

.categories-section .cat-tile--major .cat-tile-name {
  font-size: clamp(1.85rem, 3.3vw, 3.1rem);
  line-height: 0.94;
  letter-spacing: -0.038em;
}

.categories-section .cat-tile--major .cat-tile-rule {
  width: 46px;
  margin: clamp(14px, 1.35vw, 21px) 0 clamp(10px, 0.9vw, 14px);
}

/* --- 5c. BAND — 6x1, a full-width shelf ----------------------------------- */

.categories-section .cat-tile--band .cat-tile-body {
  left: clamp(22px, 2.2vw, 32px);
  right: clamp(58px, 5vw, 80px);
  bottom: clamp(18px, 1.8vw, 27px);
}

.categories-section .cat-tile--band .cat-tile-name {
  font-size: clamp(1.4rem, 2.15vw, 2.05rem);
  line-height: 1;
  letter-spacing: -0.032em;
}

.categories-section .cat-tile--band .cat-tile-rule {
  width: 40px;
  margin: clamp(11px, 1.05vw, 16px) 0 clamp(9px, 0.8vw, 12px);
}

/* --- 5d. TALL — 3x2 portrait ---------------------------------------------- */

.categories-section .cat-tile--tall .cat-tile-body {
  left: clamp(18px, 1.75vw, 26px);
  right: clamp(52px, 4.2vw, 66px);
  bottom: clamp(16px, 1.6vw, 25px);
}

.categories-section .cat-tile--tall .cat-tile-name {
  font-size: clamp(1.28rem, 1.85vw, 1.78rem);
  line-height: 1.02;
  letter-spacing: -0.03em;
}

.categories-section .cat-tile--tall .cat-tile-rule {
  width: 34px;
}

/* --- 5e. MINOR — 3x1 square ------------------------------------------------
   Stated by section 4d; nothing to add. Listed here so the set is complete
   on the page rather than implied. */


/* -----------------------------------------------------------------------------
   6. THE ARROW

   A glass disc with a hairline of the section's one green. Never a filled
   button: the chrome in this system is rules and small caps.
   -------------------------------------------------------------------------- */

.categories-section .cat-tile-go {
  position: absolute;
  z-index: 3;
  right: clamp(14px, 1.3vw, 22px);
  bottom: clamp(14px, 1.3vw, 22px);
  display: flex;
  align-items: center;
  justify-content: center;
  width: clamp(32px, 2.4vw, 38px);
  height: clamp(32px, 2.4vw, 38px);
  border: 1px solid var(--cat-ink-24);
  border-radius: 50%;
  color: var(--ink);
  opacity: 0;
  transform: translate3d(7px, 7px, 0);
  transition:
    opacity 0.42s var(--ease-brand),
    transform 0.42s var(--ease-brand),
    background-color 0.32s var(--ease-brand),
    border-color 0.32s var(--ease-brand),
    color 0.32s var(--ease-brand);
}

.categories-section .cat-tile-go svg {
  width: 16px;
  height: 16px;
}

.categories-section .cat-tile--feature .cat-tile-go {
  right: clamp(20px, 2.2vw, 30px);
  bottom: clamp(22px, 2.6vw, 38px);
  width: clamp(38px, 3.1vw, 46px);
  height: clamp(38px, 3.1vw, 46px);
}

.categories-section .cat-tile--feature .cat-tile-go svg {
  width: 18px;
  height: 18px;
}

.categories-section .cat-tile--major .cat-tile-go {
  right: clamp(18px, 1.8vw, 26px);
  bottom: clamp(20px, 2vw, 30px);
  width: clamp(36px, 2.8vw, 44px);
  height: clamp(36px, 2.8vw, 44px);
}

.categories-section a.category-card:hover .cat-tile-go {
  opacity: 1;
  transform: none;
  border-color: color-mix(in srgb, var(--color-accent) 68%, transparent);
  background: color-mix(in srgb, var(--color-accent) 15%, transparent);
  color: var(--color-accent);
}

/* Focus lands on the tile, so the affordance has to arrive for the keyboard
   too — the ring alone does not say "this goes somewhere". */
.categories-section a.category-card:focus-visible .cat-tile-go {
  opacity: 1;
  transform: none;
  border-color: color-mix(in srgb, var(--color-accent) 68%, transparent);
  color: var(--color-accent);
}


/* -----------------------------------------------------------------------------
   7. NO THUMBNAIL

   A missing term image must look like a decision. The tile becomes a graded
   dark ground with the initial set enormous in Fraunces and ghosted into the
   corner — the same display face as the name above it, so the tile still
   belongs to the family. One recipe, rotated by position through three
   custom properties, so a run of empties reads as a set rather than as three
   different mistakes — and so the ground never introduces a second hue.
   -------------------------------------------------------------------------- */

.categories-section .cat-tile--noimg {
  --cat-nog-x: 24%;
  --cat-nog-y: 16%;
  --cat-nog-a: 156deg;
}

.categories-section .cat-tile--noimg:nth-child(3n+2) {
  --cat-nog-x: 78%;
  --cat-nog-y: 22%;
  --cat-nog-a: 204deg;
}

.categories-section .cat-tile--noimg:nth-child(3n) {
  --cat-nog-x: 50%;
  --cat-nog-y: 6%;
  --cat-nog-a: 122deg;
}

.categories-section .cat-tile--noimg .cat-tile-media {
  background:
    radial-gradient(
      118% 96% at var(--cat-nog-x) var(--cat-nog-y),
      color-mix(in srgb, var(--color-accent) 14%, transparent) 0%,
      transparent 62%
    ),
    radial-gradient(
      80% 70% at 92% 96%,
      color-mix(in srgb, var(--paper) 5%, transparent) 0%,
      transparent 64%
    ),
    linear-gradient(var(--cat-nog-a), var(--color-surface-2) 0%, var(--night-2) 100%);
  transition: filter 0.5s var(--ease-brand);
}

.categories-section .cat-tile-glyph {
  position: absolute;
  right: -0.05em;
  bottom: -0.3em;
  color: color-mix(in srgb, var(--paper) 13%, transparent);
  font-family: var(--font-heading);
  font-size: clamp(7rem, 15vw, 15rem);
  font-weight: 300;
  line-height: 0.8;
  user-select: none;
}

/* An image-less tile has no photograph to lift, so its hover is the ground
   itself brightening a step. */
.categories-section a.cat-tile--noimg:hover .cat-tile-media {
  filter: brightness(1.18);
}


/* -----------------------------------------------------------------------------
   8. BREAKPOINTS

   This file loads after every media query in main.css, so main.css cannot
   reach the spread at any width — all of it is re-planned here.

   The plan is re-cut twice rather than squeezed: twelve columns down to six
   at 1000px (a 3-wide tile would fall under 215px otherwise), and six down to
   two at 660px. At each step the feature keeps the full width and every row
   still fills, so the spread stays flush.
   -------------------------------------------------------------------------- */

@media (max-width: 1280px) {
  .categories-section { --cat-gap: 20px; }
}

@media (max-width: 1180px) {
  .categories-section .section-title { font-size: clamp(2rem, 4.4vw, 3.1rem); }
}

/* Between 1000 and 1360 the feature is 6 of 12 columns of a shrinking
   container, and the rail under its count is no longer wide enough to finish
   two sub-collections before the trim mask — and a name that fades mid-word
   is worse than a name that was never set. One below 1360; below 1000 the
   feature is the full container again, so the second comes back. */
@media (max-width: 1360px) {
  .categories-section .cat-tile-sub:nth-child(n+2) { display: none; }
  .categories-section .cat-tile-sub:first-child { padding-left: 0; border-left: 0; }
}

@media (max-width: 1000px) {
  /* Six columns means a 6-span tile is the whole container, so it takes two
     rows or a square product shot gets cropped to a 3.5:1 letterbox. */
  .categories-section {
    --cat-gap: 18px;
    --cat-row: clamp(150px, 27vw, 290px);
  }

  .categories-section .categories-grid {
    grid-template-columns: repeat(6, minmax(0, 1fr));
  }

  .categories-section .categories-grid > [data-span="3"],
  .categories-section .categories-grid > [data-span="4"]  { grid-column: span 3; }
  .categories-section .categories-grid > [data-span="6"],
  .categories-section .categories-grid > [data-span="12"] { grid-column: span 6; }

  /* A full-width tile has nothing beside it, so giving it the second row
     costs the composition nothing and saves the crop. */
  .categories-section .categories-grid > [data-span="6"]:not([data-rows]),
  .categories-section .categories-grid > [data-span="12"]:not([data-rows]) {
    grid-row: span 2;
  }

  /* Everything else pairs two to a row, so an odd tail leaves the last tile
     alone. Give it the full width rather than a hole. */
  .categories-section .categories-grid > :last-child:nth-child(even) {
    grid-column: span 6;
  }

  .categories-section .cat-tile-sub:nth-child(n+2) { display: inline; }
  .categories-section .cat-tile-sub:nth-child(n+2) {
    padding-left: 14px;
    border-left: 1px solid var(--cat-ink-24);
  }

  /* The portrait is now half a wide container rather than a quarter of a
     narrow one, so the photograph can go back to full bleed. */
  .categories-section .cat-tile--tall .cat-tile-img {
    height: 100%;
    object-fit: cover;
    object-position: center;
  }

  .categories-section .section-header {
    grid-template-columns: minmax(0, 1fr);
    align-items: start;
    gap: clamp(18px, 2.6vw, 26px);
  }

  .categories-section .categories-section-subtitle { max-width: 52ch; }

  .categories-section .cat-tile--feature .cat-tile-name {
    font-size: clamp(2.4rem, 6.4vw, 4.2rem);
  }

  .categories-section .cat-tile--major .cat-tile-name {
    font-size: clamp(1.7rem, 3.6vw, 2.5rem);
  }

  .categories-section .cat-tile--band .cat-tile-name {
    font-size: clamp(1.5rem, 3vw, 2.1rem);
  }
}

@media (max-width: 660px) {
  .categories-section {
    --cat-gap: 12px;
  }

  /* The spine holds at every width — `clamp(24px, 7vw, 108px)` is 27px at
     390, which is exactly what the features strip above stands on. Dropping
     to the 15px site gutter here would make this the one section on the phone
     that runs wider than its neighbours. */

  .categories-section .categories-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-auto-rows: auto;
  }

  /* Height now comes from the tile's own ratio, not from a row track — a
     fixed row height at this width either crushes the type or runs the
     section to three screens. */
  .categories-section .categories-grid > .category-card {
    grid-column: span 1;
    grid-row: span 1;
    aspect-ratio: 1 / 1;
  }

  .categories-section .categories-grid > [data-span="6"],
  .categories-section .categories-grid > [data-span="12"] {
    grid-column: span 2;
    aspect-ratio: 16 / 10;
  }

  .categories-section .categories-grid > [data-span="6"][data-rows="2"],
  .categories-section .categories-grid > [data-span="12"][data-rows="2"] {
    aspect-ratio: 5 / 4;
  }

  /* The portraits keep their register: half width, three-quarter ratio, and
     they still pair off flush because they always arrive two at a time. */
  .categories-section .categories-grid > [data-span="3"][data-rows="2"] {
    grid-column: span 1;
    aspect-ratio: 3 / 4;
  }

  .categories-section .categories-grid > :last-child:nth-child(even) {
    grid-column: span 2;
    aspect-ratio: 16 / 10;
  }

  .categories-section .section-title {
    max-width: 18ch;
    font-size: clamp(1.95rem, 8.6vw, 2.6rem);
  }

  .categories-section .categories-section-subtitle {
    font-size: 0.92rem;
  }

  .categories-section .cat-tile-body {
    right: clamp(12px, 3.4vw, 18px);
    bottom: clamp(12px, 3.4vw, 16px);
    left: clamp(12px, 3.4vw, 16px);
  }

  .categories-section .cat-tile-name,
  .categories-section .cat-tile--tall .cat-tile-name,
  .categories-section .cat-tile--band .cat-tile-name {
    font-size: 1.04rem;
    line-height: 1.1;
  }

  .categories-section .cat-tile--feature .cat-tile-body {
    left: clamp(16px, 4.4vw, 22px);
    right: clamp(16px, 4.4vw, 22px);
    bottom: clamp(16px, 4.4vw, 22px);
  }

  .categories-section .cat-tile--feature .cat-tile-name {
    font-size: clamp(1.75rem, 7.6vw, 2.3rem);
  }

  .categories-section .cat-tile--major .cat-tile-body {
    left: clamp(14px, 3.8vw, 20px);
    right: clamp(14px, 3.8vw, 20px);
    bottom: clamp(14px, 3.8vw, 20px);
  }

  .categories-section .cat-tile--major .cat-tile-name {
    font-size: clamp(1.4rem, 5.4vw, 1.8rem);
  }

  .categories-section .cat-tile-rule {
    width: 24px;
    margin: 8px 0 7px;
  }

  .categories-section .cat-tile--feature .cat-tile-rule { width: 38px; margin: 12px 0 9px; }
  .categories-section .cat-tile--major .cat-tile-rule { width: 30px; margin: 10px 0 8px; }

  .categories-section .cat-tile-num {
    top: 11px;
    right: 12px;
  }

  .categories-section .cat-tile--feature .cat-tile-num {
    top: 14px;
    right: 15px;
  }

  .categories-section .cat-tile-flag {
    top: 14px;
    left: clamp(16px, 4.4vw, 22px);
    letter-spacing: 0.14em;
  }

  .categories-section .cat-tile-flag::before { width: 18px; }

  /* Two sub-collections do not fit a 5:4 phone tile without pushing the name
     off it. The name and the count are what matter here. */
  .categories-section .cat-tile-subs { display: none; }

  .categories-section .cat-tile-glyph { font-size: clamp(5rem, 26vw, 8rem); }
}


/* -----------------------------------------------------------------------------
   9. INPUT & MOTION PREFERENCES
   -------------------------------------------------------------------------- */

/* On a touch device the arrow can never arrive, so it is removed rather than
   left as a permanently invisible node — and the resting tile is already
   complete without it. */
@media (hover: none) {
  .categories-section .cat-tile-go { display: none; }

  .categories-section .cat-tile-body { right: clamp(14px, 3.4vw, 26px); }

  /* Nothing will ever hover these, so they rest at full length. */
  .categories-section .cat-tile-rule {
    transform: scaleX(1);
  }

  .categories-section .cat-tile-img {
    filter: saturate(0.9) contrast(1.03) brightness(0.88);
  }

  .categories-section .cat-tile--feature .cat-tile-img {
    filter: saturate(0.95) contrast(1.02) brightness(0.97);
  }

  .categories-section .cat-tile--major .cat-tile-img {
    filter: saturate(0.82) contrast(1.05) brightness(0.78);
  }
}

@media (prefers-reduced-motion: reduce) {
  .categories-section .category-card,
  .categories-section .cat-tile-img,
  .categories-section .cat-tile-veil,
  .categories-section .cat-tile-veil::after,
  .categories-section .cat-tile-body,
  .categories-section .cat-tile-rule,
  .categories-section .cat-tile-go,
  .categories-section .cat-link-arrow {
    transition: none;
  }

  .categories-section a.category-card:hover { transform: none; }
  .categories-section a.category-card:hover .cat-tile-img { transform: scale(1.015); }
  .categories-section a.cat-tile--tall:hover .cat-tile-img { transform: scale(1.015); }
  .categories-section a.category-card:hover .cat-tile-body { transform: none; }
  .categories-section .cat-tile-go { opacity: 1; transform: none; }
}
