/* HSA new site - build-level corrections to the settled design's stylesheet.
 *
 * Loaded AFTER the page's own stylesheet, so a rule here wins only where it is at
 * least as specific as the design's - which is the point: these are corrections to
 * rules the design already declares, not a second design. Each one names the measured
 * defect it fixes. Nothing here changes type, spacing rhythm or layout. Colour: only §9
 * touches it, and only because the owner asked for it in as many words (the plates go
 * white, to match the white the photography is shot on) - the reason and the scope are
 * recorded there.
 *
 * 1. BREADCRUMB LINKS WERE 13px TALL. Measured at 390 and 1440 on the built pages:
 *    the two crumb links were 61x13 and 68x13. WCAG 2.2 AA 2.5.8 asks for 24x24 on
 *    every target that is not an inline link inside a sentence, and a breadcrumb is a
 *    navigation row, not a sentence. The design's own tap-target block raised the
 *    nav, the brand and the form fields but not the crumbs.
 *
 * 2. THE CONFIGURE PANEL'S SELECT WAS 42px. The design's nav-v2 block sets
 *    select{min-height:44px}; the panel's own .cfg-field select rule is more specific
 *    and re-declared 42, so the global rule never applied. Matched at its own weight.
 *
 * Not changed, and reported instead: the option checkboxes are 24x24 (AA passes, the
 * comfortable 44 is not met) and they sit inside a 44px label, so the label is the
 * real target; the nav carets are 30x44 inside a 44px-tall row.
 *
 * 3. THE SERIES PAGE'S BREADCRUMBS HAD NO STYLES AT ALL. The design's series master
 *    (which is the catalogue INDEX, not a series detail page) carries no .crumbs
 *    block, so the detail page's breadcrumb rendered as a numbered list - "1. Products
 *    / 2. / 3. Clearspan" - with the separator <li> counted. These are the design's own
 *    .crumbs rules, copied from the model master unchanged, so the two page types read
 *    the same.
 *
 * 4. THE HERO'S RULE ROW WRAPPED MID-PHRASE ON A PHONE. Measured at 390: the row is a
 *    two-label flex with flex:1 on the left, so the right-hand label ("4 models -
 *    General depth") broke after "General" and read as "GENERAL / DEPTH". Letting the
 *    row wrap puts the second label on its own line instead of breaking inside it.
 *    Above 640 the row is unchanged.
 *
 * 5. A CHECKBOX IN A CROWDED OPTION LIST WAS SQUEEZED TO 18px WIDE. Measured at 390 on
 *    a model page carrying 18 options: `.cfg-opt` is a flex row, so the 24px box was a
 *    shrinkable flex item and the browser took 6px off it to fit the label. A control is
 *    not a flexible element - `flex: 0 0 auto` keeps the box at its declared size and
 *    lets the LABEL wrap instead.
 */

.cfg-opt input {
  flex: 0 0 auto;
}

@media (max-width: 640px) {
  .hero .rule-row {
    flex-wrap: wrap;
    row-gap: 4px;
  }

  /* flex:1 on the first label stretched both to half the row, which squeezed the
     right-hand label into two lines. Natural widths let them sit on one line and wrap
     only when they genuinely do not fit. */
  .hero .rule-row .lbl {
    flex: 0 1 auto;
  }
}

.crumbs {
  padding: 26px 0 0;
}

.crumbs ol {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  font: 500 11px/1.9 var(--label-font);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

.crumbs a {
  color: var(--ink-muted);
}

.crumbs a:hover {
  color: var(--accent-text);
}

.crumbs .sep {
  color: var(--ink-muted);
}

.crumbs [aria-current="page"] {
  color: var(--ink);
}

.crumbs a {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
}

.cfg-field select {
  min-height: 44px;
}

/* ---------------------------------------------------------------------------
 * 6. A MENU ROW WHOSE PAGE DOES NOT EXIST YET IS NOT A LINK.
 *
 * The menu is the settled design's complete menu, but several of its targets are pages
 * that still owe their copy. Rather than let a tap land on "not built yet", the row
 * renders as text with a small "soon" tag: same rhythm, same colours, no dead end.
 * Nothing here changes a row that DOES have a page.
 */
.navx-menu .soon,
.navx-link.soon {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-height: 44px;
  padding: 0 18px;
  color: var(--ink-muted);
  opacity: .72;
  cursor: default;
}

.navx-link.soon {
  padding: 0;
  justify-content: flex-start;
  gap: 8px;
  opacity: .8;
}

.navx-menu .soon .n {
  flex: 0 0 auto;
}

.soon-tag {
  flex: 0 0 auto;
  font-family: var(--label-font);
  font-size: 9.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  border: 1px solid var(--rule);
  border-radius: 2px;
  padding: 2px 5px;
  color: var(--ink-muted);
}

/* the same treatment in the footer columns */
footer .soon {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 24px;
  color: var(--ink-muted);
  opacity: .72;
}

/* ---------------------------------------------------------------------------
 * 7. .plates NEEDS ITS GRID ON EVERY PAGE THAT USES IT.
 *
 * model.css declares .plates as a 2-column grid and sizes .plate img; series.css
 * declares only .frow .plate. So the hub pages that load series.css and use .plates
 * (/installs/, /features/<slug>/) had the class with NO display:grid: the plates stacked,
 * each image rendered 724px wide on a 390px screen, and /installs/ came out 84,000px tall.
 * Same numbers as the design's own rule - this only makes them apply everywhere.
 */
.plates{display:grid;grid-template-columns:1fr 1fr;gap:22px}
.plates .plate img{height:196px;width:100%;object-fit:contain}
@media (max-width:560px){.plates{grid-template-columns:1fr}}

/* ---------------------------------------------------------------------------
 * 8. A HERO PHOTOGRAPH HAS TO BE A HERO.
 *
 * The front page's opening photograph was rendered through .plate, whose own rule is
 * `height:196px;object-fit:contain` - so the front door of the site opened with a
 * letterboxed thumbnail inside a bordered box. .shot is a full-width, uncropped-in-a-box
 * image for the top of a page; the plates keep their 196px treatment everywhere else.
 */
.shot{margin:0;border:0;background:none;padding:0}
.shot img{width:100%;height:auto;max-height:520px;object-fit:cover;display:block}
@media (max-width:560px){.shot img{max-height:280px}}

/* ---------------------------------------------------------------------------
 * 9. THE PLATES ARE WHITE, AND THE BOX CROPS THE PHOTOGRAPH.
 *
 * OWNER INSTRUCTION 2026-10-29, verbatim: "In Series, Custom, individual products and
 * option pages all have Div class='Plate' which should be changed to white background (to
 * match the white background of the product images). I would like to have each image use the
 * object position of top center and have the overflow hidden so that it is visually
 * automatically cropped by css when the page is resized."
 *
 * What that corrects: every HSA product photograph is shot on white, and the design sat them
 * in a TINTED box (--surface-2, #EFE8DC) with object-fit:contain - so each one floated in a
 * grey letterbox inside a ruled frame. Now the box is white, it clips (overflow:hidden) and
 * the image fills it (object-fit:cover, object-position:top center). Resizing the window
 * changes how much of the photograph the box shows; it never scales the box to the image.
 *
 * The white is literal, not a token: it is the photograph's own background, so it stays white
 * in the night theme too rather than turning into a dark surface with a bright hole in it.
 *
 * The context prefixes are load-bearing. series.css declares .frow .plate and §7 above
 * declares .plates .plate img; a bare .plate here would lose to both, so every selector below
 * is at least as specific as the rule it corrects - and comes later in the cascade.
 */
.plate,
.frow .plate,
.plates .plate,
.sec.series2 .frow .plate {
  background: #fff;
  overflow: hidden;
}

.plate img,
.frow .plate img,
.plates .plate img,
.sec.series2 .frow .plate img {
  object-fit: cover;
  object-position: top center;
}

/* a plate with no photograph in the library stays a white space, not a grey one */
.plate:empty {
  background: #fff;
}

/* ---------------------------------------------------------------------------
 * 10. THE LIGHTBOX.
 *
 * OWNER INSTRUCTION 2026-10-29, same batch: "each image is displayed full size (or large
 * version) in a lightbox when clicked."
 *
 * The plate carries data-full - the -1600 rung of the ladder build\media_build.py wrote -
 * and site.js builds ONE overlay per page and fills it. Nothing here is visible without
 * script: no script, no .lb element, and the plate is simply an image.
 *
 * z-index 120 clears the site's own layers: the sticky header is 40, the open menu 60.
 * Targets are 44px (WCAG 2.2 AA 2.5.8 asks 24).
 */
.plate[data-full] {
  cursor: zoom-in;
}

.lb {
  position: fixed;
  inset: 0;
  z-index: 120;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 28px;
  background: rgba(15, 12, 9, .93);
}

.lb[hidden] {
  display: none;
}

.lb figure {
  margin: 0;
  max-width: 100%;
  max-height: 100%;
  text-align: center;
}

.lb img {
  display: block;
  margin: 0 auto;
  width: auto;
  height: auto;
  max-width: min(1600px, 100%);
  max-height: calc(100vh - 132px);
  background: #fff;
}

.lb .cap {
  margin-top: 14px;
  font: 400 11px/1.5 var(--label-font);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: #EFE8DC;
}

.lb-close {
  position: absolute;
  top: 14px;
  right: 14px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  padding: 0 16px;
  background: #F7F2EA;
  color: #17130F;
  border: 1px solid rgba(23, 19, 15, .3);
  border-radius: 2px;
  font: 500 11px/1 var(--label-font);
  letter-spacing: .14em;
  text-transform: uppercase;
  cursor: pointer;
}

.lb-close:hover {
  background: #fff;
}

@media (max-width: 560px) {
  .lb {
    padding: 14px;
  }

  .lb img {
    max-height: calc(100vh - 112px);
  }
}

/* the page behind an open lightbox does not scroll */
body.lb-open {
  overflow: hidden;
}

/* ---------------------------------------------------------------------------
 * 11. THE WOOD-STAIN SWATCHES.
 *
 * OWNER INSTRUCTION 2026-10-30, verbatim: "img src the Wood Finishes (stain sample images)
 * to their appropriate places on the website. I have saved all 8 standard options in the
 * folder D:\Marketing\newsite\media\options\wood-stain. also remove any verbage like
 * 'Sample photograph to follow' or similar if there are any others".
 *
 * The eight strips are 500x200 grain photographs, one per standard stain, listed in
 * site\config\site.php as each named finish's `img`. The components the design already has
 * carry a name and a small-caps label and no image slot (.facts .fr on the hub pages,
 * .fingrid on a model page), so the swatches get a grid of their own rather than a rule
 * bent around a photograph: same ruled-cell language, same display serif, same tokens,
 * the same border rhythm as .fingrid - the photograph bleeds to the cell's top and side
 * edges and the name sits under it.
 *
 * A named finish with no photograph yet (Black Laminate) keeps the cell and drops the
 * image: a cell of type, never an empty frame and never a promise that one is coming.
 *
 * This block adds no colour, no new type size and no new spacing token.
 */
.swgrid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  border-top: 1px solid var(--rule);
  margin-top: 34px;
}

.swgrid .sw {
  display: block;
  padding: 0 18px 20px;
  border-right: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}

.swgrid .sw:nth-child(3n) {
  border-right: 0;
}

/* the strip itself: flush with the cell's top and side edges, its own 5:2 ratio kept */
.swgrid .sw-ph {
  display: block;
  margin: 0 -18px 18px;
  aspect-ratio: 5 / 2;
  overflow: hidden;
  background: var(--surface-2);
}

.swgrid .sw-ph img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

.swgrid .n {
  display: block;
  font-family: var(--display-font);
  font-size: 1.35rem;
  line-height: 1;
}

.swgrid .k {
  display: block;
  margin-top: 9px;
  font-family: var(--label-font);
  font-size: 10px;
  line-height: 1.6;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

/* a cell with no photograph is a cell of type only - it starts where a name would */
.swgrid .sw-noimg {
  padding-top: 20px;
}

@media (max-width: 980px) {
  .swgrid {
    grid-template-columns: repeat(2, 1fr);
  }

  .swgrid .sw:nth-child(3n) {
    border-right: 1px solid var(--rule);
  }

  .swgrid .sw:nth-child(2n) {
    border-right: 0;
  }
}

/* ---------------------------------------------------------------------------
 * 12. THE CARD PLATES SHOW THE WHOLE PHOTOGRAPH, AND THE BOX KEEPS ITS RATIO.
 *
 * OWNER INSTRUCTION 2026-10-30, verbatim: "smaller images like listed on main page and
 * products page should not be cropped more than 10% if the image is cropped and more than
 * 10% of the total image is not seen, then the presentation is ruined. we need to maintain
 * the most amount of image we can while scaling and cropping. The space for these images
 * needs to be a bit wider of a ratio when the full page width is displayed. There is space
 * to spare in the page to the right of the descriptions, so please increase the width of the
 * displayed images 20%. once the site is stretched thinner than 920 px, the images on these
 * same pages get way too wide. the ratio needs to be adjusted to preserve more of the height
 * of the images in the responsive design."
 *
 * WHAT WAS WRONG. §9 above put the cards on `object-fit:cover;object-position:top center`
 * over a fixed height - 210px on the series-card row, 190px inside the two-up card grid.
 * The library photographs on these cards are NOT one shape: measured on the 13 series cards
 * of /series/, their aspect ratios run from 0.60 (a 482x800 Classic Rack, tall) to 2.79
 * (an 800x287 Desktop Series desk, very wide) - a 4.6x spread. A fixed box can only ever
 * fit one of those, so `cover` clipped the rest: the 0.60 rack lost 46% of its height, the
 * 2.79 desk lost 60% of its width. Nothing about that is a presentation of the product.
 *
 * WHAT THIS DOES.
 *   - `object-fit:contain` - the whole photograph is drawn, every time, at every width.
 *     Crop is 0%, not <=10%. The box is white (§9) and the photography is shot on white, so
 *     the breathing room the box adds is invisible: this reads as a matte, not a letterbox.
 *   - the box carries a 4:3 ratio instead of a fixed height (the old box was 236x210 = 1.12;
 *     4:3 is 1.33 - "a bit wider of a ratio"), so it scales with the column instead of
 *     stretching into a letterbox band.
 *   - the series-card image column goes 280px -> 336px (+20%). The row is
 *     [image 336] [gap 44] [text] inside a 1064px measure, which leaves the description
 *     684px of room for its own 62ch cap - the spare space the owner saw to the right of
 *     the copy, spent on the photograph instead of left empty.
 *   - below 920px the row is one column (series.css), so the box would otherwise be
 *     full-width: 4:3 keeps its height proportional to its width there, and the width is
 *     capped so a tablet does not render the photograph larger than the desktop card does.
 *
 * Context prefixes are load-bearing again: series.css declares `.frow .plate img` (210px)
 * and `.sec.series2 .frow .plate img` (190px), so both are named here at their own weight
 * and later in the cascade. The three states below are the settings for a
 * CUSTOM BUILDS card on the home page, which shares this component.
 */
.frow {
  grid-template-columns: 336px 1fr;
}

/* The column change must NOT be unconditional: series.css collapses .frow to one
   column inside `@media(max-width:920px)`, and an unconditional rule here would win
   over it purely on cascade order, leaving a 336px image column on a 390px phone. */
@media (max-width: 920px) {
  .frow {
    grid-template-columns: 1fr;
  }
}

.frow .plate img,
.sec.series2 .frow .plate img {
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: contain;
  object-position: center;
}

@media (max-width: 920px) {
  .frow .plate,
  .sec.series2 .frow .plate {
    max-width: 480px;
  }
}

/* ---------------------------------------------------------------------------
 * 13. THE INSTALLATION GALLERY SHOWS THE LIBRARY'S OWN FILES, AS THEY ARE.
 *
 * OWNER INSTRUCTION 2026-10-30, verbatim: "Installs gallery needs to display the images as
 * it. It is currently scaling the images up and cropping them. Combined, this is a horribly
 * low quality presentation. We will convert this to a fancy gallery at a later date. For now
 * we need to simply display the images."
 *
 * WHAT WAS WRONG. The library stores the installation photographs as the thumbnails the old
 * site served, not as originals: measured on H:\Product Library\_Installations\images, the
 * 70 files are 165x118 up to 574x310 - a median of 297x223, i.e. ~66,000 pixels. The gallery
 * drew each of them into a ~520x196 box with `object-fit:cover`, so a 297x223 file was
 * blown up ~2.3x AND clipped on the way in. Upscaling and cropping at once is exactly the
 * "horribly low quality presentation" the owner describes; the source simply has no more
 * detail to give at that size.
 *
 * WHAT THIS DOES - deliberately the minimum, because a real gallery is a later job.
 * `width:auto;height:auto` shows each file at its own size, `max-width:100%` stops it ever
 * leaving the column, and `object-fit:contain` replaces the crop with nothing at all. A file
 * with no more pixels than it has is never enlarged past them. The class is opt-in on the
 * two pages that show installation photographs (/installs/ and the home page's "Installed"
 * row) so the model-page and custom-build galleries, whose plates ARE 4:3 film and are
 * already correct, are untouched.
 */
.plates-asis {
  align-items: start;
}

.plates-asis .plate img {
  display: block;
  width: auto;
  height: auto;
  max-width: 100%;
  margin: 0 auto;
  object-fit: contain;
  object-position: center;
}
