/* ==========================================================================
   OKD — Architectural Surfaces.  Digital catalogue.

   The palette is OKD's own and it is WARM, not cool. #e7e0da is the ground of
   the printed catalogue cover and the same greige the chat widget on okd.co.il
   uses for its buttons — two places the brand already chose it, which is why it
   is here rather than the blue-greys a first pass took off the site chrome
   (Orit, 15.9.2026: "אם צריך לקחת צבע תיקח מהבוט באתר").

   There is deliberately no black surface anywhere: the existing OKD site has
   none, and a black band under these photographs reads as a different brand.
   Dark warm type on white does the structural work, and the material
   photography supplies all the colour the page needs.

   Two rules carried over from the printed catalogue, neither of them taste:
   1. Reading text is weight 400. ExtraLight at reading size looks faded even
      when the size is right (Orit, 25.8.2026). Weight 300 is allowed only at
      display sizes, 32px and up, where the strokes are thick enough to hold.
   2. Contrast floor is 7:1 for anything carrying meaning. Every value below was
      measured against its own ground — and note that greige is a darker ground
      than white, so --ink-2 and --ink-3 do NOT clear the floor on it. That is
      what --ink-warm exists for; it is the only colour that clears 7:1 on both
      (9.61 on white, 7.35 on greige), so the greige panels switch to it.
   ========================================================================== */

:root {
  --paper:      #ffffff;   /* the ground. White, everywhere */
  --paper-2:    #f6f3f0;   /* the lightest warm tint — image grounds, bands */
  --paper-3:    #e7e0da;   /* the catalogue cover, and the site's own bot */
  --ink:        #332f2b;   /* 13.27 on white, 10.16 on greige */
  --ink-2:      #57524c;   /* 7.73 on white. Secondary text */
  --ink-3:      #5c564e;   /* 7.25 on white. Overlines and meta */
  --ink-warm:   #4a443d;   /* 9.61 on white, 7.35 on greige. Both grounds */
  --deep:       #4a443d;   /* solid buttons. White on it is 9.61 */
  --rule:       #e2dcd5;
  --rule-soft:  #efebe6;
  /* The active-state mark. It was OKD's amber #fab721 and it is now ink
     (Orit, 15.9.2026: "אני רוצה פסים בצבע שחור או אפור בהתאם לאתר"). The amber
     never sat right on a warm greige page — it read as a highlighter rather
     than as part of the brand — and it had already failed once on contrast,
     measuring 1.77:1 as type on white. Ink marks the current page instead, in
     the same colour as the word above it. */
  --accent:     #332f2b;

  --measure:    62ch;
  --gap:        clamp(18px, 2.2vw, 34px);
  --pad:        clamp(20px, 5vw, 76px);
  --head-h:     104px;

  --ease:       cubic-bezier(.22,.61,.36,1);
}

* { box-sizing: border-box; }

/* The PDF links start hidden and are revealed once site.js knows the file is
   there. .btn sets display:inline-flex, which outranks the browser's own rule
   for [hidden] -- so say it here, or the button appears with href="#". */
[hidden] { display: none !important; }

/* No smooth scrolling here, deliberately.

   Opening a material from a collection page means jumping from wherever the
   reader was back to the top -- and with smooth behaviour on <html> the browser
   ANIMATED that jump, so the new page appeared to race upwards from its own
   footer before settling (Orit, 15.9.2026). A route change is not a scroll
   within a page; it should simply begin at the top. Nothing on this site links
   to an anchor inside a page, so the smooth rule had nothing else to do. */

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: "Assistant", -apple-system, BlinkMacSystemFont, "Segoe UI", Arial, sans-serif;
  font-size: 16.5px;
  font-weight: 400;
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img { max-width: 100%; display: block; }
a   { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }

/* -------------------------------------------------------------- type scale */

h1, h2, h3, h4 { margin: 0; font-weight: 300; line-height: 1.12; letter-spacing: -.012em; }

.t-display { font-size: clamp(32px, 3.8vw, 58px); line-height: 1.06; letter-spacing: -.022em; }
.t-h1      { font-size: clamp(28px, 3.4vw, 46px); line-height: 1.08; letter-spacing: -.016em; }
.t-h2      { font-size: clamp(23px, 2.6vw, 34px); }
.t-h3      { font-size: 19px; font-weight: 400; letter-spacing: -.004em; }

/* The overline is the catalogue's small-caps label: wide, quiet, structural. */
.overline {
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: .19em;
  text-transform: uppercase;
  color: var(--ink-3);
  line-height: 1.4;
}

.lede { font-size: clamp(16px, 1.3vw, 19px); line-height: 1.58; color: var(--ink-2); max-width: 52ch; }
.body { max-width: var(--measure); }
.muted { color: var(--ink-2); }
.rule { height: 1px; background: var(--rule); border: 0; margin: 0; }

/* ------------------------------------------------------------------- shell */

.wrap { padding-inline: var(--pad); }
.wrap--wide { max-width: 1680px; margin-inline: auto; }

.site-head {
  position: sticky; top: 0; z-index: 60;
  background: var(--paper);
  border-bottom: 1px solid var(--rule);
}
/* The bar spans the window; its CONTENTS sit in the same 1680px column as
   everything below it. Without the inner wrap the mark drifted to the far left
   of a wide screen while the page under it stopped at 1680 — so the logo lined
   up with nothing, and the header read as stretched rather than as the top of
   the same page. */
.site-head__in {
  display: flex; align-items: center; gap: 28px;
  height: var(--head-h);
  max-width: 1680px; margin-inline: auto;
  padding-inline: var(--pad);
}

/* The lockup, read off the printed cover: the bracket and "Okd" standing on
   their own, then a hairline, then the words as letterspaced caps. The brand
   file's own two text lines are cropped out in build-site.py — at this size
   they are smudges, and the line beside the mark does their job legibly. */
.site-head__mark { display: flex; align-items: center; gap: 16px; flex: 0 0 auto; }
/* Drawn large enough that the line inside the bracket is a line of words
   and not a smudge. The lockup is 206 x 200 and 'Okd' is 67 units of that, so
   the mark's height is what sets how the tagline reads. */
.site-head__mark img { width: auto; height: 62px; object-fit: contain; }
.site-head__mark span {
  font-size: 10px; letter-spacing: .2em; text-transform: uppercase;
  color: var(--ink); font-weight: 500; white-space: nowrap;
  padding-inline-start: 16px; border-inline-start: 1px solid var(--rule);
  line-height: 1;
}
/* Measured, not guessed: the line is 258px at this size, the whole mark block
   316px, and the navigation 284px — so the header needs 742px to hold both side
   by side, and below 860px the nav is a hamburger anyway and the room is there.
   The line only has to step aside on a small phone, where the mark block plus
   the menu button reaches the edge at about 400px. */
@media (max-width: 520px) { .site-head__mark span { display: none; } }

.site-nav { display: flex; gap: 26px; margin-inline-start: auto; align-items: center; }
.site-nav a {
  font-size: 12px; letter-spacing: .18em; text-transform: uppercase; font-weight: 500;
  color: var(--ink-2); padding-block: 6px; position: relative;
  transition: color .22s var(--ease);
}
.site-nav a::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0;
  height: 2px; background: var(--accent);
  transform: scaleX(0); transform-origin: left; transition: transform .3s var(--ease);
}
.site-nav a:hover { color: var(--ink); }
.site-nav a:hover::after, .site-nav a[aria-current="page"]::after { transform: scaleX(1); }
.site-nav a[aria-current="page"] { color: var(--ink); }

/* The way back out to okd.co.il (Orit, 27.9.2026). The catalogue lives inside
   that site, so this is not a fifth page of the catalogue -- it leaves it. A
   hairline before it says so without a word, and it stays a shade quieter than
   the three routes beside it. */
.site-nav__out { padding-inline-start: 26px; border-inline-start: 1px solid var(--rule); }

/* The catalogue's own PDF. A filled button rather than a fourth text link:
   taking the catalogue away is an action, not a place to go.

   🛑 Selected as `.site-nav a.btn--nav`, not `.btn--nav`. `.site-nav a` is
   (0,1,1) and beats a lone class (0,1,0), so the plain modifier lost every
   contest it entered: the button drew .btn--solid's dark fill but kept the
   nav's dark ink, and the label measured 1.24:1 -- invisible. The nav's
   underline is cancelled here too; a filled button does not need one. */
.site-nav a.btn--nav {
  padding: 9px 16px; font-size: 10.5px; letter-spacing: .14em; gap: 8px;
  color: #fff; border-color: var(--deep);
}
.site-nav a.btn--nav:hover { color: var(--deep); background: transparent; }
.site-nav a.btn--nav::after { display: none; }
.site-nav a.btn--nav svg { width: 13px; height: 13px; }

.nav-toggle { display: none; }

/* 1000px, not 860. The nav used to carry three routes and fitted beside the
   logo down to 860; it now carries five items -- the two extra are okd.co.il
   and the PDF button (Orit, 27.9.2026) -- and it measured 557px wide against a
   359px logo block. At 885px that overflowed the window by 83px, which is
   invisible to the eye and only shows up in scrollWidth. The header needs
   ~992px for both, so the menu folds into the button below 1000. */
@media (max-width: 1000px) {
  .site-nav {
    position: fixed; inset: var(--head-h) 0 auto 0;
    flex-direction: column; align-items: flex-start; gap: 0;
    background: var(--paper); border-bottom: 1px solid var(--rule);
    padding: 8px var(--pad) 22px;
    transform: translateY(-8px); opacity: 0; pointer-events: none;
    transition: opacity .24s var(--ease), transform .24s var(--ease);
  }
  .site-nav[data-open="true"] { opacity: 1; transform: none; pointer-events: auto; }
  .site-nav a { font-size: 14px; letter-spacing: .12em; padding-block: 13px; width: 100%; border-bottom: 1px solid var(--rule-soft); }
  /* The column has no left edge to hang a rule on, and a button is not a row:
     it keeps its own size and loses the row's underline. */
  .site-nav__out { padding-inline-start: 0; border-inline-start: 0; }
  .site-nav a.btn--nav {
    width: auto; align-self: flex-start; margin-top: 16px;
    border: 1px solid var(--deep); padding: 12px 20px;
  }
  .nav-toggle { display: block; margin-inline-start: auto; }
  .nav-toggle svg { width: 22px; height: 22px; stroke: var(--ink); fill: none; stroke-width: 1.4; }
}

main { min-height: 70vh; }
.route { animation: routeIn .44s var(--ease) both; }
@keyframes routeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .route { animation: none; } }

.reveal { opacity: 0; transform: translateY(18px); transition: opacity .8s var(--ease), transform .8s var(--ease); }
.reveal.is-in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) { .reveal { opacity: 1; transform: none; transition: none; } }

/* --------------------------------------------------------------- figures
   display:block matters and is not decoration. These wrappers are <span>s
   inside <a>s — a card has to be one link, so its parts cannot be <div>s — and
   an inline box ignores aspect-ratio entirely, which silently drops every
   picture on the page and leaves only the caption line underneath. */
.fig { display: block; position: relative; overflow: hidden; background: var(--paper-2); }
.fig img { width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity .7s var(--ease); }
.fig img.is-loaded { opacity: 1; }
.fig--4x3  { aspect-ratio: 4 / 3; }
.fig--3x2  { aspect-ratio: 3 / 2; }

/* ----------------------------------------------------------------- buttons */

.btn {
  display: inline-flex; align-items: center; gap: 10px;
  font-size: 11.5px; letter-spacing: .16em; text-transform: uppercase; font-weight: 500;
  padding: 14px 26px; border: 1px solid currentColor;
  transition: background .28s var(--ease), color .28s var(--ease), border-color .28s var(--ease);
}
.btn svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 1.5; }
.btn--solid { background: var(--deep); color: #fff; border-color: var(--deep); }
.btn--solid:hover { background: transparent; color: var(--deep); }
.btn--ghost { color: var(--ink); border-color: var(--rule); }
.btn--ghost:hover { border-color: var(--deep); color: var(--deep); }

.link-more {
  font-size: 11.5px; letter-spacing: .16em; text-transform: uppercase; font-weight: 500;
  display: inline-flex; align-items: center; gap: 9px; padding-bottom: 5px;
  border-bottom: 1px solid var(--rule); transition: border-color .26s var(--ease), gap .26s var(--ease);
}
.link-more:hover { border-color: var(--deep); gap: 15px; }
.link-more svg { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: 1.5; }

/* --------------------------------------------------------------------------
   The catalogue's own page head — an overline and a count, two lines, no more.
   There was a hero here: a full-bleed photograph, a display headline, a lede
   and two buttons. It was removed, not shrunk. This catalogue sits inside
   okd.co.il, so the visitor has already been sold to by the time they arrive
   and what they came for is materials (Orit, 15.9.2026).
   -------------------------------------------------------------------------- */
/* The title plate, in the printed cover's own words and arrangement: the
   collection name in letterspaced caps, the catalogue year under it, centred.
   The rest of the page is left-aligned, and that is the point — this block
   reads as the cover of the thing you are about to leaf through. */
.cat-title {
  text-align: center;
  padding-block: clamp(34px, 5.5vh, 68px) clamp(26px, 4vh, 44px);
}
.cat-title h1 {
  font-size: clamp(19px, 2.1vw, 28px); font-weight: 400;
  letter-spacing: .15em; text-transform: uppercase; color: var(--ink);
  line-height: 1.2; margin: 0;
}
.cat-title__sub {
  display: block; margin-top: 12px;
  font-size: 10.5px; letter-spacing: .3em; text-transform: uppercase;
  color: var(--ink-3);
}
/* The way out of the front page and into the index. */
.cat-foot { display: flex; justify-content: flex-end; padding-block: clamp(26px, 4vh, 44px) clamp(40px, 6vh, 80px); }

/* -------------------------------------------------------- section scaffolding */

.section { padding-block: clamp(52px, 8vh, 104px); }
.section--quiet { background: var(--paper-2); }

.section__head { display: flex; align-items: flex-end; justify-content: space-between; gap: 28px; flex-wrap: wrap; margin-bottom: clamp(26px, 4vh, 48px); }
/* 34ch, not 20ch. This heading has exactly one use left — the collection name
   above "Also in this collection" on a material page — and the longest of the
   six, TEXTURED & PATTERNED COLLECTION, is 31 characters. At 20ch it broke over
   three lines beside a half-empty row (Orit, 15.9.2026: "תרחיב את זה"). The cap
   stays so a name can never run the full width of the page, but it is now set
   from the content it actually holds. */
.section__head h2 { max-width: 34ch; }
.section__head .overline { margin-bottom: 14px; }

/* --------------------------------------------------------------------------
   HOME — the collections, as pictures.

   This was a contents list: small chips beside names, with one preview panel
   that changed on hover. It read as an index, and an index is the wrong thing
   to put first — with surface materials the photograph IS the information, and
   a frosted partition in a real room tells an architect more, faster, than any
   name (Orit, 15.9.2026: "מה שחשוב אצלנו זה התמונות").

   It then went the other way: six pictures butted against each other with no
   gutters at all, which stopped reading as six things and started reading as
   one sheet of wallpaper (Orit, 15.9.2026: "זה עכשיו מידי אחד לשני"). So the
   tiles get air between them.

   **Every tile is the same size** (Orit, 15.9.2026: "לא גדלים משתנים"). A pass
   with alternating 16:9 and 4:3 was tried and rejected: mixed shapes make one
   collection look more important than the next, and these six are peers. The
   interest has to come from somewhere other than size, so it comes from the
   photographs and from what the caption does on hover — the grid itself stays
   plain on purpose. 3:2 is the shape: the covers are 1600 x 902 room renders
   (1.77), so it crops 15% and nothing else comes close without throwing away
   part of the room.
   -------------------------------------------------------------------------- */
.ctiles {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(18px, 2.2vw, 34px);
}
@media (max-width: 1040px) { .ctiles { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 680px)  { .ctiles { grid-template-columns: minmax(0, 1fr); } }

.ctile {
  display: block; position: relative; overflow: hidden;
  background: var(--paper-2);
  aspect-ratio: 3 / 2;
}

.ctile img {
  width: 100%; height: 100%; object-fit: cover;
  opacity: 0; transform: scale(1.01);
  transition: opacity .8s var(--ease), transform 1.5s var(--ease);
}
.ctile img.is-loaded { opacity: 1; transform: scale(1); }
.ctile:hover img.is-loaded { transform: scale(1.05); }

/* The chip is the brand greige, not white. A white box on a photograph of a
   white-filmed partition disappears into it — and #e7e0da is the colour OKD
   already uses for the catalogue cover and the chat widget (Orit, 15.9.2026). */
.ctile__cap {
  position: absolute; left: 0; bottom: 0;
  display: flex; align-items: baseline; gap: 14px;
  max-width: calc(100% - 28px);
  background: var(--paper-3);
  padding: 16px 24px 15px;
  transition: padding-inline-end .4s var(--ease), background .38s var(--ease);
}
.ctile__go {
  width: 0; overflow: hidden; white-space: nowrap;
  transition: width .42s var(--ease), opacity .3s var(--ease);
  opacity: 0; line-height: 0;
}
.ctile__go svg { width: 14px; height: 14px; fill: none; stroke: var(--ink); stroke-width: 1.5; transition: stroke .38s var(--ease); }
.ctile:hover .ctile__go { width: 24px; opacity: 1; }

/* Hover changes the chip's COLOUR, and that is the whole effect on top of the
   zoom (Orit, 15.9.2026). Five movement treatments were built and shown — fade
   to the material, caption opening, colour lift, drawn frame — and all were
   turned down; what was wanted was simply a colour change.
   Both values are already in the palette, so the tile marks itself as chosen
   without bringing in a colour the site does not otherwise use. Measured: the
   light text on #4a443d is 9.61:1, past the 7:1 floor. */
.ctile:hover .ctile__cap { background: var(--deep); }
.ctile:hover .ctile__name { color: var(--paper); }
/* The number takes the brand greige, not an invented tint: #cfc9c0 measured
   5.84 on the deep warm, under the floor, and #e7e0da is 7.35 and already in
   the palette. */
.ctile:hover .ctile__num { color: var(--paper-3); }
.ctile:hover .ctile__go svg { stroke: var(--paper); }
/* The number is ink, not amber. #fab721 on white measures 1.77:1 — fine for a
   2px underline or a filled checkbox, where it is a shape, but unreadable as
   type. The amber stays on the marks; anything with letterforms takes ink. */
/* --ink-3 measures 5.55 on greige, under the 7:1 floor; --ink-warm is 7.35. */
.ctile__num { font-size: 10px; letter-spacing: .16em; color: var(--ink-warm); font-weight: 600; transition: color .38s var(--ease); }
.ctile__name {
  font-size: clamp(12.5px, 1.05vw, 15px); letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink); font-weight: 500; line-height: 1.3;
  transition: color .38s var(--ease);
}

/* ------------------------------------------------------------------- grids */

/* minmax(0, 1fr) rather than 1fr, everywhere.

   A bare 1fr track has an automatic minimum of its content's min-content width,
   so it will not shrink past whatever the widest unbreakable thing inside it
   is — here the SKU and the width label in a card's caption, both nowrap. The
   grid then measured 794px inside a 635px column and pushed the page 109px past
   the right edge of the window. minmax(0, …) removes that floor and lets the
   track take the space it was actually given. */
.grid { display: grid; gap: var(--gap); }
.grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (max-width: 1020px) { .grid--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 620px)  { .grid--3, .grid--2 { grid-template-columns: minmax(0, 1fr); } }

/* A material card. Resting state is the room; hovering brings the material
   itself forward, which is the thing an architect is actually looking for. */
.mcard { display: block; }
.mcard__media { display: block; position: relative; overflow: hidden; background: var(--paper-2); aspect-ratio: 4 / 3; }
.mcard__media img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  transition: opacity .55s var(--ease), transform 1.2s var(--ease);
}
.mcard__media .mcard__room { opacity: 0; }
.mcard__media .mcard__room.is-loaded { opacity: 1; }
/* Zoom, the same as a collection tile. Nothing swaps. */
.mcard:hover .mcard__room.is-loaded { transform: scale(1.05); }
/* One line, always: code, name, width.

   Two things had been fighting. margin-inline-start:auto pushed the width to
   the far edge and ate the free space, so the name was left with 94px and
   wrapped to two lines; letting the row wrap instead dropped the WIDTH to a
   line of its own (Orit, 15.9.2026: "את הגודל תשים באותו שורה").

   Measured: on a 1585px screen the cards are 356px and 35 of the 38 captions
   fit whole. The three that do not — DOT MARKER, LINE MARKER, VERTICAL LINES —
   have sentences where the others have names ("Continuous pattern. Refined
   visibility."), and they need up to 406px.

   So the row never wraps, and when something has to give it is the name that
   truncates: the code and the width are short, fixed, and the two things a
   specifier scans for, while the full name is on the material's own page one
   click away. */
.mcard__foot { display: flex; align-items: baseline; flex-wrap: nowrap; gap: 12px; padding-top: 14px; border-top: 1px solid var(--rule); margin-top: 14px; transition: border-color .3s var(--ease); }
.mcard:hover .mcard__foot { border-color: var(--deep); }
.mcard__sku { flex: 0 0 auto; font-size: 10.5px; letter-spacing: .16em; font-weight: 600; color: var(--ink); white-space: nowrap; }
.mcard__name { flex: 0 1 auto; min-width: 0; font-size: 15px; color: var(--ink-2); line-height: 1.35; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Right after the name, not pushed to the edge. Keeping margin-inline-start:
   auto is what put the width out at the far right in the first place, and it
   survived the fix that stopped the line wrapping (Orit, 15.9.2026: "השארת את
   הגודל בצד ימין"). The three parts read as one caption. */
.mcard__tag { flex: 0 0 auto; font-size: 10px; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-3); white-space: nowrap; }

.ccard { display: block; }
.ccard__media { display: block; aspect-ratio: 3 / 2; overflow: hidden; }
.ccard__media img { transition: transform 1.3s var(--ease); }
.ccard:hover .ccard__media img { transform: scale(1.04); }
.ccard__body { display: block; padding-top: 18px; }
.ccard__body h3 { margin-bottom: 8px; }
.ccard__body p { color: var(--ink-2); font-size: 15px; margin: 0; max-width: 46ch; }
.ccard__count { margin-top: 12px; }

/* --------------------------------------------------------------------------
   Collection page.  The text side is OKD's pale blue-grey, not a dark band —
   the panel should recede behind the photograph beside it, not compete.
   -------------------------------------------------------------------------- */
/* The collection opener: the greige panel and the photograph, side by side.

   A stacked version was tried — photograph full width, words underneath — and
   turned down: this arrangement is the one that was wanted (Orit, 15.9.2026,
   "אני אהבתי ככה בדיוק"). What needed changing was which picture sits in it,
   not the layout around it.

   The panel is sized by its text rather than by a round number. It had been a
   flat 600px, and the six collections carry 217 to 377px of words, so between
   90 and 250px of greige was empty. The floor is now close to what the longest
   of the six needs, and it stays a FLOOR — a collection with more to say makes
   the row taller rather than being cut. */
.cover {
  position: relative;
  min-height: min(46vh, 430px);
  display: grid;
  /* 0.92, not 0.78. The paragraph was capped at 54ch inside a panel wide
     enough for more, so it sat in a narrow ribbon with the greige empty beside
     it (Orit, 15.9.2026: "תרחיב קצת את הטקסט שיישב טוב"). The photograph still
     takes the larger share. */
  grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.22fr);
  background: var(--paper-3);
}
.cover__text {
  padding: clamp(34px, 5vh, 62px) clamp(24px, 3.2vw, 56px);
  display: flex; flex-direction: column; justify-content: center;
}
/* Greige is a darker ground than white: --ink-3 measures 5.55 on it, under the
   7:1 floor. --ink-warm is 7.35 and clears both grounds. */
.cover__text .overline { color: var(--ink-warm); }
.cover__text h1 { margin: 14px 0 22px; }
/* 64ch. The printed catalogue settled this measure once: 110 mm gives 67 to 74
   characters a line and reads well, while the full column at 110 characters was
   too long (Orit, 18.8.2026). 64 sits inside that range at this size. */
.cover__text p { color: var(--ink-warm); max-width: 64ch; white-space: pre-line; }
.cover__media { position: relative; overflow: hidden; }
.cover__media img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* Below this the split stops being worth it: the text column drops under about
   370px and the measure falls to roughly 41 characters, which is a ribbon, not
   a paragraph. Stacked, the words get the full width. */
@media (max-width: 1000px) {
  .cover { grid-template-columns: 1fr; }
  .cover__media { aspect-ratio: 4 / 3; }
}

.crumb { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; font-size: 10.5px; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-3); padding-block: 22px; }
.crumb a:hover { color: var(--ink); }
.crumb span { opacity: .5; }

/* ------------------------------------------------------------ material index */

.index-layout { display: grid; grid-template-columns: 232px minmax(0, 1fr); gap: clamp(28px, 4vw, 64px); align-items: start; }
@media (max-width: 960px) { .index-layout { grid-template-columns: 1fr; } }

/* min-width:0 is load-bearing, not tidying. A grid item defaults to
   min-width:auto, so the 1fr track refuses to shrink below the MIN-CONTENT
   width of what it holds — and what it holds is another grid, three card
   columns wide. The track stayed 794px inside a 635px space and pushed the
   whole page 109px past the right edge of the window, measured. Every grid
   child on this site that itself contains a grid needs this. */
.results, .spread > *, .index-layout > * { min-width: 0; }

.filters { position: sticky; top: calc(var(--head-h) + 24px); }
.fgroup { border-top: 1px solid var(--rule); padding-block: 18px; }
.fgroup:first-child { border-top: 0; padding-top: 0; }
.fgroup > .overline { margin-bottom: 12px; }
.fopt {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: start;
  font-size: 13.5px; color: var(--ink-2); padding: 6px 0; line-height: 1.3;
  transition: color .2s var(--ease);
}
.fopt:hover { color: var(--ink); }
.fopt__box { width: 11px; height: 11px; flex: 0 0 11px; border: 1px solid var(--rule); background: transparent; transition: background .2s var(--ease), border-color .2s var(--ease); }
.fopt[aria-pressed="true"] { color: var(--ink); font-weight: 500; }
.fopt[aria-pressed="true"] .fopt__box { background: var(--accent); border-color: var(--accent); }
.fopt__n { margin-inline-start: auto; font-size: 10.5px; color: var(--ink-3); font-variant-numeric: tabular-nums; }

.results__bar { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; padding-bottom: 20px; border-bottom: 1px solid var(--rule); margin-bottom: var(--gap); }
.results__count { font-size: 10.5px; letter-spacing: .16em; text-transform: uppercase; color: var(--ink-3); }
.viewtoggle { margin-inline-start: auto; display: flex; gap: 2px; }
.viewtoggle button { padding: 7px 9px; border: 1px solid transparent; line-height: 0; }
.viewtoggle button svg { width: 15px; height: 15px; stroke: var(--ink-3); fill: none; stroke-width: 1.4; }
.viewtoggle button[aria-pressed="true"] { border-color: var(--rule); }
.viewtoggle button[aria-pressed="true"] svg { stroke: var(--ink); }

.chipbar { display: flex; gap: 8px; flex-wrap: wrap; }
.chip { display: inline-flex; align-items: center; gap: 8px; font-size: 10.5px; letter-spacing: .12em; text-transform: uppercase; border: 1px solid var(--rule); padding: 6px 11px; color: var(--ink-2); }
.chip:hover { border-color: var(--deep); color: var(--ink); }
.chip svg { width: 10px; height: 10px; stroke: currentColor; stroke-width: 1.7; fill: none; }

.mlist { border-top: 1px solid var(--rule); }
.mrow { display: grid; grid-template-columns: 60px 92px 1fr 1fr auto; gap: 18px; align-items: center; padding: 13px 0; border-bottom: 1px solid var(--rule-soft); transition: padding-left .3s var(--ease); }
.mrow:hover { padding-left: 10px; }
.mrow__chip { display: block; width: 60px; height: 36px; overflow: hidden; background: var(--paper-2); }
.mrow__chip img, .mrow__chip svg { width: 100%; height: 100%; object-fit: cover; display: block; }
.mrow__sku { font-size: 11.5px; font-weight: 600; letter-spacing: .13em; }
.mrow__name { font-size: 15px; color: var(--ink-2); }
.mrow__col { font-size: 10.5px; letter-spacing: .13em; text-transform: uppercase; color: var(--ink-3); }
.mrow__go svg { width: 14px; height: 14px; stroke: var(--ink-3); fill: none; stroke-width: 1.5; }
@media (max-width: 760px) { .mrow { grid-template-columns: 52px 1fr auto; } .mrow__name, .mrow__col { display: none; } }

.empty { padding: 60px 0; text-align: center; color: var(--ink-3); }

/* --------------------------------------------------------------------------
   MATERIAL PAGE — the catalogue spread, digitally.
   Left: the room. Right: the specification panel, which scrolls with the eye.
   -------------------------------------------------------------------------- */
.spread { display: grid; grid-template-columns: minmax(0, 1fr) minmax(360px, 38%); gap: clamp(28px, 4vw, 72px); align-items: start; padding-bottom: clamp(50px, 8vh, 96px); }
@media (max-width: 1000px) { .spread { grid-template-columns: 1fr; } }

.spread__media > .fig { aspect-ratio: 4 / 3; }

/* Labels drawn on the visualization, in the printed page's own type: small,
   letterspaced caps in ink. Each is centred on its point, so it stays put
   whatever size the box is. */
/* display:block because the layer is a <span> -- it has to be, since it also
   sits inside a material card, which is one <a> built from inline parts. An
   inline box ignores inset and would collapse the layer to nothing. */
.rlabels { display: block; position: absolute; inset: 0; pointer-events: none; }
.rlabels span {
  position: absolute; transform: translateX(-50%);
  font-size: clamp(9.5px, 0.85vw, 12.5px); font-weight: 600; letter-spacing: .16em;
  text-transform: uppercase; color: var(--ink); white-space: nowrap;
}

/* On a card the same words are set smaller. The card is ~356px against the
   material page's ~870, so the page's size would read as a caption stamped
   over the room rather than a note on the glass. And the layer takes the
   image's hover zoom with it: the words name particular panes, so they have
   to travel with them instead of drifting across the photograph. */
.mcard__media .rlabels span { font-size: 8.5px; letter-spacing: .12em; }
.mcard__media .rlabels { transition: transform 1.2s var(--ease); }
.mcard:hover .rlabels { transform: scale(1.05); }

/* The drawings sit under the photograph, in the same column, separated the
   same way the panel separates its own blocks. The profile diagram is upright
   and narrow, so it is capped rather than stretched across the column. */
/* The two drawings sit side by side, not stacked.

   The close-up and the coverage profile are both large bordered figures, and
   one under the other they read as the same card repeated twice down the page
   (Orit, 15.9.2026: "פחות נראה טוב שיש את החלקים האלה אחד אחרי השני").

   auto-fit with a 320px minimum decides for itself: where the column can hold
   two tracks of 320 they sit as a pair, where it cannot they fall back to one,
   and a material with no profile — a solid film — gets the full width for its
   single figure without any rule having to know that. No breakpoint to keep in
   sync with the column's own widths. */
.mfigs {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: clamp(18px, 2.2vw, 34px);
  align-items: start;
  border-top: 1px solid var(--rule);
  padding-top: 22px;
  margin-top: 26px;
}
.mblock > .overline { margin-bottom: 14px; }

.panel { position: sticky; top: calc(var(--head-h) + 24px); }
.panel__sku { font-size: 12px; font-weight: 600; letter-spacing: .26em; color: var(--ink); }
.panel h1 { margin: 10px 0 18px; }
.panel__desc { color: var(--ink-2); max-width: 46ch; }
.panel__desc strong { font-weight: 600; color: var(--ink); }

.pblock { border-top: 1px solid var(--rule); padding-top: 20px; margin-top: 26px; }
.pblock > .overline { margin-bottom: 14px; }

/* The close-up. 128 x 75 mm in print — the same 1.707 ratio here. */
/* White, not the warm tint. A near-white sample needs every level of
   separation it can get from its ground, and 255 gives the drawn fade 27
   levels where the tint gave 18 — measured. */
/* No frame around a photograph; a frame around a drawing.

   The border was on every close-up. Around a drawn gradient it earns its
   place — the drawing is a continuous field, so an edge touching the line
   loses nothing, and the line is what says where the sample ends. Around a
   photograph it does the opposite: the squid pictures are square, so `contain`
   leaves 42% of a 128:75 box empty, and the border drew a rectangle around
   that emptiness (Orit, 15.9.2026: "אל תשים מסגרת מסביב לתקריבים בסקוויד").
   Without it the photograph simply sits on the page. */
.closeup { aspect-ratio: 128 / 75; background: var(--paper); overflow: hidden; position: relative; }
/* No frame on anything. The border survived on drawn swatches one round
   longer than on photographs, on the argument that a continuous field needs a
   line to say where the sample ends. Overruled (Orit, 15.9.2026: "אל תעשה
   מסגרות מסביב") — the drawings sit on the page unframed, like the pictures. */
/* contain by DEFAULT, cover only where the material asks for it.

   This matched the print catalogue's rule the wrong way round: there the
   close-up is `contain` unless detail.fill is set, because cropping a photo of
   a material throws away the pattern at its edges, and that is a decision made
   per picture (Orit, 22.8.2026). The site was cropping all 24 photographs,
   so the four Squid close-ups — which carry their own printed label — lost the
   word off the top (Orit, 15.9.2026: "בסקוויד אני רואה שזה עדיין חתוך").
   Fourteen materials carry detail.fill and keep the crop; ten do not.

   object-position stays left: contain leaves slack on a photo that is not the
   box's proportion, and all of it belongs to the right so the picture starts on
   the text line (Orit, 18.8.2026). */
.closeup img { width: 100%; height: 100%; object-fit: contain; object-position: left center; }
.closeup--fill img { object-fit: cover; }
.closeup svg { width: 100%; height: 100%; display: block; }

/* A drawn swatch is inset; a photograph is not.

   The pattern is painted to the edges of its own viewBox, so its outermost
   dots are sliced — measured on KD-141-01: 38 to 126 dark pixels touching the
   left-hand columns and 510 of 590 on the bottom row. In the printed catalogue
   the box is padded and the drawing lands at about 121 x 69 mm inside 128 x 75,
   so that slice sits away from the frame and reads as a crop of a continuous
   material. On the site the drawing met the border and the same slice read as
   a mistake (Orit, 15.9.2026: "לא רואים את כל הגרפיקה, צריך קצת להקטין").

   The percentages are not arbitrary. Padding percentages resolve against WIDTH,
   both axes, so 2.7% / 2.2% holds the inner area at 1.746 whatever size the box
   is — which is exactly the 590:338 of the viewBox. The drawing stops being
   letterboxed at the same time as it stops touching the frame. */

.closeup--pair { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; border: 0; background: none; }
.closeup--pair > span { background: var(--paper); overflow: hidden; }

.heroes { display: flex; flex-wrap: wrap; gap: 34px; }
.hero-num__v { font-size: 40px; font-weight: 300; line-height: 1; letter-spacing: -.02em; color: var(--ink); }
.hero-num__v span { font-size: 16px; margin-inline-start: 4px; letter-spacing: .04em; color: var(--ink-2); }
.hero-num__v--word { font-size: 22px; letter-spacing: .04em; }
.hero-num__c { margin-top: 8px; font-size: 10px; letter-spacing: .17em; text-transform: uppercase; color: var(--ink-3); }

/* Specification list: the emphasis is on the value, not the label
   (Orit, 7.9.2026). Both are weight 400; the hierarchy is colour alone. */
.pinfo { display: grid; grid-template-columns: auto 1fr; gap: 7px 18px; margin: 0; font-size: 14.5px; }
.pinfo dt { color: var(--ink-2); font-weight: 400; }
.pinfo dd { color: var(--ink); margin: 0; font-weight: 400; }

.taglist { display: flex; flex-wrap: wrap; gap: 7px; margin: 0; padding: 0; }
.taglist li { list-style: none; font-size: 12.5px; letter-spacing: .04em; color: var(--ink-2); border: 1px solid var(--rule); padding: 5px 11px; }
.featlist { margin: 0; padding: 0; list-style: none; columns: 2; column-gap: 24px; font-size: 14.5px; color: var(--ink-2); }
.featlist li { break-inside: avoid; padding: 3px 0 3px 15px; position: relative; }
.featlist li::before { content: ""; position: absolute; left: 0; top: .78em; width: 6px; height: 1px; background: var(--ink-3); }
@media (max-width: 520px) { .featlist { columns: 1; } }

/* Colour range — the flat chips are painted, never images (Orit, 7.9.2026). */
.swatches { display: grid; gap: 14px 12px; grid-template-columns: repeat(var(--sw-cols, 6), 1fr); }
.sw { min-width: 0; }
.sw__chip { aspect-ratio: 1; width: 100%; border: 1px solid var(--rule); background-size: cover; background-position: center; }
.sw__code { margin-top: 7px; font-size: 10.5px; letter-spacing: .08em; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.sw__name { font-size: 11.5px; color: var(--ink-2); line-height: 1.25; }
@media (max-width: 620px) { .swatches { grid-template-columns: repeat(4, 1fr); } }

/* The gradient profile drawing — the one piece an architect measures from. */
.profile { padding-block: 6px; }
.profile svg { width: 100%; height: auto; display: block; }

.enquire-row { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 30px; }
.related { border-top: 1px solid var(--rule); padding-top: clamp(34px, 5vh, 58px); }

/* The end of one collection and the start of the next.

   This was a 10.5px overline and it read as another small label on a page
   already full of them — a reader reaching it could not tell they had finished
   (Orit, 15.9.2026: "לרשום ביותר גדול שיבינו שהם סיימו את הקולקציה"). It is a
   heading now, at the same size as the page's own title, with the collection
   just finished named above it so the break is stated rather than implied. */
.related--next {
  margin-top: clamp(56px, 9vh, 110px);
  padding-bottom: clamp(50px, 8vh, 100px);
}
.next-head { padding-bottom: clamp(26px, 4vh, 44px); }
.next-head h2 { margin-top: 14px; max-width: 18ch; }

/* ---------------------------------------------------------- enquire + footer */

.about-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: clamp(28px, 4vw, 72px); align-items: center; }
@media (max-width: 860px) { .about-grid { grid-template-columns: 1fr; } }
.expertise { margin: 0; padding: 0; list-style: none; border-top: 1px solid var(--rule); }
.expertise li { padding: 12px 0; border-bottom: 1px solid var(--rule); font-size: 15px; }
.site-foot .expertise li { border-color: #d5cdc4; }

/* --------------------------------------------------------------------------
   Contact — centred, because the page has one thing to say.
   -------------------------------------------------------------------------- */
.contact {
  max-width: 640px; margin-inline: auto; text-align: center;
  padding-block: clamp(50px, 10vh, 120px) clamp(60px, 12vh, 140px);
}
/* The label sits between two short rules, as it does on OKD's own page. */
.contact__label { display: flex; align-items: center; justify-content: center; gap: 18px; }
.contact__label::before, .contact__label::after {
  content: ""; flex: 0 0 34px; height: 1px; background: var(--rule);
}
.contact h1 { margin: 22px 0 0; }
.contact .lede { margin: 16px auto 0; max-width: 40ch; }

.contact__ways {
  display: flex; align-items: center; justify-content: center;
  gap: 22px; flex-wrap: wrap;
  margin-top: clamp(34px, 5vh, 54px);
  font-size: clamp(16px, 1.3vw, 18.5px);
}
.contact__ways a { border-bottom: 1px solid transparent; transition: border-color .24s var(--ease); }
.contact__ways a:hover { border-color: var(--ink); }
.contact__rule { width: 1px; height: 22px; background: var(--rule); }
@media (max-width: 460px) { .contact__rule { display: none; } }

.contact__about { margin-top: clamp(32px, 5vh, 48px); padding-top: 26px; border-top: 1px solid var(--rule); }
.contact__mat { margin-top: 12px; font-size: 15px; color: var(--ink-2); }
.contact__mat b { font-weight: 600; letter-spacing: .12em; font-size: 12px; color: var(--ink); }
.contact__cta { margin-top: clamp(30px, 4.5vh, 46px); display: flex; justify-content: center; }

.site-foot { background: var(--paper-3); color: var(--ink-warm); padding: clamp(44px, 7vh, 78px) 0 32px; }
.site-foot__in { max-width: 1680px; margin-inline: auto; padding-inline: var(--pad); }
/* Mark on the left, the two lists together on the right.

   The columns used to be 1.4fr 1fr 1fr -- three stretched tracks, each holding
   a short list and a lot of nothing. Once the paragraph under the logo came out
   (Orit, 15.9.2026) the first track was a 52px mark in a 640px column and the
   two lists floated in the middle of their own empty thirds.

   Sizing the lists to their content and letting the first track absorb all the
   slack turns three half-empty columns into one deliberate space: brand on one
   side, the ways through the catalogue on the other. Nothing is stretched, so
   nothing reads as a gap that should have been filled. */
.foot-grid {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) repeat(3, minmax(0, 1fr));
  gap: clamp(28px, 3.4vw, 64px);
}
@media (max-width: 1080px) { .foot-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: 40px; } }
@media (max-width: 620px) { .foot-grid { grid-template-columns: 1fr; gap: 34px; } }
.site-foot .overline { margin-bottom: 14px; color: var(--ink-warm); }
.site-foot a:hover { color: var(--ink); }
.site-foot__mark { display: block; }
/* Larger than it was at 52px. In a column of its own, next to lists three and
   six items deep, a 52px mark read as a stray icon rather than the signature on
   the page. Measured against the lists beside it, not chosen by eye: the tallest
   column is 6 items at 30px each plus its label, and 84px gives the mark enough
   presence to hold the end of that row. */
.site-foot__mark img { width: 84px; height: auto; }
.foot-list { margin: 0; padding: 0; list-style: none; font-size: 14px; }
.foot-list li { padding: 4px 0; }
.foot-base { margin-top: 42px; padding-top: 20px; border-top: 1px solid #d5cdc4; display: flex; justify-content: space-between; gap: 18px; flex-wrap: wrap; font-size: 10.5px; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-warm); }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
