/* ==========================================================================
   CATALOG — components that only the Products / Gallery / Custom pages need.
   Loaded AFTER grfp.css and adds nothing to the home page's weight.
   Every colour, font and space here resolves to a token already declared in
   grfp.css. No new palette enters the site through this file.
   ========================================================================== */

/* --------------------------------------------------------------------------
   PAGE HEAD — the ink band that replaces the home page's photographic hero.
   Products/Gallery/Custom are working pages, not a pitch: they open on type,
   not a picture, so the eye goes straight to the thing being catalogued.
   -------------------------------------------------------------------------- */
/* THE INK TYPE HEAD, now used by nothing but the two orphan outdoor pages. The
   products index opened on it for two builds — first as two stacked ink sections,
   then as one with the counts set as spec-sheet numerals on the right — and on
   2026-08-19 Joshua moved it to the full-bleed photographic hero that article 2a
   already specifies for every category page. So the catalogue's front door now opens
   the way the rooms behind it do, and the numeral rules that only that head used are
   gone with it. This rule and its count line stay for the orphans; both go the day
   those two pages are redirected. */
.pagehead{background:var(--ink);color:var(--cream);padding-block:clamp(2.75rem,5.5vw,4.5rem)}
.pagehead .eyebrow{color:var(--gold)}
.pagehead .eyebrow .bar{background:var(--gold)}
.pagehead h1{font-family:var(--sans);font-weight:700;
  font-size:var(--h1-hero);line-height:1;margin:.5rem 0 0}
.pagehead .lede{color:var(--cream-88);margin:1.1rem 0 0;max-width:62ch}
.pagehead .count{font-family:var(--sans);font-weight:700;font-size:.74rem;
  letter-spacing:.17em;text-transform:uppercase;color:var(--gold);margin:1.4rem 0 0}

/* Breadcrumb — ink band variant and light variant share one rule set. */
.crumb{font-family:var(--sans);font-size:.74rem;letter-spacing:.11em;text-transform:uppercase;
  color:var(--cream-88);margin:0 0 .35rem}
.crumb a{color:var(--gold);text-decoration:none}
.crumb a:hover{text-decoration:underline}
.crumb span{opacity:.55;padding:0 .45rem}

/* --------------------------------------------------------------------------
   DEPARTMENT BLOCKS — the Products index. One block per nav group, each a
   plain list of its categories with a live item count. The count is the point:
   a designer scanning this wants to know where the depth is.
   -------------------------------------------------------------------------- */
.dept{border-top:1px solid var(--line);padding-block:clamp(2rem,4vw,3.25rem)}
.dept:first-of-type{border-top:0}
/* .dept-h is gone: the department's name lives on its photograph now, so the separate
   heading row it styled no longer exists. .pidx-h, which styles the ranges block's
   heading, is a different rule and is still in use. */

/* THE DEPARTMENT'S ROOM, THEN ITS CATEGORIES. (Joshua, 2026-08-18: "this whole
   block needs some lifestyle photos or a redesign. It is poorly designed for a
   Designer or customer to see what we offer.") It was five headings over a field of
   bordered text boxes — a taxonomy, not a catalogue, and nothing on it showed a
   designer a single thing GRFP sells. Each department now opens on its own room
   photograph and every category card carries a product shot.
   Only imagery that already exists is used. The five room photographs are the HOME
   PAGE'S OWN, so a designer arriving from there meets the same picture of the same
   department rather than a second opinion about it; the card shots are each
   category's first product with an image. There are no per-category room shots on
   this site and none were invented.
   NOTE: a dormant second .cats block used to sit further down this file, from an
   earlier design that wanted a .row wrapper. It declared .cats a a second time and
   silently won on padding because it came later. It is folded in here — one rule
   set for one component. */
/* THE COLUMN COUNT COMES FROM THE DATA, not from a minmax that guesses. auto-fill gave
   every band four columns, and 6, 10 and 5 categories become 4+2, 4+4+2 and 4+1 — a
   short final row with a hole in it, on every band, which is the ragged rhythm this page
   was originally written to fix. --cols is set per band by columnsFor(): the count in
   3-5 that divides evenly. Below 900px it reverts to a minmax, because on a narrow
   screen a flush row matters less than a tile wide enough to read. */
.cats{list-style:none;margin:0;padding:0;display:grid;
  grid-template-columns:repeat(var(--cols,4),minmax(0,1fr));gap:.75rem}
@media (max-width:900px){
  .cats{grid-template-columns:repeat(auto-fill,minmax(200px,1fr))}
}
.cats a{display:block;background:var(--paper);border:1px solid var(--line);
  text-decoration:none;color:var(--ink);height:100%;overflow:hidden;
  transition:transform .22s cubic-bezier(.25,1,.5,1),box-shadow .22s cubic-bezier(.25,1,.5,1),border-color .18s ease}
.cats a:hover{transform:translateY(-3px);box-shadow:var(--sh-card);border-color:var(--gold)}
/* A SQUARE BOX FOR SQUARE IMAGES, and this is measurement not preference. Every
   catalogue shot on this site is exactly 1:1 — sampled across categories, all 1000x1000
   or 1411x1411. In a 16:10 box on `contain` a square image is HEIGHT-constrained, so it
   rendered at the box's height and gave back a third of its width as dead white on each
   side: a 205px-wide card showed a 128px product. At 1:1 the image fills the box edge to
   edge and the same card shows a 238px product. Nothing was cropped before and nothing
   is cropped now; the box simply stopped being the wrong shape for its contents. */
.cats .thumb{display:block;width:100%;aspect-ratio:1/1;background:var(--shot-ground);
  border-bottom:1px solid var(--line);overflow:hidden}
/* COVER, NOT CONTAIN (2026-08-26). These two boxes are 1:1 and every catalogue shot is
   exactly 1:1 — all 20 on this page measured square — so cover and contain render
   IDENTICALLY today; this is a no-op on the current images, verified. It is here so a
   lifestyle photograph, which is not square, FILLS the card instead of being letterboxed
   inside it against the white plate. Masters want to be 800x800: the box is 348px at its
   widest (one column at 390) and 392px if a band ever takes 3 columns, so 800 covers
   both at 2x. Scoped to these two rules on purpose — the PDP gallery, the hero and the
   A-Z grid are still catalogue cutouts and still want contain. */
.cats .thumb img{width:100%;height:100%;object-fit:cover;display:block}
.cats .cbody{display:block;padding:1.05rem 1.15rem 1.2rem}
.cats .nm{display:block;font-family:var(--sans);font-weight:700;font-size:1.05rem;
  line-height:1.25;letter-spacing:-.01em}
/* The count is the reason this card is worth reading — a designer scanning for
   where the depth is wants the figure, not a whisper of it. It was .68rem with
   .12em tracking, which at card size did not register at all. It is NOT a
   department accent: this page carries all five departments, and the rule is one
   page, one department — or none. */
.cats .ct{display:block;margin-top:.45rem;font-family:var(--mono);font-size:.78rem;
  letter-spacing:.06em;color:var(--walnut)}
.cats a[data-empty="1"]{opacity:.5}
.cats a[data-empty="1"] .ct{color:var(--ink-70)}
.cats a[data-empty="1"] .thumb{display:none}

/* A SINGLE-CATEGORY DEPARTMENT SHOWS PRODUCT. Shuffleboards and Outdoor hold one
   category each, so a card repeating the heading's own words was duplication — but
   removing it left a photograph, a heading and empty page, which reads as a fault
   rather than as economy. These bands show four pieces by SKU instead. Same tile
   geometry as the category cards above them, because they are the same kind of object
   at a different altitude, and one geometry is what stops the page accumulating
   idioms. */
.dept-picks{list-style:none;margin:1.25rem 0 0;padding:0;display:grid;
  grid-template-columns:repeat(var(--cols,4),minmax(0,1fr));gap:.75rem}
@media (max-width:900px){
  .dept-picks{grid-template-columns:repeat(auto-fill,minmax(200px,1fr))}
}
.dept-picks a{display:block;background:var(--paper);border:1px solid var(--line);
  text-decoration:none;color:var(--ink);height:100%;overflow:hidden;
  transition:transform .22s cubic-bezier(.25,1,.5,1),box-shadow .22s cubic-bezier(.25,1,.5,1),border-color .18s ease}
.dept-picks a:hover{transform:translateY(-3px);box-shadow:var(--sh-card);border-color:var(--gold)}
.dept-picks .thumb{display:block;width:100%;aspect-ratio:1/1;background:var(--shot-ground);
  border-bottom:1px solid var(--line);overflow:hidden}
.dept-picks .thumb img{width:100%;height:100%;object-fit:cover;display:block}
/* A BARE TILE HAS NOTHING UNDER THE IMAGE, SO THE IMAGE HAS NO EDGE TO DIVIDE FROM.
   .thumb carries a border-bottom to separate the shot from the caption beneath it;
   with the caption gone that rule draws a hairline across the foot of the picture for
   no reason. Removing the caption without removing its divider is how a deletion leaves
   a mark. */
.dept-picks.is-bare .thumb{border-bottom:0}
.dept-picks .cbody{display:block;padding:1.05rem 1.15rem 1.2rem}
.dept-picks .nm{display:block;font-family:var(--mono);font-size:.86rem;letter-spacing:.02em;
  color:var(--ink);font-variant-numeric:lining-nums}
.dept-picks .ct{display:block;margin-top:.4rem;font-family:var(--mono);font-size:.72rem;
  letter-spacing:.06em;color:var(--walnut)}

/* THE DEPARTMENT HEADER IS A PHOTO BAND, carrying its own name. It was a bare strip
   150-260px tall with the heading in a separate row underneath — a 16:9 room cropped to a
   letterbox, and then a whole row spent naming what the picture already showed. This is
   the site's own photo-band device instead: image, one flat veil, name over it, the same
   treatment the category heroes and the home page hero use. Taller so the room reads as
   a room, and one row shorter.
   THE VEIL IS .68, AND THAT NUMBER IS MEASURED not chosen. At .60 the 38px name cleared
   large-text AA on all five photographs (4.67 to 5.21:1) but the small mono count line
   beside it did not: cream-88 came to 3.76-4.19:1 against the 4.5:1 body threshold, on
   every one of the five. The count went to full cream and the veil to .68, which brings
   the worst pixel behind the smallest type on the least forgiving photograph clear of
   4.5:1 with margin. Small type is what sets a veil, not the headline. */
/* THESE ARE THE SHAPE OF THEIR PHOTOGRAPH TOO, but by aspect-ratio rather than by vw: a
   department band sits inside .wrap, so 100vw overshoots its own width and would crop the
   sides instead of the top. At a fixed 320px they were showing 43-78% of their rooms.
   aspect-ratio is safe here where it would not be on a hero: the only thing over the image
   is one line — a name, a count and sometimes a link — so there is no copy tall enough to
   need more room than the ratio gives. The min-height stays as a floor for phones. */
/* max-width:100% IS LOAD-BEARING HERE, and finding out why cost a 320px overflow.
   aspect-ratio and a min-height that contradicts it do not resolve the way you expect: the
   browser satisfies the RATIO by growing the box's WIDTH. At 320px the column is 280px wide,
   16:9 of that is 157px tall, the min-height demanded 200px — so the box widened to 356px
   and pushed 56px past the viewport, behind overflow-x:hidden where nothing but a
   measurement would have found it. The cap makes the width inviolable and lets the ratio
   lose instead. The floor comes down to 150px for the same reason: a floor that fights the
   ratio is what created the conflict. */
.dept-head{position:relative;overflow:hidden;margin:0 0 1.5rem;
  aspect-ratio:16/9;max-width:100%;min-height:clamp(150px,23vw,300px);
  display:flex;align-items:flex-end;isolation:isolate}
.dept-head>.veil{background:rgba(20,16,11,.68)}
.dept-head.is-flat{background:var(--mist);min-height:0;margin-bottom:1.1rem}
.dept-head-in{position:relative;display:flex;align-items:baseline;gap:1rem;flex-wrap:wrap;
  width:100%;padding:clamp(1.1rem,2.2vw,1.6rem) clamp(1.1rem,2.2vw,1.75rem)}
.dept-head h2{font-family:var(--sans);font-weight:700;
  font-size:clamp(1.5rem,3.4vw,2.375rem);line-height:1;letter-spacing:-.022em;
  text-transform:uppercase;margin:0;color:var(--cream)}
.dept-head .n{font-family:var(--mono);font-size:.78rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--cream)}
.dept-head .go{margin-left:auto;font-family:var(--sans);font-weight:700;font-size:.72rem;
  letter-spacing:.1em;text-transform:uppercase;color:var(--cream);text-decoration:none;
  border-bottom:1px solid rgba(250,248,243,.45);white-space:nowrap}
.dept-head .go:hover{border-bottom-color:var(--gold)}
.dept-head.is-flat h2,.dept-head.is-flat .n{color:var(--ink)}
.dept-head.is-flat .n{color:var(--walnut)}
.dept-head.is-flat .go{color:var(--ink);border-bottom-color:var(--line)}
@media (max-width:560px){.dept-head .go{margin-left:0}}

/* --------------------------------------------------------------------------
   FACETS — the size/style filter rail. Buttons, not links: filtering happens
   client-side against products.json, so there is no URL to visit and a link
   would lie about that.
   -------------------------------------------------------------------------- */
.facets{background:var(--mist);border-block:1px solid var(--line);
  padding-block:clamp(1.1rem,2.2vw,1.6rem);position:sticky;top:0;z-index:20}
.facet-row{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap}
.facet-lbl{font-family:var(--sans);font-weight:700;font-size:.7rem;letter-spacing:.15em;
  text-transform:uppercase;color:var(--ink-70);margin-right:.35rem}
.chip{font-family:var(--sans);font-weight:600;font-size:.76rem;letter-spacing:.06em;
  background:var(--paper);color:var(--ink);border:1px solid var(--line);
  border-radius:999px;padding:.42rem .9rem;cursor:pointer;
  transition:background-color .16s ease,border-color .16s ease,color .16s ease}
.chip:hover{border-color:var(--gold)}
.chip[aria-pressed="true"]{background:var(--ink);color:var(--cream);border-color:var(--ink)}
.chip .k{opacity:.6;font-weight:400;padding-left:.35rem}
.facet-clear{font-family:var(--sans);font-size:.74rem;letter-spacing:.08em;text-transform:uppercase;
  background:none;border:0;color:var(--walnut);cursor:pointer;text-decoration:underline;padding:.42rem .3rem}

/* --------------------------------------------------------------------------
   PRODUCT GRID — SKU cards. No prices anywhere: GRFP is trade-only and price
   lives with the Designer Program, so a price on this page would be a claim
   the site is not allowed to make.
   -------------------------------------------------------------------------- */
.pcount{font-family:var(--sans);font-weight:700;font-size:.72rem;letter-spacing:.15em;
  text-transform:uppercase;color:var(--walnut);margin:0 0 1.2rem}
.pgrid{list-style:none;margin:0;padding:0;
  display:grid;grid-template-columns:repeat(auto-fill,minmax(215px,1fr));gap:.9rem}
.pgrid li{margin:0}
.pcard{display:flex;flex-direction:column;gap:.5rem;height:100%;
  background:var(--paper);border:1px solid var(--line);
  padding:1.05rem 1.1rem;text-decoration:none;color:var(--ink);
  transition:transform .22s cubic-bezier(.25,1,.5,1),box-shadow .22s cubic-bezier(.25,1,.5,1),border-color .18s ease}
.pcard:hover{transform:translateY(-3px);box-shadow:var(--sh-card);border-color:var(--gold)}
/* The SKU is the number a designer quotes and brings to the showroom, so it
   reads as the card's identifier, not as a caption. Same weight as .ecard. */
.pcard .sku{font-family:'Courier New',ui-monospace,monospace;font-weight:700;font-size:.82rem;
  letter-spacing:.02em;color:var(--ink);text-transform:uppercase}
.pcard .ty{font-family:var(--mono);font-weight:400;font-size:.8rem;line-height:1.25;margin-top:auto}
.pcard .cl{font-family:var(--sans);font-size:.7rem;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-70)}
.pempty{font-family:var(--sans);font-size:1.1rem;color:var(--ink-70);padding:2.5rem 0}

/* --------------------------------------------------------------------------
   GALLERY — CSS columns, not grid. The source images are mixed portrait and
   landscape with no common ratio, and columns let each keep its own shape
   without cropping. Cropping a finished room to fit a tile is the one thing a
   gallery must not do.
   -------------------------------------------------------------------------- */
/* JUSTIFIED ROWS, AND EVERY PHOTOGRAPH AT ITS EXACT RATIO. (Joshua, 2026-08-19, with a
   reference image showing clean rows of mixed widths rather than equal columns.)
   Four layouts were measured before this one shipped, which is the only reason to trust it:
     four equal columns  0% crop, but a ragged foot and one long undifferentiated wall
     a spanned mosaic    4-16% crop, 34% worst, and 10547px tall at 1440 — double the
                         columns version, because a two-column landscape cell fits half as
                         many photographs per row
     flex rows by BUCKET 13% crop, because orient has three values and the real ratios have
                         eleven: a photograph tagged square is anywhere from 0.9 to 1.14
     these rows          0% by construction
   HOW IT GETS TO ZERO. Each figure declares its own measured ratio and takes
   `flex: var(--ar) 1 0` — so after gaps are deducted the remaining width is shared in
   proportion to the ratios, making every width proportional to its own shape. Its height then
   comes from `aspect-ratio: var(--ar)`, which for widths already proportional to ar resolves
   to the SAME height for every item in the row. Justified rows, solid edges, no crop, and no
   JavaScript measuring anything.
   Rows are packed at build time to an aspect-sum target of about 3.45, giving three or four
   photographs per row; a row of wide photographs comes out shorter than a row of narrow ones,
   and that variation is the rhythm the reference image has.
   THE RATIOS ARE MEASURED AND STORED. data/gallery.json now carries w and h for all 54, read
   off the mirrored files — the coarse `orient` label is what produced the 13% version. */
.gal{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:1rem}
.gal-row{display:flex;gap:1rem;min-width:0}
.gal-row figure{margin:0;min-width:0;flex:var(--ar) 1 0;aspect-ratio:var(--ar)}
@media (max-width:640px){
  /* A row of four at phone width gives four thumbnails, so the row wraps to two across.
     align-items:flex-start IS REQUIRED and its absence cost 57.8% crop at 390px: flex
     defaults to align-items:stretch, which forces every item in a line to the line's height
     and so OVERRIDES aspect-ratio. Above 640 that was invisible, because widths proportional
     to each ratio already produce equal heights and stretching changed nothing. Force widths
     to 50% and the heights genuinely differ — at which point stretch silently reintroduces
     exactly the crop this layout exists to avoid. */
  .gal-row{flex-wrap:wrap;align-items:flex-start}
  .gal-row figure{flex:1 1 calc(50% - .5rem)}
}

/* object-fit:cover is a belt here rather than a crop: the box already carries the
   photograph's own ratio, so there is nothing for cover to trim. It stays in case a stored
   ratio is ever wrong, where a letterboxed image would be the louder failure. */
.gal img{display:block;width:100%;height:100%;object-fit:cover;border-radius:2px;
  background:var(--mist);box-shadow:var(--sh);
  transition:transform .22s cubic-bezier(.25,1,.5,1),box-shadow .22s cubic-bezier(.25,1,.5,1)}
.gal button{display:block;width:100%;height:100%;padding:0;border:0;background:none;cursor:zoom-in}
.gal button:hover img{transform:translateY(-3px);box-shadow:var(--sh-card)}

/* Lightbox. <dialog> so Esc and focus trapping come from the platform. */
.lb{border:0;padding:0;background:transparent;max-width:min(94vw,1400px);max-height:94vh}
.lb::backdrop{background:rgba(20,16,11,.9)}
.lb img{display:block;max-width:100%;max-height:88vh;width:auto;height:auto;margin:0 auto;border-radius:2px}
.lb-cap{font-family:var(--sans);font-size:.78rem;letter-spacing:.06em;color:var(--cream-88);
  text-align:center;padding:.85rem 1rem 0}
.lb-x{position:fixed;top:1rem;right:1.15rem;font-family:var(--sans);font-weight:700;font-size:1.5rem;
  line-height:1;background:none;border:0;color:var(--cream);cursor:pointer;padding:.4rem .6rem}

/* --------------------------------------------------------------------------
   CUSTOM — the four-step build story.
   -------------------------------------------------------------------------- */
.steps{counter-reset:step;list-style:none;margin:0;padding:0}
.steps > li{counter-increment:step;border-top:1px solid var(--line);
  padding-block:clamp(1.9rem,3.6vw,2.9rem);
  display:grid;grid-template-columns:5.5rem 1fr;gap:clamp(1rem,3vw,2.4rem)}
.steps > li::before{content:"Step " counter(step);
  font-family:var(--sans);font-weight:700;font-size:.72rem;letter-spacing:.15em;
  text-transform:uppercase;color:var(--gold);padding-top:.4rem}
.steps h3{font-family:var(--sans);font-weight:700;font-size:clamp(1.1rem,2.1vw,1.42rem);
  text-transform:uppercase;letter-spacing:.03em;margin:0 0 .7rem}
.steps p{margin:0 0 .85rem;max-width:64ch}
.steps p:last-child{margin-bottom:0}

.choices{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:1rem;margin-top:1.4rem}
.choice{background:var(--paper);border:1px solid var(--line);border-left:3px solid var(--gold);
  border-radius:2px;padding:1.1rem 1.2rem}
.choice h4{font-family:var(--sans);font-weight:700;font-size:.78rem;letter-spacing:.13em;
  text-transform:uppercase;margin:0 0 .6rem}
.choice ul{margin:0;padding-left:1.1rem}
.choice li{font-family:var(--sans);font-size:.98rem;line-height:1.5;margin-bottom:.3rem}

@media (max-width:640px){
  .steps > li{grid-template-columns:1fr;gap:.5rem}
  .gal{columns:2 150px}
  .facets{position:static}
}


/* ==========================================================================
   PRODUCT IMAGERY — added 2026-08-17 with the WordPress media harvest.
   ========================================================================== */

/* Cards become image-led. The photograph is the differentiator: 136 pool tables
   whose text reads "Pool Table · Collection 213" are indistinguishable without
   it. object-fit:contain, not cover — these are catalogue shots on white, often
   with the product centred and tight, and cover would crop legs and rails off. */
.pcard{padding:0;overflow:hidden}
.pcard .shot{display:block;width:100%;aspect-ratio:4/3;background:var(--shot-ground);
  overflow:hidden;border-bottom:1px solid var(--line)}
.pcard .shot img{width:100%;height:100%;object-fit:contain;display:block;
  transition:transform .3s cubic-bezier(.25,1,.5,1)}
.pcard:hover .shot img{transform:scale(1.03)}
.pcard .body{display:flex;flex-direction:column;gap:.4rem;padding:.9rem 1rem 1rem;flex:1}
.pcard .ty{margin-top:0}
/* Two lines, then ellipsis. Much of this copy is collection boilerplate repeated
   across dozens of items, so giving it more room than two lines makes a grid
   read as one paragraph printed over and over. */
.pcard .ds{font-family:var(--sans);font-size:.88rem;line-height:1.45;color:var(--ink-70);
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.pcard .facets-line{font-family:var(--sans);font-size:.66rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--walnut);margin-top:.15rem}
.pgrid{grid-template-columns:repeat(auto-fill,minmax(255px,1fr));gap:1.1rem}



/* ==========================================================================
   CUSTOM BUILT MEDIA — added 2026-08-17 with the /custom-built harvest.
   ========================================================================== */

/* The hero is a single tall photograph of a finished custom piece. It sits beside
   the opening copy rather than behind it: the page's job is to show work, and a
   veiled background image shows less than an unveiled one. */
.custom-hero{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,.72fr);
  gap:clamp(1.5rem,4vw,3.5rem);align-items:center}
.custom-hero figure{margin:0}
.custom-hero img{display:block;width:100%;height:auto;border-radius:3px;
  box-shadow:var(--sh);background:var(--mist)}

/* Step media. One or two images per step, never cropped — a custom piece is the
   subject, and cropping it to a uniform tile defeats the point. */
.step-media{display:grid;gap:.9rem;margin-top:1.3rem}
.step-media.two{grid-template-columns:repeat(auto-fit,minmax(240px,1fr))}
.step-media.four{grid-template-columns:repeat(auto-fit,minmax(175px,1fr))}
.step-media figure{margin:0}
.step-media img{display:block;width:100%;height:auto;border-radius:2px;
  background:var(--mist);box-shadow:var(--sh)}
.step-media figcaption{font-family:var(--sans);font-size:.68rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--walnut);margin-top:.5rem;line-height:1.4}

/* A render is not a photograph and must not be passed off as one. Every
   AI-generated or illustrative image on this page carries this mark, in the
   caption, where a reader actually sees it. */
.is-render figcaption::before{content:"Render · ";color:var(--gold);font-weight:700}

.wide-fig{margin:1.4rem 0 0}
.wide-fig img{display:block;width:100%;height:auto;border-radius:3px;
  background:var(--mist);box-shadow:var(--sh)}
.wide-fig figcaption{font-family:var(--sans);font-size:.68rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--walnut);margin-top:.55rem}

@media (max-width:760px){ .custom-hero{grid-template-columns:1fr} }


/* --------------------------------------------------------------------------
   COLLECTION BANDS — the collections-led category page.
   Generated by build/category-page.mjs. The story is told ONCE here, beside
   its own products, which is why the cards below carry no description: on
   this catalogue 302 of 523 products share their description with another
   product, so a description on the card was the same paragraph repeated.
   -------------------------------------------------------------------------- */
.jump-row{margin-top:.55rem;padding-top:.55rem;border-top:1px solid var(--line)}
.jump-row .chip{text-decoration:none;color:var(--ink);display:inline-block}

.cband{border-top:1px solid var(--line);padding-block:clamp(2rem,4.4vw,3.4rem)}
.cband:nth-of-type(even){background:var(--mist)}
.cband-grid{display:grid;grid-template-columns:minmax(0,19rem) minmax(0,1fr);
  gap:clamp(1.4rem,3.6vw,3rem);align-items:start}
.cband-side{position:sticky;top:1rem}
/* Collection numbers are set in Fragment Mono, whose figures are lining and
   fixed-width by design — a 213 lines up under a 232. The lining-nums
   declaration is retained as the same guard as the door plate's. */
.cband-n{font-family:var(--mono);font-weight:400;font-size:clamp(2.6rem,5vw,4rem);
  line-height:.92;margin:0;color:var(--ink);font-variant-numeric:lining-nums;
  letter-spacing:-.02em}
.cband-n span{display:block;font-family:var(--sans);font-weight:700;font-size:.66rem;
  letter-spacing:.2em;text-transform:uppercase;color:var(--walnut);margin-bottom:.4rem}
.cband-key{font-family:var(--sans);font-weight:700;font-size:.66rem;letter-spacing:.13em;
  text-transform:uppercase;color:var(--walnut);margin:.7rem 0 0}
.cband-say{font-family:var(--sans);font-size:1rem;line-height:1.6;color:var(--ink-78);
  margin:.9rem 0 0}
.cband-facts{list-style:none;margin:1.1rem 0 0;padding:0;border-top:1px solid var(--gold)}
.cband-facts li{display:flex;justify-content:space-between;gap:1rem;padding:.45rem 0;
  border-bottom:1px solid var(--line)}
.cband-facts b{font-family:var(--sans);font-weight:700;font-size:.64rem;letter-spacing:.13em;
  text-transform:uppercase;color:var(--walnut);padding-top:.2rem;white-space:nowrap}
.cband-facts span{font-family:var(--mono);font-size:.78rem;color:var(--ink-78);text-align:right}
.band-more{margin:1.1rem 0 0}
.band-more a{font-family:var(--sans);font-weight:700;font-size:.7rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--ink);text-decoration:none;
  border-bottom:2px solid var(--gold);padding-bottom:.18rem}
.band-more a:hover{color:var(--walnut)}

.cband-items{list-style:none;margin:0;padding:0;
  display:grid;grid-template-columns:repeat(auto-fill,minmax(190px,1fr));gap:.9rem}
.ecard{display:flex;flex-direction:column;height:100%;background:var(--paper);
  border:1px solid var(--line);overflow:hidden;text-decoration:none;
  color:var(--ink);
  transition:transform .22s cubic-bezier(.25,1,.5,1),box-shadow .22s cubic-bezier(.25,1,.5,1),border-color .18s ease}
.ecard:hover{transform:translateY(-3px);box-shadow:var(--sh-card);border-color:var(--gold)}
.ecard .shot{display:block;background:var(--shot-ground)}
.ecard .shot img{display:block;width:100%;aspect-ratio:4/3;object-fit:contain}
.ecard .body{display:flex;flex-direction:column;gap:.18rem;
  padding:.7rem .85rem .9rem;border-top:1px solid var(--line)}
.ecard .sku{font-family:'Courier New',ui-monospace,monospace;font-weight:700;font-size:.82rem;
  letter-spacing:.02em;color:var(--ink)}
.ecard .ty{font-family:var(--mono);font-weight:400;font-size:.78rem;line-height:1.25}
.ecard .attr{font-family:var(--sans);font-size:.7rem;letter-spacing:.06em;color:var(--ink-70);
  line-height:1.35}

/* The flat grid's card gains the same line, for the filtered view. */
.pcard .attr{font-family:var(--sans);font-size:.7rem;letter-spacing:.06em;
  color:var(--ink-70);line-height:1.35}

/* SOLO — a category that is one collection end to end. The giant numeral is
   an index for a page with nine of them; on a page with one it just shouts. */
.cband.is-solo{border-top:0}
.cband-solo{font-family:var(--sans);font-weight:700;font-size:.68rem;letter-spacing:.2em;
  text-transform:uppercase;color:var(--walnut);margin:0}

/* PHOTO-LED — no spec varies and no name is confirmed, so the photograph is
   the only honest differentiator. It gets the space the empty attribute line
   would have wasted: fewer, larger tiles rather than more, emptier ones. */
.cband-items.is-photo{grid-template-columns:repeat(auto-fill,minmax(240px,1fr))}
.cband-items.is-photo .shot img{aspect-ratio:1/1}
.cband-items.is-photo .body{gap:.1rem}

@media (max-width:900px){
  .cband-grid{grid-template-columns:1fr}
  .cband-side{position:static}
}


/* ==========================================================================
   PRODUCTS INDEX — the catalogue's front door. Generated by
   build/products-index.mjs. Collections lead, tiered by breadth, because
   breadth is what a designer furnishing a whole room needs; departments are
   the second cut.
   ========================================================================== */

.pidx{padding-block:clamp(2rem,4.2vw,3.2rem);border-top:1px solid var(--line)}
.pidx.alt{background:var(--mist)}
.pidx-h{display:flex;align-items:baseline;gap:1rem;flex-wrap:wrap;margin:0 0 1.5rem}
.pidx-h h3{font-family:var(--sans);font-weight:700;font-size:clamp(1.1rem,2.2vw,1.5rem);
  text-transform:uppercase;letter-spacing:.04em;margin:0}
.pidx-h .n{font-family:var(--sans);font-weight:700;font-size:.68rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--walnut)}

/* --- the ranges: ONE ruled row for all 21 -------------------------------------
   This replaced a grid of five tall photo cards sitting above a list of sixteen ruled
   rows, inside one block. Five items in a three-track grid leaves an orphan gap; the
   cards wrapped a 16:10 contain box around images that are exactly 1:1, so the product
   rendered at the box's height and lost a third of its width to white; and two
   treatments for twenty-one instances of one object is what this page has now been
   corrected for three times. Every collection has a product shot, so every row carries
   a thumbnail and the five that furnish a room say so in words instead of by being a
   different shape.
   ---------------------------------------------------------------------------- */
.rlist{list-style:none;margin:0;padding:0;border-top:1px solid var(--line)}
.rlist li{border-bottom:1px solid var(--line)}
/* ROW HEIGHT IS THE BLOCK'S LENGTH, and twenty-one of them add up. At a 76px thumbnail
   each row came to 92px and the block ran 2308px — LONGER than the five cards and
   sixteen rows it replaced, which is not an improvement however much tidier it is. At
   64px with tighter padding the row is 78px and the block comes in under the original
   while keeping a thumbnail on every range. */
.rlist a{display:grid;grid-template-columns:64px minmax(0,1fr) 9.5rem 11.5rem 2.75rem;
  gap:clamp(.8rem,1.8vw,1.35rem);align-items:center;padding:.5rem .4rem;
  text-decoration:none;color:var(--ink);
  transition:background-color .16s ease,padding-left .18s ease}
.rlist a:hover{background:var(--paper);padding-left:.9rem}
.rthumb{display:block;width:64px;aspect-ratio:1/1;background:var(--shot-ground);
  border:1px solid var(--line)}
.rthumb img{width:100%;height:100%;object-fit:contain;display:block}
/* WHAT IT CONTAINS is the headline of the row. A 2.2rem collection number used to hold
   this position, which made the SKU prefix the largest thing on a card about a range of
   furniture. */
.rwhat{font-family:var(--sans);font-weight:600;font-size:.95rem;line-height:1.3}
.rmeta{font-family:var(--mono);font-size:.74rem;letter-spacing:.04em;color:var(--walnut)}
.rlist .is-broad .rmeta{color:var(--ink-78)}
/* SENTENCE CASE, NO TRACKING, AND IT IS NOT A STYLE CHOICE. As tracked bold caps
   "UNDER AIR HOCKEY TABLES →" did not fit the column and wrapped, orphaning the arrow on
   its own line — the longest destination is 23 characters and tracking adds .12em to
   every one of them. Sentence case with no tracking fits every label on one line, and it
   is the right register anyway: this is a note about where the row goes, not a button. */
.rdest{font-family:var(--sans);font-weight:600;font-size:.78rem;color:var(--ink-78);
  text-align:right;text-wrap:nowrap}
.rlist .is-broad .rdest{font-weight:700;color:var(--ink)}
.rid{font-family:var(--mono);font-size:.78rem;color:var(--walnut);text-align:right;
  font-variant-numeric:lining-nums}
@media (max-width:900px){
  .rlist a{grid-template-columns:64px minmax(0,1fr) 8.5rem 3rem}
  .rthumb{width:64px}
  .rdest{display:none}
}
@media (max-width:600px){
  /* the description and the thumbnail are the row; the count and number step aside */
  .rlist a{grid-template-columns:56px minmax(0,1fr)}
  .rthumb{width:56px}
  .rmeta,.rid{display:none}
}

/* --- departments: the page's OPENING cut now, not its closing one -------- */
.dept--solo{padding-bottom:.5rem}

.pidx-depts{padding-block:clamp(2.2rem,4.6vw,3.6rem);border-top:1px solid var(--line)}
.pidx-depts h2{margin:.6rem 0 1.6rem}
.dept-note{font-family:var(--sans);font-size:.93rem;color:var(--ink-70);margin:-.9rem 0 1rem;max-width:64ch}
.dept-note.dim{font-size:.85rem;color:var(--walnut);margin:.8rem 0 0}
.dept-h .n{font-family:var(--sans);font-weight:700;font-size:.72rem;letter-spacing:.15em;
  text-transform:uppercase;color:var(--walnut)}


/* ==========================================================================
   PRODUCT DETAIL PAGES — 523 of them, generated by build/harvest-pdps.mjs.
   ========================================================================== */

/* The model name, where one is confirmed. It sits BENEATH the heading and
   never replaces it: the h1 is "<SKU> <Type>" because the SKU is the number a
   designer quotes and brings to the showroom, and this page's own note tells
   them to. Serif and generous, so the name still reads as information rather
   than as a label. Renders only for a confirmed name — see
   build/model-names.mjs for why a name has to be reviewed before it appears. */
.pdp-model{font-family:var(--sans);font-weight:500;font-size:clamp(1.15rem,2vw,1.5rem);
  line-height:1.3;color:var(--gold);margin:.5rem 0 0}

.pdp-top{display:grid;grid-template-columns:minmax(0,1.05fr) minmax(0,1fr);
  gap:clamp(1.5rem,4vw,3.2rem);align-items:start}
.pdp-hero-fig{margin:0;background:var(--mist);border:1px solid var(--line);border-radius:3px;
  overflow:hidden}
/* contain, not cover: catalogue shots are tight on white and cover crops rails
   and legs off the frame — the two things a designer is actually looking at. */
.pdp-hero-fig img{display:block;width:100%;aspect-ratio:4/3;object-fit:contain}
.pdp-copy p{margin:0 0 1rem;font-family:var(--sans);font-size:1.02rem;line-height:1.6;color:var(--ink-78)}
.pdp-copy p:first-child{font-size:clamp(1.08rem,1.7vw,1.28rem);color:var(--ink)}
.pdp-note{font-family:var(--sans)!important;font-size:.84rem!important;color:var(--walnut)!important;
  border-left:3px solid var(--gold);padding-left:.9rem;margin:1.4rem 0 1.5rem!important}

.pdp-facets{display:flex;gap:.4rem;flex-wrap:wrap;margin:1rem 0 0}
.pdp-facets span{font-family:var(--sans);font-weight:600;font-size:.68rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--ink);background:var(--gold);
  border-radius:999px;padding:.3rem .75rem}

.pdp-block{border-top:1px solid var(--line);margin-top:clamp(2rem,4vw,3rem);
  padding-top:clamp(1.5rem,3vw,2.2rem)}
.pdp-block h2{font-family:var(--sans);font-weight:700;font-size:.76rem;letter-spacing:.16em;
  text-transform:uppercase;color:var(--walnut);margin:0 0 1rem}

.spec-list{list-style:none;margin:0;padding:0;
  display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:.1rem 1.6rem}
.spec-list li{font-family:var(--sans);font-size:.97rem;line-height:1.5;
  padding:.5rem 0;border-bottom:1px solid var(--line)}

.dim-table{width:100%;border-collapse:collapse;margin-top:.6rem;max-width:620px}
.dim-table th,.dim-table td{text-align:left;font-size:.95rem;padding:.5rem .6rem;
  border-bottom:1px solid var(--line)}
.dim-table th{font-family:var(--sans);font-weight:600;font-size:.78rem;letter-spacing:.04em;
  text-transform:uppercase;color:var(--ink-70);width:45%}
.dim-table td{font-family:var(--mono);font-size:.88rem}

.pdp-gallery{display:grid;grid-template-columns:repeat(auto-fill,minmax(170px,1fr));gap:.8rem}
.pdp-gallery figure{margin:0;background:var(--shot-ground);border:1px solid var(--line);border-radius:2px;overflow:hidden}
.pdp-gallery img{display:block;width:100%;aspect-ratio:1/1;object-fit:contain}

@media (max-width:780px){ .pdp-top{grid-template-columns:1fr} }


/* ==========================================================================
   PRODUCT PAGE — "the showroom object" (design article 1b), 2026-08-17.
   Replaces the two-column image-beside-copy PDP. The argument the redesign
   makes: a catalogue of 523 items whose text reads "Pool Table · Collection
   213" cannot be told apart by its type line, so the OBJECT has to carry the
   page. The cutout is made enormous and allowed to interrupt the display type.
   ========================================================================== */

/* The department accent is set once, per page, as a local variable — so every
   rule below reads --acc and nothing has to know which department it is on.
   One page, one department (see DEPTS in build/chrome.mjs). */
.pdp2{--acc:var(--dept-pool)}
.pdp2.d-pool{--acc:var(--dept-pool)}
.pdp2.d-shuffle{--acc:var(--dept-shuffle)}
.pdp2.d-furniture{--acc:var(--dept-furniture)}
.pdp2.d-games{--acc:var(--dept-games)}
.pdp2.d-outdoor{--acc:var(--dept-outdoor)}

/* --- hero ----------------------------------------------------------------- */
/* PAPER, NOT CREAM — and this is a deliberate divergence from the mock.
   The design draws the hero on cream with a transparent cutout render floating
   over the headline. We do not have transparent cutouts: all 523 catalogue
   images are shot on PURE WHITE (#FFFFFF, verified at the corners), so on cream
   each one reads as a white card sitting on the page and the overlap effect dies.
   Two fixes were tried:
     mix-blend-mode:multiply  knocks the white ground out perfectly — and also
       knocks out white PRODUCTS. 154-PTB00001 is a white Rasson table; it went
       to a ghost with only its blue cloth left. Losing a product to a blend mode
       is worse than a visible edge.
     paper ground             #FFFEFB against the image's #FFFFFF differs by 4
       in one channel and nothing else, so the image's ground disappears into the
       page while every product keeps its body.
   Paper won. Revisit when the images are real cutouts, or after the ImageKit
   mirror makes background removal available — then this goes back to cream. */
/* THE HERO IS THE SHOT'S OWN GROUND. It was paper, chosen because #FFFEFB differs
   from the photography's #FFFFFF "by 4 in one channel and nothing else, so the
   image's ground disappears into the page". Measured against the real files, it
   nearly disappears — 4 steps of blue across a 880px flat plate is visible, and it
   is what Joshua saw. Matching the measured ground exactly costs nothing and leaves
   no edge at all. */
.pdp-hero{background:var(--shot-ground);padding-top:clamp(1.6rem,3.5vw,3rem)}
.pdp-crumb{display:flex;justify-content:space-between;align-items:baseline;gap:1rem;
  font-family:var(--mono);font-size:.8rem;color:var(--walnut);position:relative;z-index:2}
.pdp-crumb a{color:var(--walnut);text-decoration:none}
.pdp-crumb a:hover{text-decoration:underline}
/* the department tick — 22x3px of the accent, the page's only wayfinding mark */
.dept-tick{display:inline-block;width:22px;height:3px;background:var(--acc);
  vertical-align:middle;margin-right:.65rem}
.pdp-crumb .sku{font-size:clamp(.85rem,1.6vw,1.25rem);color:var(--ink);white-space:nowrap}

/* THE NAME. 168px on a 1280 canvas is 13.1vw — carried as vw so the type keeps
   its proportion to the cutout it overlaps at every width, with a floor that
   keeps it readable on a phone and a ceiling so it stops growing past 1440. */
/* THE TYPE SITS IN FRONT OF THE OBJECT. (Joshua, 2026-08-18: "the Text gets Cut
   off by the IMAGE. Seem like the layer is an issue. The image needs to go behind
   the Text.") The mock draws a transparent cutout floating over the headline, and
   the build stacked it that way — cutout above, name below. But the note at the top
   of this block already records that we have no transparent cutouts: every
   catalogue shot is on pure white. So the photograph was not overlapping the
   headline, it was ERASING it — the last digits of the SKU and the tail of the
   "model name pending review" line disappeared under an opaque white rectangle at
   every width above 640. Reversed: the name and the pending line are above, the
   photograph is beneath. The composition the mock wanted survives — object and
   type still interlock — and nothing is lost, because the type crosses the
   image's own near-white ground, where ink reads at full contrast. */
.pdp-name{font-family:var(--sans);font-weight:700;font-size:clamp(2.6rem,13vw,10.5rem);
  letter-spacing:-.03em;line-height:.95;margin:clamp(.9rem,1.9vw,1.5rem) 0 0;
  position:relative;z-index:2;text-transform:none;text-wrap:balance}
/* SKU-LED is the state that ships today: no model name is confirmed, so the
   number a designer actually quotes is the headline. 92px of a 1280 canvas =
   7.2vw. It is smaller than the name-led state on purpose — a part number set
   at 168px is shouting a serial. */
.pdp-name.is-sku{font-size:clamp(1.9rem,7.2vw,5.75rem);letter-spacing:-.025em;line-height:.98}
/* Above the photograph for the same reason as the name, and larger than the .75rem
   it was: this line is the page's honest admission that the model name is not
   confirmed, and it was set smaller than the breadcrumb above it. */
.pdp-pending{font-family:var(--mono);font-size:.85rem;color:var(--walnut);
  margin:.7rem 0 0;letter-spacing:.02em;position:relative;z-index:2}

/* THE CUTOUT, BEHIND the type. The negative top margin is what makes the overlap;
   it is proportional to the headline (-52px under a 168px line) so the two move
   together. It sits BELOW the name in the stack — see the note on .pdp-name for
   why that had to be reversed — and `contain` because these are catalogue shots
   that must not be cropped. */
.pdp-cutout{position:relative;z-index:0;margin:clamp(-3.25rem,-4vw,-1.1rem) auto 0;
  display:flex;justify-content:center;width:min(100%,880px)}
.pdp-cutout img{width:100%;height:auto;aspect-ratio:880/470;object-fit:contain;display:block}
/* THE OVERLAP IS STILL A WIDE-SCREEN COMPOSITION. Below 640 the breadcrumb and the
   "model name pending review" line wrap to two lines, and pulling a photograph up
   over stacked wrapped type is illegible whichever way round the layers go. There
   is no room for an object to interrupt type at phone width, so it stops trying.
   This rule was the ONLY place the erasure had been fixed — which is why the bug
   read as a phone-width success and a desktop failure. */
@media (max-width:640px){
  .pdp-cutout{margin-top:.6rem}
}
/* The material line and the trade chip, under a hairline. */
.pdp-matline{display:flex;justify-content:space-between;align-items:center;gap:1.25rem;
  flex-wrap:wrap;border-top:1px solid var(--line);
  margin-top:clamp(1.2rem,2vw,1.6rem);padding:clamp(1.1rem,1.9vw,1.6rem) 0 clamp(1.4rem,2.4vw,2.1rem)}
.pdp-mat{font-family:var(--mono);font-size:.85rem;letter-spacing:.04em;color:var(--ink)}
/* THE PRICING LINE AS A CREDENTIAL, not an apology. There is no price on this
   site; this says why in the register of a certificate. */
/* flex:0 1 auto, not 0 0 auto — the chip must be allowed to shrink. Enlarging its
   label for legibility pushed it 20px past a 320px viewport, hidden from view by
   overflow-x:hidden on <body> and caught only by measuring. It shrinks and its
   label wraps rather than running off the edge. */
.trade-chip{display:inline-flex;align-items:center;gap:.6rem;flex:0 1 auto;min-width:0;
  border:1px solid rgba(31,36,33,.25);padding:.5rem .875rem}
.trade-chip .dia{width:8px;height:8px;background:var(--gold);transform:rotate(45deg);flex:0 0 auto}
/* Larger where there is room, back to its old size where there is not: this label
   is 30 characters of tracked mono and simply does not fit a phone at .74rem. */
.trade-chip span{font-family:var(--mono);font-size:clamp(.62rem,1.9vw,.74rem);
  letter-spacing:.1em;text-transform:uppercase;color:var(--ink);min-width:0}

/* --- numbered sections ---------------------------------------------------- */
.pdp-sec{padding-block:clamp(1.9rem,4vw,3rem)}
.pdp-sec.on-cream{background:var(--cream);border-top:1px solid var(--line)}
.pdp-sec.on-ink{background:var(--ink);color:var(--cream)}
.sec-eyebrow{font-family:var(--mono);font-size:.7rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--acc);margin:0 0 1rem}
/* On ink the accent fails contrast (1.86-2.77:1), so the eyebrow is gold there.
   This is the ban from the token block, enforced rather than remembered. */
.pdp-sec.on-ink .sec-eyebrow{color:var(--gold)}

/* 02 Specification — two columns of hairline rows. */
.spec-2col{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  column-gap:clamp(1.5rem,4.4vw,3.5rem)}
.spec-line{display:flex;justify-content:space-between;align-items:baseline;gap:1rem;
  padding:.75rem 0;border-bottom:1px solid var(--line)}
/* LARGER, BOTH SIDES. (Joshua, 2026-08-18: "The detail of the Product has very
   very small text. Make it larger and readable please.") The label was .7rem —
   11.2px — and the value .875rem at weight 500. This table is the densest real
   information on the page and it was the smallest type on it. Label .82rem, value
   1rem at 600, and the row breathes a little more. */
.spec-line{padding:.9rem 0}
.spec-line b{font-family:var(--mono);font-weight:400;font-size:.82rem;color:var(--walnut);
  white-space:nowrap}
.spec-line span{font-family:var(--sans);font-weight:600;font-size:1rem;text-align:right}
@media (max-width:640px){.spec-2col{grid-template-columns:1fr}}

/* THE SIZE ROW, inside 02 Specification. The chips moved out of the ink band
   because a size is a specification, not a chooser — see harvest-pdps.mjs. They
   keep the chip form the ratified design draws, but on a light ground now, so the
   border and label come off the light palette instead of the reversed one. */
.spec-sizes{margin-top:clamp(1.4rem,2.4vw,2rem);padding-top:clamp(1.1rem,2vw,1.5rem);
  border-top:1px solid var(--line)}
.spec-sizes-lbl{font-family:var(--mono);font-size:.82rem;color:var(--walnut);margin:0 0 .9rem}
.spec-sizes .size-chip{color:var(--ink);border-color:rgba(31,36,33,.25)}

/* 03 Cloth — the ink band. Sizes used to share it; what is left is the one thing
   here that is genuinely a chooser rather than a fact. */
.opt-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  gap:clamp(1.75rem,4.4vw,3.5rem)}
.opt-lbl{font-family:var(--mono);font-size:.7rem;color:rgba(250,248,243,.7);margin:0 0 .75rem}
.size-chips{display:flex;gap:.75rem;flex-wrap:wrap}
.size-chip{font-family:var(--mono);font-size:.82rem;color:var(--cream);
  border:1px solid rgba(250,248,243,.3);padding:.75rem 1.4rem}
/* The gold border marks the size standing on the floor in Dallas — the reason
   a designer would come and look at this one rather than order it. */
.size-chip.is-sel{border-color:var(--gold)}
.cloth-row{display:flex;gap:1rem;flex-wrap:wrap}
.swatch{display:flex;flex-direction:column;gap:.4rem;align-items:center}
.swatch i{width:34px;height:34px;border-radius:2px;display:block}
.swatch.is-dark i{border:1px solid rgba(250,248,243,.25)}
.swatch.is-sel i{box-shadow:0 0 0 1px var(--gold)}
.swatch span{font-family:var(--mono);font-size:.6rem;color:rgba(250,248,243,.75)}
/* THE SWATCHES ARE ILLUSTRATIVE and the page has to say so until they are
   photographed off the real cloth wall. Ruled, not optional. */
.pdp-disclose{font-family:var(--mono);font-size:.66rem;line-height:1.7;
  color:rgba(250,248,243,.6);margin:clamp(1.4rem,2.6vw,2rem) 0 0;max-width:62ch}
.pdp-sec.on-cream .pdp-disclose{color:var(--walnut)}
@media (max-width:640px){.opt-grid{grid-template-columns:1fr}}

/* 04 Furnish the room — three small tiles and the line that explains them. */
.furnish{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:1rem}
.furnish a{text-decoration:none;color:inherit;display:block}
.furnish .shot{display:block;background:var(--shot-ground);border:1px solid var(--line)}
.furnish .shot img{width:100%;height:clamp(90px,11vw,120px);object-fit:contain;display:block}
.furnish figcaption{font-family:var(--mono);font-size:.66rem;color:var(--walnut);
  margin-top:.5rem;line-height:1.5}
.furnish a:hover .shot{border-color:var(--gold)}
.furnish-say{font-family:var(--sans);font-weight:500;font-size:.875rem;
  color:var(--walnut);margin:.9rem 0 0}
@media (max-width:560px){.furnish{grid-template-columns:1fr 1fr}}


/* ==========================================================================
   CATEGORY PAGE — design article 2a, 2026-08-18. Generated by
   build/category-page.mjs for all 23 pages.
   The collections-led structure is unchanged; what changes is that the page
   opens on a photograph instead of an ink type band, the chapter grounds
   alternate by RULE rather than per-page authoring, and an A–Z grid closes the
   catalogue before the ask.
   ========================================================================== */

.cat2{--acc:var(--dept-pool)}
.cat2.d-pool{--acc:var(--dept-pool)}
.cat2.d-shuffle{--acc:var(--dept-shuffle)}
.cat2.d-furniture{--acc:var(--dept-furniture)}
.cat2.d-games{--acc:var(--dept-games)}
.cat2.d-outdoor{--acc:var(--dept-outdoor)}

/* --- the photographic hero ------------------------------------------------ */
.cat-hero{min-height:clamp(360px,44vh,520px);display:flex;align-items:flex-end}
.cat-hero>.veil{background:var(--veil-hero)}
/* A BRIGHTER PHOTOGRAPH NEEDS A DEEPER VEIL, and which one is arithmetic rather than
   taste. Measured on the veiled band with the copy hidden — sampling the rendered
   composite, not the source file, and not the text's own glyphs — the products hero's
   photograph is a sunlit loft whose brightest region composites to (109,107,104) under
   the standard .62 veil. That leaves the cream-88 lede at 4.03:1, under the 4.5:1 body
   threshold, and the gold count line at 2.21:1, which is not close.
   Two changes, both measured after: the veil goes to .74 for this hero only, and the
   count line goes cream. Gold is an accent and cream is the site's text colour on
   dark; §7 permits gold to letter on a veiled photograph, but that permission was
   written against th-sb, which is a dark room. It does not survive a bright one, and
   the ban on gold as text is a contrast rule, so it follows the contrast.
   The gold tick stays: it is a rule, not text.
   Only the veil is overridden here. The count line needed no override in the end —
   see the note on .cat-count for why it was already cream everywhere. */
.cat-hero.is-bright>.veil{background:rgba(20,16,11,.74)}

/* SIXTEEN BY NINE, which is the photograph's own shape. (Joshua, 2026-08-19: "Make the
   Block bigger please like the full 16:9.") The standard hero tops out at 520px, so at
   1440 it was a 2.77 letterbox holding a 1.79 image — the crop was throwing away the
   top and bottom of the room to fit a band that was never as tall as its picture.
   min-height rather than aspect-ratio, deliberately: `.band` sets overflow:hidden, so a
   fixed aspect box would CLIP the copy at any width where the copy is taller than the
   ratio allows, and that is exactly what happens on a phone. A min-height can only be
   exceeded, never undercut, so the band is 16:9 wherever the copy fits inside it and
   grows past 16:9 where it does not.
   The 380px floor is for narrow screens: 16:9 of 390px is 219px, which cannot hold a
   heading, a four-line lede and a count line. The 1080px ceiling is 16:9 of 1920 —
   past that width the band holds still and the photograph crops again rather than a
   front door growing to 1440px tall on a large monitor. */
.cat-hero.is-16x9{min-height:min(max(56.25vw,380px),1080px)}
.cat-hero .wrap{padding-block:clamp(2rem,4.4vw,3.5rem)}
.cat-crumb{display:flex;justify-content:space-between;align-items:baseline;gap:1rem;
  flex-wrap:wrap;font-family:var(--mono);font-size:.7rem;color:var(--cream-88);margin:0 0 1rem}
.cat-crumb a{color:var(--cream);text-decoration:none;border-bottom:1px solid rgba(250,248,243,.4)}
/* THE TICK IS GOLD HERE, not the department accent. On a veiled photograph the
   accent lands at 2:1 or worse and simply disappears; gold is the one accent
   that reads on this ground. The department's own colour takes over the moment
   the page reaches a light ground, below. */
.cat-crumb .tick{display:inline-block;width:22px;height:3px;background:var(--gold);
  vertical-align:middle;margin-right:.65rem}
.cat-hero h1{font-size:var(--h1-hero);line-height:.98;letter-spacing:-.03em;
  color:#fff;margin:0;max-width:16em;text-transform:none}
.cat-hero .lede{color:var(--cream-88);max-width:56ch;margin:1.1rem 0 0}
/* THE COUNT IS A UNION, AND SAYS SO WHERE IT IS ONE. Tiles can sum higher than
   the real product count because collections overlap; the generator only prints
   the "tiles sum to N" half when the two numbers actually differ.
   NO COLOUR IS DECLARED HERE, and that is a correction rather than an omission. This
   rule carried `color:var(--gold)` from the day it was written and it never once took
   effect: `.band p` in grfp.css is a class plus an element, which outranks a bare
   class, so every count line on all 24 of these pages has always rendered cream. The
   declaration was removed rather than given the specificity to win, because cream is
   the better answer on this ground and the measurements say so — gold at 11px over the
   products hero's sunlit photograph comes to 2.21:1 at the brightest pixel against
   4.5:1 required, where cream comes to 6.27:1. A dead rule that would have failed
   contrast if it had ever worked is worth deleting, not resurrecting. */
.cat-count{font-family:var(--mono);font-size:.7rem;letter-spacing:.06em;
  margin:1.1rem 0 0}

/* --- the type plate, on the 23 category pages ----------------------------- */
/* NO PHOTOGRAPH, AND NO INK EITHER. (Joshua, 2026-08-19: "remove the Header Hero Image
   ... JUST THE HEADLINE.") The literal reading is the band with its picture deleted, which
   is an ink rectangle with a heading in it -- correct, and dull, and identical 23 times.
   The department's colour is the more useful answer: it is the only device that keys 23
   pages to 5 departments with nothing photographic in it, and --acc is already declared on
   .cat2 above, so this costs one property.
   ALL TYPE IS FULL CREAM, and that is measured rather than assumed. Cream on the five
   accents: pool 7.40:1, furniture 7.99:1, games 5.92:1, shuffle 5.53:1, outdoor 5.37:1 --
   every one clear of the 4.5:1 body threshold. The photographic hero letters its lede and
   crumb in --cream-88; composited on these grounds that is 4.58:1 on outdoor and 4.70:1 on
   shuffle, which passes by 0.08 and is not worth having, so both are overridden back to
   cream here. Gold is absent on purpose: 2.38-3.53:1 on these five, an ink-only accent by
   the table in grfp.css. The tick follows the same rule and goes cream.
   Sized by its type. There is no image for the band to be the shape of, so there is no
   --ar, no is-whole and no veil -- and no 1080px of band holding nothing. */
.cat-plate{background:var(--acc)}
.cat-plate .wrap{padding-block:clamp(2.4rem,6vw,4.6rem)}
/* display:block, because the plate's crumb is now one run of text rather than two
   halves needing to be pushed apart; the shared rule is flex with space-between. */
.cat-plate .cat-crumb{display:block;color:var(--cream);margin:0 0 clamp(1.5rem,4vw,2.6rem)}
.cat-plate .cat-crumb .tick{background:var(--cream)}
.cat-plate h1{font-size:var(--h1-hero);line-height:.98;letter-spacing:-.03em;
  margin:0;max-width:16em;text-transform:none}
.cat-plate .lede{max-width:56ch;margin:clamp(1.3rem,3vw,1.9rem) 0 0;text-wrap:pretty}

/* THE DIMENSION LINE. A drafting device, not an <hr>: the figure sits on the same left
   axis as the heading and the rule runs from it out to the right margin, capped at both
   ends the way a measurement is written on a shop drawing. The caps are drawn on the
   rule's own box, which is why the rule is an empty span rather than a border on the
   paragraph. It wraps rather than pushing: the longest count line on the site is the
   union disclosure ("N products - tiles sum to M - collections overlap"), which at 320px
   is wider than the plate, so the value shrinks and the rule takes what is left. */
.cat-measure{display:flex;align-items:center;flex-wrap:wrap;gap:.9rem;
  margin:clamp(1.4rem,3.4vw,2.1rem) 0 0}
.cat-measure .m-val{flex:0 1 auto;min-width:0;font-family:var(--mono);font-size:.78rem;
  letter-spacing:.06em;color:var(--cream)}
/* 8rem of flex-basis, not 2.5rem, and the difference is the whole behaviour. Flex breaks
   a line by comparing hypothetical sizes against the container, so a small basis lets the
   rule stay on the heading line and shrink to a 46px stub with a cap at each end -- which
   reads as a rendering artefact, not a measurement. At 8rem it cannot fit beside a long
   count on a phone, so it wraps and spans the full plate instead. Both outcomes are a
   dimension line; the stub was neither. */
.cat-measure .m-rule{position:relative;flex:1 1 8rem;height:1px;
  background:rgba(250,248,243,.62)}
.cat-measure .m-rule::before,.cat-measure .m-rule::after{content:"";position:absolute;
  top:-4px;width:1px;height:9px;background:rgba(250,248,243,.62)}
.cat-measure .m-rule::before{left:0}
.cat-measure .m-rule::after{right:0}

/* THE CLEAR BUTTON, WHICH WAS NEVER READABLE. `.facet-clear` is declared once, globally, in
   --walnut -- and catalog.js only ever injects it into [data-facets], which only ever exists
   inside this band. So the one place that button can appear has always been a dark ground:
   on the veiled photograph it sat near 1.2:1, and on the department plate it measures
   1.07:1 on pool, which is invisible rather than merely low. Walnut is a light-ground
   colour; the chips beside it are already cream, so the control joins them.
   Scoped to the plate rather than fixed on the global rule, which stays correct for any
   light-ground use of the class later. */
.cat-plate .facet-clear{color:var(--cream)}

/* --- chapter grounds, by rule -------------------------------------------- */
/* paper -> ink -> cream, every second collection band ink. Declared once here
   rather than authored per page: 23 pages with hand-set grounds would drift the
   first time a collection was added. */
.cband{border-top:1px solid var(--line)}
.cband:nth-of-type(odd){background:var(--paper)}
.cband:nth-of-type(even){background:var(--ink);color:var(--cream);border-top-color:transparent}
.cband:nth-of-type(4n+3){background:var(--cream)}
.cband:nth-of-type(even) .cband-n,
.cband:nth-of-type(even) h2{color:var(--cream)}
.cband:nth-of-type(even) .cband-say,
.cband:nth-of-type(even) .cband-facts span{color:var(--cream-88)}
.cband:nth-of-type(even) .cband-key,
.cband:nth-of-type(even) .cband-n span,
.cband:nth-of-type(even) .cband-facts b{color:rgba(250,248,243,.7)}
.cband:nth-of-type(even) .cband-facts li{border-bottom-color:var(--line-d)}
.cband:nth-of-type(even) .band-more a{color:var(--cream)}
/* the accent eyebrow only exists on the light chapters — never text on ink */
.cband-key{color:var(--acc)}
.cband:nth-of-type(even) .cband-key{color:var(--gold)}
/* cards flip to paper on the ink chapters so they never vanish into the ground */
.cband:nth-of-type(even) .ecard{background:var(--paper);color:var(--ink);border-color:transparent}
.cband:nth-of-type(even) .ecard:hover{box-shadow:var(--sh-card-d)}

/* --- 03 the A–Z grid ----------------------------------------------------- */
/* Four up, contained cutouts, and a tile that says how many are not shown
   rather than pretending the grid is the catalogue. */
.azgrid{background:var(--cream);border-top:1px solid var(--line)}
.az-h{display:flex;justify-content:space-between;align-items:baseline;gap:1rem;
  flex-wrap:wrap;margin:0 0 1.4rem}
.az-h .sec-m{color:var(--acc);margin:0}
.az-note{font-family:var(--mono);font-size:.66rem;color:var(--walnut);margin:0}
.az{list-style:none;margin:0;padding:0;display:grid;
  grid-template-columns:repeat(4,minmax(0,1fr));gap:1.25rem}
.az a{display:block;border:1px solid var(--line);background:var(--mist);padding:.875rem;
  text-decoration:none;color:var(--ink);height:100%;
  transition:transform .22s cubic-bezier(.25,1,.5,1),box-shadow .22s cubic-bezier(.25,1,.5,1)}
.az a:hover{transform:translateY(-3px);box-shadow:var(--sh-card)}
.az img{width:100%;height:clamp(120px,14vw,180px);object-fit:contain;display:block;
  background:var(--shot-ground)}
.az b{display:block;font-family:var(--mono);font-weight:400;font-size:.7rem;
  margin-top:.7rem;color:var(--ink)}
.az i{display:block;font-style:normal;font-family:var(--mono);font-size:.62rem;
  color:var(--walnut);margin-top:.2rem}
.az .more{border:1px solid var(--line);display:flex;align-items:center;justify-content:center;
  font-family:var(--mono);font-size:.7rem;color:var(--walnut);text-align:center;padding:1rem;
  min-height:120px}
@media (max-width:900px){.az{grid-template-columns:repeat(3,minmax(0,1fr))}}
@media (max-width:640px){.az{grid-template-columns:repeat(2,minmax(0,1fr))}}

/* --- the filter rail on the hero ----------------------------------------- */
/* Cream-50% borders on the photograph, and it renders ONLY when facet data
   exists — the rail self-hides rather than shipping an empty control. */
.cat-chips{display:flex;gap:.5rem;flex-wrap:wrap;margin:1.4rem 0 0}
.cat-chips .chip{background:transparent;color:var(--cream);
  border-color:rgba(250,248,243,.5);border-radius:0}
.cat-chips .chip:hover{border-color:var(--gold)}
.cat-chips .chip[aria-pressed="true"]{background:var(--cream);color:var(--ink);border-color:var(--cream)}

/* IMAGE-LED (design 5a) — the same grid one size up. The tiles are the page's
   only argument, so they get the height the empty attribute line would have
   wasted, and the caption carries the SKU alone. */
.az.is-wall img{height:clamp(150px,20vw,260px)}


/* ==========================================================================
   COLLECTION HUB — design article 3a, 2026-08-18. Generated by
   build/collection-hub.mjs for collections 57, 62 and 232, which were flat
   hand-built grids of 65, 64 and 89 cards until now.
   The chapters are the data's own type field, bucketed into three families.
   ========================================================================== */

.hubband{padding-block:clamp(2rem,4.4vw,3.4rem);border-top:1px solid var(--line)}
.hubband.is-tables{background:var(--cream)}
/* Seating on ink, in the design's order. Cards flip to paper so they never
   vanish into the ground, exactly as the category chapters do. */
.hubband.is-seating{background:var(--ink);color:var(--cream);border-top-color:transparent}
.hubband.is-seating .sec-m{color:var(--gold)}
.hubband.is-seating .ecard{background:var(--paper);color:var(--ink);border-color:transparent}
.hubband.is-seating .ecard:hover{box-shadow:var(--sh-card-d)}
.hubband.is-accessories{background:var(--paper)}
/* A HUB WEARS NO DEPARTMENT ACCENT. "One page, one department" cannot apply here:
   a collection deliberately crosses departments — that is its whole argument, a
   room furnished end to end in one design language. So the chapter eyebrows take
   the neutral label colour the site already uses for mono labels on light
   (walnut, 6.9:1 on cream) rather than borrowing an accent that would claim the
   page belongs to one department. Gold on the ink chapter, 6.57:1. */
.hubband .sec-m{color:var(--walnut)}

/* 3-up, 220px, contained: these are catalogue shots and cover would crop the
   rails and legs off the two things a designer is looking at. */
.hub-grid{list-style:none;margin:0;padding:0;display:grid;
  grid-template-columns:repeat(3,minmax(0,1fr));gap:1.25rem}
.hub-grid .ecard .shot img{aspect-ratio:auto;height:clamp(150px,17vw,220px);object-fit:contain}
@media (max-width:820px){.hub-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:480px){.hub-grid{grid-template-columns:1fr}}

/* ACCESSORIES ARE HAIRLINE ROWS. Fourteen cue racks photographed on white make
   fourteen near-identical tiles; a line of type says the same thing and lets a
   designer scan the whole list at once. The 12px hover indent is the site's
   row-hover rule, unchanged. */
.hubrows{list-style:none;margin:0;padding:0;border-top:1px solid var(--gold)}
.hubrows li{border-bottom:1px solid var(--line)}
.hubrows a{display:flex;align-items:baseline;gap:1.25rem;padding:.7rem .4rem;
  text-decoration:none;color:var(--ink);
  transition:padding-left .18s ease,background-color .16s ease}
.hubrows a:hover{padding-left:.75rem;background:var(--mist)}
.hubrows b{font-family:var(--mono);font-weight:400;font-size:.78rem;
  min-width:11rem;flex:0 0 auto}
.hubrows span{font-family:var(--sans);font-weight:500;font-size:.9rem;color:var(--ink-78)}
@media (max-width:520px){
  .hubrows a{flex-direction:column;gap:.15rem}
  .hubrows b{min-width:0}
}
@media (prefers-reduced-motion:reduce){.hubrows a:hover{padding-left:.4rem}}


/* ==========================================================================
   CUSTOM BUILT — design article 3b, 2026-08-18. Hand-built page, direct edit.
   The studio conversation shown rather than described: four numbered steps as a
   spine, and the materials as labelled swatches.
   ========================================================================== */

/* THE HERO IS A PHOTOGRAPH NOW (Joshua, 2026-08-19). It was type on cream, mirroring the
   Gallery's — but the Gallery has a reason for that (its own photography is the argument, so
   a hero image would compete with the work below it) and this page does not. A page whose
   whole claim is that a table is made for one particular room should open on a table in a
   particular room. Same device as every other hero here: image, one flat veil, copy over it,
   bottom-aligned.
   THE VEIL IS .74, MEASURED against this photograph and not inherited. It is a sunlit
   plastered room — pale walls, pale floor, pale cloth — which is the brightest ground on the
   site after the products hero, and it needed the same treatment for the same reason. The
   figures are below. */
.cb-hero{display:flex;align-items:flex-end}   /* height comes from .is-whole */
.cb-hero>.veil{background:var(--veil-hero)}
.cb-hero.is-bright>.veil{background:rgba(20,16,11,.74)}
.cb-hero .wrap{padding-block:clamp(2rem,4vw,3.25rem)}
/* GOLD LETTERING DOES NOT SURVIVE THIS PHOTOGRAPH. §7 permits gold to letter on a veiled
   photograph, and that permission was written against th-sb, a dark room. Measured here at
   the worst pixel behind the copy it comes to 3.47:1 against the 4.5:1 a small line needs —
   the identical finding as the products hero, and resolved the same way. The kicker letters
   in cream; the TICK stays gold, because a 22x3px bar is a rule and the ban is on gold as
   text. */
.cb-hero .kicker-m{color:var(--cream)}
.cb-hero .kicker-m .tick{display:inline-block;width:22px;height:3px;background:var(--gold);
  vertical-align:middle;margin-right:.65rem}
.cb-hero h1{font-size:var(--h1-hero);line-height:.98;letter-spacing:-.03em;
  margin:1.25rem 0 1rem;text-transform:none;color:#fff}
.cb-hero .lede{max-width:52ch;color:var(--cream-88)}

/* THE RANGE STRIP — three finished pieces, evidencing the claim above it. Three items in
   three columns resolves flush by definition, which is why it is three and not four.
   Captions sit BELOW the frame, as every caption on this site does, and each names which
   kind of thing it is: the strip exists to show that "beyond pool tables" means something. */
/* Paper, so the run reads paper (step 4) -> cream (split) -> paper (range) -> ink
   (close), with no ground repeating against its neighbour. */
.cb-range{background:var(--paper);border-top:1px solid var(--line);
  padding-block:clamp(2rem,4vw,3rem)}
.cb-range-grid{list-style:none;margin:1rem 0 0;padding:0;display:grid;
  grid-template-columns:repeat(3,minmax(0,1fr));gap:1.25rem}
.cb-range-grid figure{margin:0}
.cb-range-grid img{width:100%;height:clamp(180px,19vw,270px);object-fit:cover;display:block;
  background:var(--mist)}
.cb-range-grid figcaption{font-family:var(--mono);font-size:.72rem;letter-spacing:.04em;
  color:var(--walnut);margin-top:.7rem}
@media (max-width:820px){.cb-range-grid{grid-template-columns:1fr}}

/* 01 Beyond pool tables — copy beside a tall photograph running to the edge. */
/* Cream, not paper: since the move on 2026-08-24 this follows Step 4, which is
   on-paper, and two paper grounds in a row read as one long section. */
.cb-split{background:var(--cream);border-top:1px solid var(--line);
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
.cb-split-copy{padding:clamp(1.9rem,3.4vw,2.75rem) clamp(1.25rem,4vw,3.5rem);
  display:flex;flex-direction:column;justify-content:center}
.cb-split-copy h2{margin:.9rem 0 1rem}
.cb-split-copy p{max-width:36em;color:var(--ink-78)}
/* THE IMAGE MUST NOT DRIVE THE HEIGHT — and lowering min-height did not achieve that,
   which is why this block was still 961px tall after I reported it fixed. Joshua flagged
   it on 2026-08-18 as "WAY TO BIG... way too much white space and the image is to big";
   I cut the figure's min-height and never measured the rendered block.
   min-height only sets a floor. The image is a grid-item carrying height:100%, which
   cannot resolve while the row is still being sized, so the browser fell back to the
   image's intrinsic ratio at full column width — 720px wide at 3:4 is 960px tall — and
   THAT became the row. Three lines of copy then floated in the middle of a 961px column,
   which is precisely the fault that was reported.
   Out of flow, exactly as .dp-fig had to be. The copy sets the height and the photograph
   fills whatever that turns out to be. Same defect, same fix, second surface. */
.cb-split figure{margin:0;min-width:0;position:relative;
  min-height:clamp(240px,26vw,400px);background:var(--mist)}
.cb-split img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block}
@media (max-width:820px){
  .cb-split{grid-template-columns:1fr}
  .cb-split figure{min-height:clamp(240px,42vw,320px)}
}

/* The steps. Numbered by the section eyebrow, not by a counter, because the
   numbering runs across the whole page (01–07) and not just the steps. */
/* RHYTHM IS THE RATIO, not more air everywhere. Every section used the same 57.6px top
   and bottom while a step's own media sat 32px under its copy — 1.8:1, too close to read
   as grouping. The section padding opens and the internal gap closes, so a step's media
   belongs to that step and the gap between steps reads as a break. */
.cb-step{padding-block:clamp(2.75rem,5.6vw,4.5rem);border-top:1px solid var(--line)}
.cb-step.on-cream{background:var(--cream)}
.cb-step.on-paper{background:var(--paper)}
.cb-step h2{line-height:1.04;letter-spacing:-.025em;
  margin:0 0 1.1rem}
/* 68ch, NOT 62em, AND THE UNIT WAS THE WHOLE BUG. An em is the type's own size; a ch is
   the width of a character. 62em at .97rem resolved to 962px, which measured 112
   characters per line on all four of these paragraphs — half again over the 65-75 an eye
   tracks without losing its place. 68ch is 68 characters by definition, at any size. */
.cb-step p.body{font-size:.97rem;line-height:1.7;max-width:68ch;color:var(--ink-78);margin:0}

/* SIDE BY SIDE, AND THE CONTENT PICKS WHICH STEPS GET IT. Four consecutive steps built
   identically — heading, one wide paragraph, a row of media underneath — is the monotony
   that made this page read as a wall of text. Capping the measure at 68ch fixed the
   reading and left ~500px of empty column beside every paragraph, which would have traded
   one fault for another.
   So the two steps whose media is one or two items put that media in the empty column,
   and the two with three or four keep it full width beneath. The page alternates stacked /
   beside / stacked / beside without a rule being imposed on it: four factory photographs
   need the whole width, one delivery shot does not. */
.cb-step.is-side .wrap{display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,.8fr);
  grid-template-areas:"head media" "body media";
  column-gap:clamp(1.75rem,4vw,3.25rem);align-items:start}
.cb-step.is-side h2{grid-area:head}
.cb-step.is-side p.body{grid-area:body}
.cb-step.is-side .cb-media{grid-area:media;margin-top:.4rem}
/* in a narrower column the two renders stack rather than shrinking to a pair of stamps */
.cb-step.is-side .cb-media.two{grid-template-columns:1fr}
.cb-step.is-side .cb-media.two img{height:clamp(200px,17vw,260px)}
@media (max-width:900px){
  .cb-step.is-side .wrap{grid-template-columns:1fr;grid-template-areas:"head" "body" "media"}
  .cb-step.is-side .cb-media{margin-top:clamp(1.1rem,1.8vw,1.4rem)}
  .cb-step.is-side .cb-media.two{grid-template-columns:repeat(2,minmax(0,1fr))}
}

/* Step 1's three cards: a mist header strip, centred, over verbatim bullets. */
.cb-cards{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:1.5rem;
  margin-top:clamp(1.2rem,2vw,1.6rem)}
.cb-card{border:1px solid var(--line);background:var(--paper)}
.cb-card h3{background:var(--mist);border-bottom:1px solid var(--line);
  padding:.875rem;text-align:center;font-family:var(--sans);font-weight:700;
  font-size:.875rem;margin:0}
.cb-card-in{padding:1.1rem 1.15rem 1.3rem;text-align:center}
.cb-card .sub{font-family:var(--mono);font-size:.66rem;letter-spacing:.12em;
  text-transform:uppercase;color:var(--walnut);margin:0 0 .7rem}
.cb-card .lines{font-size:.85rem;line-height:2;color:var(--ink-78);margin:0}
@media (max-width:820px){.cb-cards{grid-template-columns:1fr}}

/* Step media: the two elevations, the four factory images, the delivery shot.
   Anything AI-generated or illustrative keeps the .is-render caption marker the
   page already established — a render is never passed off as a photograph. */
.cb-media{display:grid;gap:1.25rem;margin-top:clamp(1.1rem,1.8vw,1.4rem)}
.cb-media.two{grid-template-columns:repeat(2,minmax(0,1fr))}
.cb-media.four{grid-template-columns:repeat(4,minmax(0,1fr))}
/* FIVE is the making sequence on Custom Built — select, cut, base, rail, finish —
   and it is the one count where this file's usual ladder does not work: with five
   items every column count between 5 and 1 leaves a ragged last row, so there is no
   honest middle step to break to. Exact at five, then straight to one. */
.cb-media.five{grid-template-columns:repeat(5,minmax(0,1fr));gap:.9rem}
.cb-media.five img{height:clamp(150px,13vw,190px)}
.cb-media figure{margin:0}
.cb-media img{width:100%;display:block;background:var(--mist);object-fit:cover}
.cb-media.two img{height:clamp(240px,30vw,400px);object-fit:contain;background:var(--paper)}
.cb-media.four img{height:clamp(150px,17vw,230px)}
.cb-media.one img{height:clamp(200px,22vw,300px)}
/* .one crops to a fixed height, which is right when the box matters more than the
   frame. .is-ar is the opposite case: the height comes from the file's own ratio, so
   a 16:9 photograph in a narrow side column keeps both its edges. */
.cb-media.one.is-ar img{height:auto;aspect-ratio:var(--ar,1.7778)}
.cb-media figcaption{font-family:var(--mono);font-size:.62rem;letter-spacing:.08em;
  text-transform:uppercase;color:var(--walnut);margin-top:.55rem;line-height:1.5}
@media (max-width:760px){
  .cb-media.four{grid-template-columns:repeat(2,minmax(0,1fr))}
  .cb-media.two{grid-template-columns:1fr}
  /* .five goes to one, not two: five in two columns is 2+2+1, the ragged row again */
  .cb-media.five{grid-template-columns:1fr;gap:1.25rem}
  .cb-media.five img{height:auto;aspect-ratio:1.7917}
}

/* ==========================================================================
   04 THE MATERIALS RAIL — ink, with the three material families behind chips.
   NO JAVASCRIPT. The chips are labels for hidden radio inputs, so switching sets
   is CSS only: it works with JS off, it survives catalog.js failing, and there is
   no state for a script to lose. The inputs must stay SIBLINGS of, and before,
   .mat-sets for the :checked ~ selectors below to reach it.
   ========================================================================== */
.matrail{background:var(--ink);color:var(--cream);padding-block:clamp(2.25rem,4.6vw,3.6rem)}
.matrail .sec-m{color:var(--gold)}
.matrail fieldset{border:0;margin:0;padding:0}
.mat-chips{display:flex;gap:.5rem;flex-wrap:wrap;margin:0 0 1.6rem}
.matrail input{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}
.matrail label{font-family:var(--mono);font-size:.72rem;letter-spacing:.08em;
  color:var(--cream);border:1px solid rgba(250,248,243,.3);padding:.6rem 1.2rem;
  cursor:pointer;transition:border-color .18s ease,background-color .18s ease,color .18s ease}
.matrail label:hover{border-color:var(--gold)}
/* the selected chip, and the keyboard focus ring the visually-hidden input needs */
#m-cloth:checked~.mat-chips label[for="m-cloth"],
#m-wood:checked~.mat-chips label[for="m-wood"],
#m-leather:checked~.mat-chips label[for="m-leather"]{background:var(--cream);color:var(--ink);border-color:var(--cream)}
.matrail input:focus-visible~.mat-chips label[for="m-cloth"],
.matrail input:focus-visible~.mat-chips label[for="m-wood"],
.matrail input:focus-visible~.mat-chips label[for="m-leather"]{outline:2px solid var(--gold);outline-offset:3px}
.mat-set{display:none;list-style:none;margin:0;padding:0;
  grid-template-columns:repeat(auto-fill,minmax(96px,1fr));gap:1.1rem}
#m-cloth:checked~.mat-sets .s-cloth,
#m-wood:checked~.mat-sets .s-wood,
#m-leather:checked~.mat-sets .s-leather{display:grid}
.mat-set li{display:flex;flex-direction:column;gap:.5rem;align-items:flex-start}
.mat-set i{display:block;width:88px;height:88px;border-radius:2px}
.mat-set i.is-dark{border:1px solid rgba(250,248,243,.25)}
.mat-set span{font-family:var(--mono);font-size:.62rem;line-height:1.5;
  color:rgba(250,248,243,.75)}
/* THE DISCLOSURE IS A RULING. The swatches are colour values, not photographs of
   the cloth wall, and the page says so until they are shot at Suite 1D102. */
.mat-note{font-family:var(--mono);font-size:.66rem;line-height:1.7;
  color:rgba(250,248,243,.6);margin:clamp(1.4rem,2.6vw,2rem) 0 0;max-width:64ch}
/* THE RAIL TOOK THE FABRIC BLOCK'S HEADING AND POINTS on 2026-08-24, and those were
   written for paper: an ink h2, --ink-78 lede, and hairlines at 18% black that vanish
   on ink. These are the same three elements at their on-dark values, scoped to this
   band so the paper versions are untouched — the .matrail .sec-m gold override above
   is the same move. Cream on ink is 14.8:1; the .82 lede is 11.4:1. */
.matrail h2{color:var(--cream);margin:.2rem 0 0;max-width:18em}
.matrail .fab-lede{color:rgba(250,248,243,.82)}
.matrail .fab-points li{color:var(--cream);border-top-color:rgba(250,248,243,.25)}
/* the swatches used to follow an eyebrow; they now follow a lede, and needed the
   air a paragraph asks for rather than the air a label asks for */
.matrail fieldset{margin-top:clamp(1.5rem,3vw,2.1rem)}

/* 07 With your studio — full-bleed photograph, ink veil, centred. */
/* Its veil is .74 via .is-bright, not the .64 it used to carry, and the reason is that
   making this band show its whole photograph CHANGED THE CROP: at 460px tall the copy sat
   over the darker middle of the frame, and at 966px it sits over brighter ground. The body
   copy measured 4.32:1 against 4.5 required after the change — a contrast regression caused
   by a layout fix, which is the argument for re-measuring whenever a crop moves. */
.cb-close{display:flex;align-items:center;text-align:center}   /* height from .is-whole */
.cb-close>.veil{background:var(--veil-custom)}
.cb-close .wrap{width:100%}
/* The other statement band. "OUR QUALITY, YOUR CREATIVITY" does exactly the job
   "TO THE TRADE" does — a verbatim client line, alone in a full-bleed band, with
   nothing beside it to balance against — so it takes the same token rather than a
   third size that happened to be written on a different day. */
.cb-close h2{color:var(--cream);margin:0 auto 1.1rem;max-width:20em;
  font-size:var(--h2-stmt)}
.cb-close p{margin:0 auto;max-width:44em;color:var(--cream-88);font-size:1.02rem;line-height:1.6}

/* ==========================================================================
   THE C.L. BAILEY COLLECTION PAGE — /cl-bailey/
   ==========================================================================
   Built 2026-08-24 from stakeholder feedback: "CLB should have its own
   collection page and all the furniture items in their corresponding
   categories." It ships as a DRAFT: build/model-names.mjs still strips
   'bailey' and 'clbailey' from every product surface by the 2026-08-17 §8
   ruling, and that carve-out has not been made. See build/cl-bailey.mjs.

   The header reuses .cat-plate, so C.L. Bailey reads as a peer of the 23
   category pages rather than a new kind of thing. --acc is walnut because CLB
   is not a department and must not borrow a department's colour: cream on
   walnut is 6.90:1. */
.clb{--acc:var(--walnut)}
.clb-open{background:var(--paper)}
.clb-open img{display:block;width:100%;height:auto}
.clb-group{background:var(--paper)}
.clb-group:nth-of-type(even){background:var(--cream)}
.clb-group h2{margin:.2rem 0 clamp(1.2rem,3vw,1.8rem)}
/* auto-FILL, not auto-fit. auto-fit collapses the empty tracks, so a group holding one
   line stretched that single card across the whole wrap while every other group showed
   normal cards — game-tables and pub-tables both did it. (Joshua: "replace the large
   image and just put a card like every other product.") auto-fill keeps the tracks, so
   one card is the same width as one card anywhere else on the page. */
.clb-lines{list-style:none;margin:0;padding:0;display:grid;gap:clamp(1rem,2.4vw,1.6rem);
  grid-template-columns:repeat(auto-fill,minmax(min(100%,240px),1fr))}
.clb-line{min-width:0}
/* The photograph and the slot are interchangeable: both are the first child,
   both take the same ratio, so filling one never moves the row. */
.clb-line>img{display:block;width:100%;aspect-ratio:1.3333;object-fit:cover}
.clb-body{padding:.85rem 0 0}
.clb-body h3{font-family:var(--sans);font-weight:700;font-size:1rem;margin:0 0 .3rem}
.clb-fin{margin:0;font-family:var(--mono);font-size:.72rem;letter-spacing:.04em;
  color:var(--ink-78);line-height:1.7}
.clb-fin.is-todo{color:var(--walnut)}

/* The C.L. Bailey band on a category page — the collection page's rows, on the
   page a designer actually lands on. Same .clb-lines grid, on cream so it reads
   as a named section within the category rather than another product shelf. */
.clb-strip{background:var(--cream);border-top:1px solid rgba(31,36,33,.12)}
.clb-strip h2{margin:.2rem 0 clamp(1.2rem,3vw,1.8rem)}
.clb-more{margin:clamp(1.2rem,3vw,1.8rem) 0 0;font-family:var(--mono);font-size:.78rem}
.clb-more a{color:var(--ink);text-decoration:none;border-bottom:1px solid var(--gold)}
.clb-more a:hover{color:var(--walnut)}

/* A range card's slot is exactly the size of a range card's photograph — same fixed
   height, no aspect-ratio — so filling one is a like-for-like swap and the row never
   moves. */
.cb-range-grid .slot{aspect-ratio:auto;height:clamp(180px,19vw,270px)}

/* --- 03 THE FILM, on Custom Built -----------------------------------------
   Paper, standing where Step 2's paper step stood, so the cream-paper-ink rhythm
   down the page is unchanged by the swap. The frame carries --ar and the video
   fills it, which means the poster and the playing film occupy exactly the same
   box — no reflow at the moment somebody presses play, which is the one thing a
   <video> in a page of fixed-ratio photographs must not do. Black behind it, not
   --mist: this file letterboxes to its own 16:9 and any gap should read as the
   frame, not as a hole in the page. */
.cb-film{background:var(--paper);border-top:1px solid var(--line);
  padding-block:clamp(2rem,4vw,3rem)}
.cb-film-frame{margin:0}
.cb-film-frame video{display:block;width:100%;height:auto;aspect-ratio:var(--ar,1.7778);
  background:#000;object-fit:cover}
.cb-film-frame figcaption{font-family:var(--mono);font-size:.66rem;letter-spacing:.06em;
  text-transform:uppercase;color:var(--walnut);margin-top:.7rem}

/* --- 04b FABRIC, on Custom Built ------------------------------------------
   Paper, between the dark materials band above and the cream step below, so no
   two grounds repeat. The photograph runs the wrap at its own 16:9 rather than
   sitting in a column — §8, and the lesson from the C.L. Bailey block, where a
   16:9 in a narrow column cost 40.7% of the frame. */
.fabric{background:var(--paper);border-top:1px solid var(--line)}
.fabric h2{margin:.2rem 0 0;max-width:18em}
.fab-lede{margin:.9rem 0 0;max-width:58ch;color:var(--ink-78);text-wrap:pretty}
.fab-shot{margin:clamp(1.4rem,3.4vw,2.2rem) 0 0}
.fab-shot img{display:block;width:100%;aspect-ratio:var(--ar,1.7778)}
/* Two columns, not auto-fit. Four items with auto-fit landed 3+1 at 1440 — the same
   ragged last row the department tiles had to solve. 2x2 is even at every width above
   620px and gives each line room to sit on one line instead of three. */
.fab-points{list-style:none;margin:clamp(1.4rem,3vw,2rem) 0 0;padding:0;display:grid;
  gap:1rem 2rem;grid-template-columns:1fr}
@media (min-width:620px){.fab-points{grid-template-columns:repeat(2,minmax(0,1fr))}}
.fab-points li{padding-top:.75rem;border-top:1px solid rgba(31,36,33,.18);
  font-family:var(--mono);font-size:.8rem;line-height:1.7;color:var(--ink)}

/* --- C.L. Bailey cards that lead somewhere -------------------------------- */
/* A card with a studio product behind it is a link; one without is not, and must not
   pretend to be. The anchor wraps the photograph and the body so the whole card is the
   target, and it carries the site's one motion allowance: a 3px lift. */
.clb-line.is-link{position:relative}
.clb-go{display:block;color:inherit;text-decoration:none;
  transition:transform .22s cubic-bezier(.25,1,.5,1)}
.clb-go:hover{transform:translateY(-3px)}
.clb-go:hover .clb-body h3{border-bottom-color:var(--gold)}
.clb-go .clb-body h3{display:inline;border-bottom:1px solid transparent;
  transition:border-color .22s ease}
@media (prefers-reduced-motion:reduce){.clb-go,.clb-go:hover{transition:none;transform:none}}

/* --- a C.L. Bailey product page ------------------------------------------- */
/* Studio shots are squares. They are shown as squares here — this is the one surface
   where the whole frame matters, and the white ground is the point of the set. */
.clbp-set{background:var(--paper)}
.clbp-set:nth-of-type(even){background:var(--cream)}
.clbp-shots{list-style:none;margin:1rem 0 0;padding:0;display:grid;gap:clamp(1rem,2.4vw,1.6rem);
  grid-template-columns:repeat(auto-fit,minmax(min(100%,260px),1fr))}
.clbp-shots li{min-width:0}
.clbp-shots img{display:block;width:100%;aspect-ratio:1;object-fit:contain;background:#fff}
.clbp-cap{margin:.6rem 0 0;font-family:var(--mono);font-size:.68rem;letter-spacing:.08em;
  text-transform:uppercase;color:var(--walnut)}

/* --- the C.L. Bailey spec block ------------------------------------------- */
/* Description, then the feature bullets beside a short definition list. Cream, so it
   separates from the white shot galleries below without another rule. */
.clbp-detail{background:var(--cream)}
.clbp-detail .lede{max-width:64ch;margin:.9rem 0 0;text-wrap:pretty}
.clbp-facts{display:grid;gap:clamp(1.2rem,3vw,2.4rem);margin:clamp(1.4rem,3vw,2rem) 0 0;
  grid-template-columns:1fr}
@media (min-width:820px){.clbp-facts{grid-template-columns:1fr minmax(0,.7fr)}}
.clbp-feat{list-style:none;margin:0;padding:0;display:grid;gap:.55rem}
.clbp-feat li{padding-left:1.15rem;position:relative;font-size:.95rem;line-height:1.6;
  max-width:52ch}
.clbp-feat li::before{content:"";position:absolute;left:0;top:.62em;width:11px;height:1px;
  background:var(--walnut)}
.clbp-spec{margin:0;font-family:var(--mono);font-size:.78rem;line-height:1.7}
.clbp-spec dt{color:var(--walnut);letter-spacing:.06em;text-transform:uppercase;
  font-size:.68rem;margin:0 0 .15rem}
.clbp-spec dd{margin:0 0 .9rem;color:var(--ink)}
.clbp-src{margin:clamp(1.2rem,3vw,1.8rem) 0 0;font-family:var(--mono);font-size:.7rem;
  color:var(--ink-78)}

/* --- CART (spec 2026-09-02) -------------------------------------------------
   Nothing new is invented: the site's .btn shapes, its tokens, the 3px lift.
   The header link inherits .nav a; only the count badge is its own. */
.cart-link{display:inline-flex;align-items:center;gap:.35rem}
.cart-n{font-family:var(--mono);font-size:.66rem;line-height:1;padding:.22rem .45rem;border-radius:999px;background:var(--gold);color:var(--ink)}
.cart-add{background:var(--paper);border-top:1px solid var(--line)}
.cart-add-row{display:flex;align-items:center;gap:.9rem;flex-wrap:wrap}
.cart-qty{width:4.5rem;font-family:var(--mono);font-size:.95rem;padding:.7rem .6rem;border:1px solid rgba(31,36,33,.35);background:var(--paper);color:var(--ink)}
.cart-note{margin:.8rem 0 0;font-family:var(--mono);font-size:.78rem;color:var(--ink-78)}
.cart-note a{color:var(--ink);border-bottom:1px solid var(--gold);text-decoration:none}
.cart-kicker{font-family:var(--mono);font-size:.7rem;letter-spacing:.14em;text-transform:uppercase;color:var(--walnut);margin:0 0 .6rem}
.cart-email{font-weight:700;margin:0 0 1.2rem}
.cart-form{display:grid;gap:.8rem;max-width:34rem}
.cart-input{font-family:var(--sans);font-size:1rem;padding:.75rem .8rem;border:1px solid rgba(31,36,33,.35);background:var(--paper);color:var(--ink);width:100%}
.cart-input:focus,.cart-qty:focus{outline:2px solid var(--gold);outline-offset:1px}
.cart-code{font-family:var(--mono);letter-spacing:.3em}
.cart-lines{list-style:none;margin:clamp(1.4rem,3vw,2rem) 0 0;padding:0;display:grid;gap:1rem}
.cart-line{display:grid;grid-template-columns:120px minmax(0,1fr);gap:1rem;padding:1rem 0;border-top:1px solid var(--line)}
.cart-line img,.cart-noimg{width:120px;aspect-ratio:4/3;object-fit:contain;background:#fff;display:block}
.cart-line-name{font-weight:700;color:var(--ink);text-decoration:none}
.cart-line-name:hover{border-bottom:1px solid var(--gold)}
.cart-line-meta{margin:.2rem 0 .6rem;font-family:var(--mono);font-size:.74rem;color:var(--ink-78)}
.cart-line-ctl{display:flex;gap:.6rem;align-items:center;flex-wrap:wrap}
.cart-line-note{flex:1 1 14rem}
.cart-remove{font-family:var(--mono);font-size:.72rem;letter-spacing:.06em;background:none;border:0;color:var(--ink-78);cursor:pointer;text-decoration:underline}
.cart-remove:hover{color:var(--ink)}
.cart-empty{font-size:1rem;color:var(--ink-78);margin:0 0 1rem}
.cart-send{display:grid;gap:.8rem;max-width:34rem;margin-top:clamp(1.4rem,3vw,2rem)}
.cart-msg{resize:vertical;min-height:5.5rem}
.cart-done{font-size:1.1rem;margin:0 0 1.2rem}
.cart-links{margin:1.2rem 0 0;font-family:var(--mono);font-size:.78rem}
.cart-links a{color:var(--ink);text-decoration:none;border-bottom:1px solid var(--gold)}
.cart-past{margin-top:clamp(2rem,4vw,3rem);border-top:1px solid var(--line);padding-top:1.2rem}
.cart-past ul{list-style:none;margin:0;padding:0;font-family:var(--mono);font-size:.78rem;display:grid;gap:.4rem}
.cart-past a{color:var(--ink);border-bottom:1px solid var(--gold);text-decoration:none}
@media (max-width:560px){.cart-line{grid-template-columns:88px minmax(0,1fr)}.cart-line img,.cart-noimg{width:88px}}

/* --- ACCOUNT (horizon one, 2026-09-02) --------------------------------------
   Two panels side by side, the shape Billiard Factory's own sign-in uses:
   Returning on the left, New on the right, one door behind both. */
.acct-link{white-space:nowrap}
.acct-panels{display:grid;gap:clamp(1.2rem,3vw,2.4rem)}
@media (min-width:820px){.acct-panels{grid-template-columns:1fr 1fr}}
.acct-panel{border:1px solid var(--line);background:var(--paper);padding:clamp(1.2rem,2.6vw,1.8rem)}
.acct-panel h3,.acct-block h3{font-family:var(--mono);font-weight:400;font-size:.72rem;letter-spacing:.14em;text-transform:uppercase;color:var(--walnut);margin:0 0 .8rem}
.acct-panel p{margin:0 0 1rem;font-size:.98rem;line-height:1.6;max-width:44ch}
.acct-form{display:grid;gap:.8rem}
.acct-form-row{grid-template-columns:1fr 1fr auto;max-width:44rem}
@media (max-width:640px){.acct-form-row{grid-template-columns:1fr}}
.acct-fine{margin:.9rem 0 0;font-family:var(--mono);font-size:.72rem;color:var(--ink-78)}
.acct-sent{margin:0 0 1.2rem;font-size:1rem;line-height:1.6;max-width:56ch}
.acct-change,.acct-resend{font:inherit;font-family:var(--mono);font-size:.74rem;letter-spacing:.06em;background:none;border:0;padding:0;color:var(--ink);text-decoration:underline;cursor:pointer}
.acct-resend:disabled{color:var(--ink-78);text-decoration:none;cursor:default}
.acct-code{display:flex;gap:.8rem;flex-wrap:wrap;align-items:stretch;max-width:34rem}
.acct-code .cart-code{flex:1 1 12rem;font-size:1.6rem;letter-spacing:.42em;text-align:center;padding:.6rem .8rem}
.acct-block{padding:clamp(1.2rem,2.6vw,1.8rem) 0;border-top:1px solid var(--line)}
.acct-block:first-child{border-top:0;padding-top:0}
.acct-go{color:var(--ink);text-decoration:none;border-bottom:1px solid var(--gold);white-space:nowrap}
.acct-sends{list-style:none;margin:0;padding:0}
.acct-sends li{display:grid;grid-template-columns:7.5rem minmax(0,1fr) auto;gap:1rem;align-items:baseline;padding:.7rem 0;border-top:1px solid var(--line)}
.acct-sends li:first-child{border-top:0}
.acct-when{font-family:var(--mono);font-size:.76rem;color:var(--ink-78)}
.acct-what{font-size:.95rem;line-height:1.5;min-width:0}
.acct-pdf{font-family:var(--mono);font-size:.74rem;letter-spacing:.06em;color:var(--ink);text-decoration:none;border-bottom:1px solid var(--gold)}
.acct-pdf.is-none{color:var(--ink-78);border:0}
@media (max-width:560px){.acct-sends li{grid-template-columns:1fr;gap:.2rem}}

/* --- PROJECTS (§4q, 2026-09-02): many projects, one current ------------------- */
.cart-add-hint{margin:.5rem 0 0}
.cart-pick{display:grid;gap:.5rem;max-width:34rem;margin-top:.6rem}
.cart-pick-btn{font:inherit;font-size:.92rem;text-align:left;padding:.65rem .8rem;border:1px solid rgba(31,36,33,.35);background:var(--paper);color:var(--ink);cursor:pointer}
.cart-pick-btn:hover{border-color:var(--ink)}
.cart-pick-btn.is-current{border:2px solid var(--gold)}
.cart-pick-new{display:flex;gap:.6rem;flex-wrap:wrap;align-items:stretch}
.cart-pick-new .cart-input{flex:1 1 14rem}
.acct-new{margin-top:1.2rem}
.acct-tag{margin-left:.6rem;font-family:var(--mono);font-size:.64rem;letter-spacing:.12em;text-transform:uppercase;color:var(--ink);background:var(--gold);padding:.15rem .45rem;border-radius:999px;vertical-align:middle}
.acct-projects .acct-change{margin-left:.6rem}
.cart-line-ro{margin:.4rem 0 0;font-family:var(--mono);font-size:.78rem;color:var(--ink-78)}

/* --- ONE PRODUCT TEMPLATE (2026-09-02): the C.L. Bailey pages now use the harvested
   product page's skeleton. Two small additions it needed. */
.pdp-sec.on-paper{background:var(--paper);border-top:1px solid var(--line)}
.pdp-sec .clbp-lede{max-width:64ch;margin:.9rem 0 0;text-wrap:pretty}
.pdp-sec .clbp-shots{margin-top:1.2rem}

/* --- PROFILE (2026-09-02): name and phone, required, because Jana calls. ------- */
.acct-why{max-width:52ch;margin:0 0 1.2rem;font-size:1rem;line-height:1.6}
.acct-form-4{grid-template-columns:1fr 1fr 1fr auto}
@media (max-width:820px){.acct-form-4{grid-template-columns:1fr 1fr}}
@media (max-width:640px){.acct-form-4{grid-template-columns:1fr}}

/* --- THE NUMBER LEADS THE CARD (2026-09-02): SKU in mono as the heading, the model name
   as the line under it. Same weight the harvested tiles give a SKU. */
.clb-body h3.clb-sku{font-family:var(--mono);font-weight:400;font-size:.92rem;letter-spacing:.04em;margin:0 0 .15rem}
.clb-name{margin:0 0 .3rem;font-family:var(--sans);font-weight:700;font-size:.95rem;color:var(--ink)}

/* ---- 404 ---------------------------------------------------------------
   The not-found page's one list: the four places a lost visitor can go. Same
   measure and rhythm as .cart-note prose; links carry the ink underline. */
.nf-list { list-style: none; margin: 0; padding: 0; max-width: 62ch; display: grid; gap: .65rem; font-size: 1.05rem; line-height: 1.5; }
.nf-list a { color: inherit; font-weight: 700; text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: .18em; }

/* ---- PRIVACY -----------------------------------------------------------
   One hand-built page of prose. Same measure as the rest of the site's body
   copy so it reads as part of the site rather than as pasted-in paperwork. */
.pp-body { max-width: 68ch; margin: 0 0 1rem; font-size: 1.02rem; line-height: 1.62; text-wrap: pretty; }
.pp-note { max-width: 68ch; margin: 1.1rem 0 0; font-size: .95rem; line-height: 1.55; color: var(--ink-78); }
.pp-list { list-style: none; margin: 0; padding: 0; max-width: 68ch; display: grid; gap: .8rem;
  font-size: 1.02rem; line-height: 1.6; }
.pp-list li { padding-left: 1.1rem; position: relative; text-wrap: pretty; }
.pp-list li::before { content: ""; position: absolute; left: 0; top: .62em; width: 6px; height: 1px; background: var(--gold); }
.pp-body a, .pp-list a { color: inherit; font-weight: 700; text-decoration: underline;
  text-decoration-thickness: 1px; text-underline-offset: .18em; }
