/* ============================================================================
   Diamond Overseas Trading Co. LLC — "Clear" direction
   ----------------------------------------------------------------------------
   Built on the same system as client-preview/daisy-classic/ — same rules, same
   verification — with Diamond's own brand, content and information
   architecture. If you are changing behaviour rather than colour, change it in
   both, and read docs/guides/client-preview.md first: every rule in here was
   paid for once already on that build.

   COLOUR — Diamond's CATALOGUE palette, read out of "daimond catalogue 2"
   (the PDF's own vector and text colours, which match the logo mark):

     #F99B21  the signature orange.  2.16:1 on white
     #F47520  deeper orange.         2.83:1
     #34A749  green.                 3.10:1
     #BAD332  lime.                  1.69:1
     #ED2027  red.                   4.34:1
     #231F20  ink and dark ground.  16.30:1
     #5E5F62  grey text.             6.38:1

   Every hex above is used here EXACTLY as the catalogue sets it. Around the
   orange and the green sit two tonal ramps built on their hues, marked
   "derived" below. There is no brown: the catalogue has none, so nothing
   here is a darkened orange. None of the bright hues clears 4.5:1 on white,
   so they keep the jobs they can hold — fills, borders, rules and icons — and
   small text on white goes to the dark end of the GREEN ramp. Since
   2026-09-19 the INTERFACE is green throughout, at the client's request: the
   orange ramp below is kept because it is the catalogue's and the logo's, but
   nothing in the stylesheet paints with it any more.

   TYPE — Diamond's own faces, read from their stylesheets: Lato for headings,
   Merriweather for body, Kanit for the menu and buttons. None of the three has
   a single Arabic glyph, so on the live site Arabic falls back to Arial. Cairo
   sits second in every stack below (client's request, 2026-09-19): Latin never
   reaches it, Arabic always does, and only the Arabic tree downloads it.

   Logical properties only — one stylesheet serves LTR English and RTL Arabic.
   ========================================================================== */


:root {
  /* Ground — the theme's own grey ramp, exact */
  --bg:            #ffffff;
  --bg-soft:       #f7f7f7;   /* theme */
  --bg-sunk:       #eeeeee;   /* theme */

  /* Dark bands — footer, motto, hero panel. The catalogue's own ink, #231F20. */
  --band:          #231f20;   /* catalogue */
  --band-2:        #2d292a;   /* DERIVED — a step lighter */
  /* A weak tone as the DEFAULT means the next dark section anyone adds
     inherits the bug we already fixed once. The safe value is the default. */
  --on-band:       #faf7f2;
  --on-band-dim:   #faf7f2;

  /* Ink */
  --ink:           #231f20;   /* catalogue text   16.3:1 */
  --ink-2:         #444444;   /* body              9.7:1 */
  /* #5E5F62 is the catalogue's grey, and clears every ground here: 6.38 on
     white, 5.96 on --bg-soft, 5.50 on --bg-sunk. */
  --ink-3:         #5e5f62;

  /* Brand — exact, except where marked */
  /* Orange ramp. 500 and 600 are the catalogue's; the rest DERIVED. */
  --orange-50:     #fff6ea;
  --orange-100:    #feeacf;
  --orange-200:    #fdd9a8;
  --orange-300:    #fbc06e;
  --orange-500:    #f99b21;   /* catalogue signature. Ink on it 7.56:1 */
  --orange-600:    #f47520;   /* catalogue deeper orange. Ink on it 5.75:1 */

  /* Green ramp. 500 is the catalogue's; the rest DERIVED. */
  --green-50:      #eef8f0;
  --green-100:     #d6efdb;
  --green-200:     #a9dcb3;
  --green-300:     #6cc17c;
  --green-500:     #34a749;   /* catalogue green. 3.10:1 — large text only */
  --green-700:     #1f7a33;   /* text on white 5.40:1, on --bg-sunk 4.65:1 */
  --green-800:     #176128;   /* white text on it 7.56:1 */
  --green-900:     #135222;

  --lime-500:      #bad332;   /* catalogue lime */
  --red-500:       #ed2027;   /* catalogue red */

  /* Roles */
  /* The client asked on 2026-09-19 for the theme to lead with the logo's
     green. Measured off assets/_source/logo-full.png, the logo's green is
     #35A749 — the catalogue's #34A749 to within one unit of red, so the hue
     was already here and only the ROLE changes: green now carries the fills,
     rules and underlines that orange carried. Orange was kept on the dark
     bands at first; the client asked on 2026-09-19 for it to go from there
     too, so the interface is now green throughout and orange survives only
     inside the logo artwork and the photographs themselves.
     green-500 is 3.10:1 on white — fine for a border, a rule or a 4px bar
     (non-text UI needs 3:1), never for text. Text stays on green-700/800. */
  --brand:         var(--green-500);   /* fills, rules, underlines. Never small text on white: 3.10:1 */
  --brand-mid:     var(--green-500);
  --brand-red:     var(--red-500);
  --brand-deep:    var(--green-700);   /* text and links on light grounds */
  --brand-dark:    var(--green-800);   /* fill behind white text; hover text */
  --brand-wash:    var(--green-50);    /* hover tint under green text (7.07:1) */
  /* On-dark accents. Two tones, because a band is not always the same ground:
     --band-accent sits on the FLAT #231F20 of the footer and the closing band
     (7.42:1), and fills buttons there, where its own ink is also 7.42:1.
     --band-accent-soft is for text laid directly on a PHOTOGRAPH, where the
     ground is whatever survives the .30 overlay. Its 4.6:1 is measured against
     the brightest pixel of every band image, and the brightness factors in
     make-assets.py were re-derived for it — see ADR-0006 and ADR-0013.
     Do not put --band-accent on a photograph: it is 2.2:1 there. */
  --band-accent:      var(--green-300);
  --band-accent-soft: var(--green-100);

  /* Structure */
  --line:          #e3e3e3;   /* theme */
  --line-strong:   #bbbbbb;   /* theme */
  --radius:        14px;
  --radius-sm:     9px;
  --shadow-1:      0 1px 2px rgba(35, 31, 32, .06), 0 2px 8px rgba(35, 31, 32, .05);
  --shadow-2:      0 6px 14px rgba(35, 31, 32, .09), 0 18px 40px rgba(35, 31, 32, .08);

  /* Type — EXACTLY the stacks diamondjo.com declares. Read off the homepage's
     inline CSS, families and fallbacks both:

       h1-h4, logo                       "Lato", Arial, Tahoma, sans-serif
       body, buttons, inputs, h5, h6,
       blockquote, counters, subheader   "Merriweather", Arial, Tahoma, sans-serif
       main menu, action buttons,
       overlay menu                      "Kanit", Arial, Tahoma, sans-serif

     The live site requests these same three on its Arabic pages and no
     others, so every Arabic character there falls through to Arial, then
     Tahoma. The client asked on 2026-09-19 for something better, so "Cairo"
     is now second in each stack: it carries Arabic AND Latin, but Lato,
     Merriweather and Kanit still win every Latin glyph because they come
     first, so Latin rendering is byte-for-byte what it was. build.py asks
     Google Fonts for Cairo on the Arabic tree only — an English page has no
     character that could reach it. */
  --font-head: "Lato", "Cairo", Arial, Tahoma, sans-serif;
  --font-body: "Merriweather", "Cairo", Arial, Tahoma, sans-serif;
  --font-ui:   "Kanit", "Cairo", Arial, Tahoma, sans-serif;
  --font-mono: "Roboto Mono", ui-monospace, Consolas, "Liberation Mono", monospace;

  /* Aliases: the original draws no distinction by language, so neither do we. */
  --font-ar-head: var(--font-head);
  --font-ar-body: var(--font-body);

  /* Rhythm */
  --gutter:      24px;
  --pad:         28px;
  --section:     84px;
  --header-h:    78px;
  --maxw:        1200px;
  --facets-w:    272px;
}

@media (max-width: 900px) {
  :root { --pad: 18px; --section: 56px; --header-h: 62px; --gutter: 16px; }
}

/* ------------------------------------------------------------------ reset */

*, *::before, *::after { box-sizing: border-box; }

/* The UA rule for [hidden] is display:none at the lowest possible priority, so
   ANY author display declaration beats it — .arrow-link{display:inline-flex}
   silently un-hides every element the script hid. State it once, loudly, and
   the attribute means what it says everywhere. */
[hidden] { display: none !important; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-block-start: calc(var(--header-h) + 16px);
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    transition-duration: .001ms !important;
  }
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 16.5px;
  line-height: 1.8;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

html[dir="rtl"] body { line-height: 1.95; }

img, svg { max-width: 100%; }
img { height: auto; display: block; }

h1, h2, h3, h4 {
  font-family: var(--font-head);
  color: var(--ink);
  line-height: 1.2;
  margin: 0;
  font-weight: 900;
  letter-spacing: -0.02em;
}

html[dir="rtl"] h1, html[dir="rtl"] h2,
html[dir="rtl"] h3, html[dir="rtl"] h4 {
  font-family: var(--font-ar-head);
  /* letter-spacing severs the joins between Arabic letters. */
  letter-spacing: normal;
  line-height: 1.55;
  font-weight: 700;
}

p { margin: 0 0 1em; }
p:last-child { margin-block-end: 0; }

a { color: var(--brand-deep); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { color: var(--brand-dark); }

ul, ol { margin: 0; padding-inline-start: 1.25em; }

::selection { background: var(--green-200); color: var(--ink); }

:focus-visible {
  outline: 3px solid var(--brand-deep);
  outline-offset: 2px;
  border-radius: 3px;
}
.band :focus-visible, .footer :focus-visible { outline-color: var(--band-accent); }

.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

/* A Latin run inside Arabic text — codes, phones, emails, domains. Without
   dir="ltr" these scramble at the boundaries of an RTL paragraph. */
.code {
  font-family: var(--font-mono);
  font-size: .92em;
  letter-spacing: .02em;
  unicode-bidi: isolate;
}
html[dir="rtl"] .code { letter-spacing: normal; }

/* A Latin word quoted inside Arabic prose — a trade name, not a code. Isolated
   so it does not drag the punctuation around it to the wrong side. */
.ltr { unicode-bidi: isolate; direction: ltr; }

.skip {
  position: absolute; inset-block-start: -100px; inset-inline-start: 12px;
  z-index: 100; background: var(--brand-dark); color: #fff;
  padding: 12px 18px; border-radius: 0 0 var(--radius-sm) var(--radius-sm);
  font-weight: 700; text-decoration: none;
}
.skip:focus { inset-block-start: 0; color: #fff; }

/* --------------------------------------------------------------- layout */

.shell {
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--pad);
}

.section { padding-block: var(--section); }
.section--soft { background: var(--bg-soft); }
.section--tight { padding-block: calc(var(--section) * .6); }

.section__head { max-width: 62ch; margin-block-end: 40px; }
.section__head--center { margin-inline: auto; text-align: center; }

.eyebrow {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--font-ui);
  font-size: 13px; font-weight: 800;
  text-transform: uppercase; letter-spacing: .09em;
  color: var(--brand-deep);
  margin-block-end: 12px;
}
/* The dash takes the LABEL's colour, not --brand. Two reasons: the pair reads
   as one mark instead of two greens, and green-500 is 2.90:1 on --bg-soft and
   2.67:1 on --bg-sunk — under the 3:1 a graphical mark wants — where green-700
   is 5.04:1 and 4.65:1. On a dark band the .band rule below overrides it to
   --band-accent-soft instead. */
.eyebrow::before {
  content: ""; inline-size: 22px; block-size: 3px;
  background: var(--brand-deep); border-radius: 2px;
}
/* Uppercase is meaningless in Arabic and the tracking breaks the joins. */
html[dir="rtl"] .eyebrow {
  text-transform: none; letter-spacing: normal;
  font-family: var(--font-ar-head); font-size: 14px;
}

h1, .h1 { font-size: clamp(31px, 4.2vw, 48px); }
h2, .h2 { font-size: clamp(25px, 2.9vw, 35px); }
h3, .h3 { font-size: clamp(19px, 1.6vw, 21px); }

.lede {
  font-size: clamp(17px, 1.35vw, 19.5px);
  color: var(--ink-2);
  margin-block-start: 14px;
  max-width: 64ch;
}

.grid { display: grid; gap: var(--gutter); }
.grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

@media (max-width: 1000px) { .grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 860px)  { .grid--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 620px) {
  .grid--2, .grid--3, .grid--4 { grid-template-columns: minmax(0, 1fr); }
}

/* ------------------------------------------------------------ preview bar */

.preview-bar {
  background: var(--band);
  color: var(--on-band);
  font-size: 14.5px;
  padding-block: 9px;
}
.preview-bar .shell {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 10px 16px; justify-content: center; text-align: center;
}
.preview-bar strong { color: var(--band-accent); font-weight: 700; }
.preview-bar a { color: var(--band-accent); }

/* ---------------------------------------------------------------- header */

.header {
  position: sticky; inset-block-start: 0; z-index: 40;
  background: var(--bg);
  border-block-end: 1px solid var(--line);
}
.header__inner {
  min-block-size: var(--header-h);
  display: flex; align-items: center; gap: 20px;
}

.brand { display: inline-flex; align-items: center; gap: 12px; text-decoration: none; }
.brand__logo { block-size: 46px; width: auto; }
@media (max-width: 900px) { .brand__logo { block-size: 38px; } }
.brand__mark {
  /* Only rendered if the logo file is missing. White needs the dark end of the
     ramp: 7.56:1 on green-800, where --brand itself would give 3.10:1. */
  inline-size: 42px; block-size: 42px; border-radius: 50%;
  background: var(--brand-dark); color: #fff;
  display: grid; place-items: center;
  font-family: var(--font-head); font-weight: 800; font-size: 22px;
}
.brand__name { display: block; font-family: var(--font-head); font-weight: 800; font-size: 20px;
                color: var(--ink); line-height: 1.1; }
.brand__sub  { display: block; font-size: 12.5px; color: var(--ink-3); }

.header__spacer { flex: 1 1 auto; }

/* Desktop navigation */
.nav { display: flex; align-items: center; gap: 2px; }
.nav__list { display: flex; align-items: center; gap: 2px; list-style: none; margin: 0; padding: 0; }
.nav__item { position: relative; }
.nav__link {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 10px 13px; border-radius: var(--radius-sm);
  font-family: var(--font-ui); font-weight: 500; font-size: 14.5px;
  color: var(--ink); text-decoration: none; white-space: nowrap;
}
html[dir="rtl"] .nav__link { font-family: var(--font-ar-head); font-size: 15.5px; }
.nav__link:hover { background: var(--brand-wash); color: var(--brand-dark); }
.nav__link[aria-current="page"] { color: var(--brand-dark); }
.nav__link[aria-current="page"]::after {
  content: ""; position: absolute; inset-block-end: -1px; inset-inline: 13px;
  block-size: 3px; background: var(--brand); border-radius: 2px 2px 0 0;
}
.nav__link svg { inline-size: 16px; block-size: 16px; fill: currentColor; }

/* The panel hangs 6px clear of the link, and those 6px used to be dead
   ground: the pointer left .nav__item on the way down, :hover dropped, and the
   menu closed under the cursor. The client reported it as "the sub-menu
   disappears, I need several attempts" — measured in Chrome, y 107-111 below
   the link hit-tested as .header__inner, not as the item. Two things fix it:

     · ::before fills exactly that strip with a transparent extension of the
       panel, so the hover target runs unbroken from link to first row;
     · the panel no longer slides on the way out. translateY(-6px) moved the
       panel — and its bridge — up and away from the descending cursor at the
       very moment hover was most fragile, which is what turned a 6px gap into
       "several attempts". It fades now, and never moves.

   z-index because .nav__item is positioned: without it a later sibling item
   paints over the panel of an earlier one. */
.nav__panel {
  position: absolute; inset-block-start: calc(100% + 6px); inset-inline-start: 0;
  z-index: 1;
  min-inline-size: 250px;
  background: var(--bg); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow-2);
  padding: 8px; list-style: none; margin: 0;
  opacity: 0; visibility: hidden;
  transition: opacity .16s ease, visibility .16s;
}
/* 8px, not the 6px of the gap: an exactly-abutting edge hit-tests ambiguously
   on the shared line, and a probe found the pointer still landing on
   .header__inner at that one row. Two pixels of overlap into the link removes
   the seam outright. The strip is only live while the panel is open. */
.nav__panel::before {
  content: ""; position: absolute;
  inset-block-end: 100%; inset-inline: 0; block-size: 8px;
}
.nav__item:hover .nav__panel,
.nav__item:focus-within .nav__panel {
  opacity: 1; visibility: visible;
}
.nav__panel a {
  display: block; padding: 9px 12px; border-radius: var(--radius-sm);
  font-size: 15px; color: var(--ink); text-decoration: none;
}
.nav__panel a:hover { background: var(--brand-wash); color: var(--brand-dark); }

/* Header utilities */
.util { display: flex; align-items: center; gap: 6px; }
.util__rule { inline-size: 1px; block-size: 26px; background: var(--line); margin-inline: 6px; }

.lang {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 8px 13px; border: 1px solid var(--line-strong); border-radius: 999px;
  font-family: var(--font-head); font-weight: 700; font-size: 14px;
  color: var(--ink); text-decoration: none; background: var(--bg);
}
.lang:hover { border-color: var(--brand); background: var(--brand-wash); color: var(--brand-dark); }
.lang svg { inline-size: 17px; block-size: 17px; fill: currentColor; }
html[dir="rtl"] .lang { font-family: var(--font-body); }

.icon-link {
  display: inline-grid; place-items: center;
  inline-size: 38px; block-size: 38px; border-radius: 50%;
  color: var(--ink-2); text-decoration: none;
}
.icon-link svg { inline-size: 19px; block-size: 19px; fill: currentColor; }
.icon-link:hover { background: var(--brand-wash); color: var(--brand-dark); }

.burger {
  display: none;
  align-items: center; gap: 9px;
  padding: 9px 14px; border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm); background: var(--bg);
  font-family: var(--font-head); font-weight: 700; font-size: 14.5px;
  color: var(--ink); cursor: pointer;
}
.burger svg { inline-size: 20px; block-size: 20px; fill: currentColor; }
.burger:hover { border-color: var(--brand); background: var(--brand-wash); }

@media (max-width: 1080px) {
  .nav, .util__desktop { display: none; }
  .burger { display: inline-flex; }
}

/* ---------------------------------------------------------------- drawer */
/* A sibling of the header, never a child: inside the header's stacking
   context it paints under the logo, and it cannot honour a sticky offset. */

.drawer[hidden] { display: none !important; }

.drawer {
  position: fixed; inset: 0; z-index: 60;
  display: grid;
  /* grid-template-columns is in LOGICAL order: under RTL the browser already
     reverses the tracks, so column 2 is on the left of its own accord.
     Reversing it again here as well put the panel back on the right while the
     transform still assumed it was on the left — so it started off-screen left
     and flew the full width of the viewport to land on the right. Let the grid
     do its own mirroring; only the transform needs a sign. */
  grid-template-columns: 1fr min(400px, 88vw);
}

.drawer__scrim {
  grid-area: 1 / 1 / 2 / 3;
  background: rgba(20, 17, 18, .55);
  opacity: 0; transition: opacity .22s ease;
  /* Opacity is not absence: without this the faded scrim keeps eating clicks. */
  pointer-events: none;
  border: 0; padding: 0; cursor: pointer;
}
.drawer__panel {
  grid-area: 1 / 2 / 2 / 3;
  background: var(--bg);
  display: flex; flex-direction: column;
  overflow-y: auto; overscroll-behavior: contain;
  box-shadow: var(--shadow-2);
  transform: translateX(100%);       /* physical: flipped for RTL below */
  transition: transform .24s ease;
}
html[dir="rtl"] .drawer__panel { transform: translateX(-100%); }

.drawer.is-open .drawer__scrim { opacity: 1; pointer-events: auto; }
.drawer.is-open .drawer__panel { transform: translateX(0); }

.drawer__head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 16px var(--pad); border-block-end: 1px solid var(--line);
  position: sticky; inset-block-start: 0; background: var(--bg); z-index: 1;
}
.drawer__close {
  display: inline-grid; place-items: center;
  inline-size: 42px; block-size: 42px;
  border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  background: var(--bg); color: var(--ink); cursor: pointer;
}
.drawer__close svg { inline-size: 20px; block-size: 20px; fill: currentColor; }
.drawer__close:hover { border-color: var(--brand); background: var(--brand-wash); }

.drawer__nav { padding: 10px var(--pad) var(--pad); }
.drawer__nav ul { list-style: none; margin: 0; padding: 0; }
.drawer__link {
  display: block; padding: 13px 12px; border-radius: var(--radius-sm);
  font-family: var(--font-head); font-weight: 700; font-size: 17px;
  color: var(--ink); text-decoration: none;
}
html[dir="rtl"] .drawer__link { font-family: var(--font-ar-head); }
.drawer__link:hover { background: var(--brand-wash); color: var(--brand-dark); }
.drawer__link[aria-current="page"] { background: var(--brand-wash); color: var(--brand-dark); }

/* Submenus collapse with <details> so the drawer works with scripting off —
   three product categories otherwise push the rest of the menu off a phone. */
.drawer details > summary {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 13px 12px; border-radius: var(--radius-sm);
  font-family: var(--font-head); font-weight: 700; font-size: 17px;
  color: var(--ink); cursor: pointer; list-style: none;
}
html[dir="rtl"] .drawer details > summary { font-family: var(--font-ar-head); }
.drawer details > summary::-webkit-details-marker { display: none; }
.drawer details > summary:hover { background: var(--brand-wash); color: var(--brand-dark); }
.drawer details > summary svg {
  inline-size: 20px; block-size: 20px; fill: currentColor;
  transition: transform .18s ease; flex: none;
}
.drawer details[open] > summary svg { transform: rotate(180deg); }
.drawer details ul { padding-inline-start: 12px; margin-block-end: 6px; }

/* A group whose label navigates and whose chevron expands. The anchor is laid
   over the label half of the summary row, so a tap on the words follows the
   link and a tap on the chevron works the disclosure — with or without JS,
   and with no interactive element nested inside <summary>. */
.dgroup { position: relative; }
.dgroup > details > summary { min-block-size: 50px; }
.dgroup__cover {
  position: absolute; inset-block-start: 0; inset-inline-start: 0;
  block-size: 50px; inline-size: calc(100% - 56px);
  border-radius: var(--radius-sm);
}
/* The cover sits ON TOP of the label in order to catch the tap, so it must
   never paint a background of its own — it would paint over the very words it
   exists to activate, and the label would vanish on hover. The tint belongs to
   the summary underneath; :has() is what lets a hover on the overlay style the
   element behind it. Where :has() is unsupported the only thing lost is the
   tint, never the text. */
.dgroup__cover { background: transparent; }
.dgroup:has(> .dgroup__cover:hover) > details > summary,
.dgroup:has(> .dgroup__cover:focus-visible) > details > summary,
.dgroup:has(> .dgroup__cover[aria-current="page"]) > details > summary {
  background: var(--brand-wash);
  color: var(--brand-dark);
}
.dgroup__label { pointer-events: none; }
.drawer details .drawer__link { font-size: 15.5px; font-weight: 600; color: var(--ink-2); }

.drawer__foot {
  margin-block-start: auto;
  padding: var(--pad); border-block-start: 1px solid var(--line);
  background: var(--bg-soft);
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
}

/* ----------------------------------------------------------- scroll reveal */
/* Guarded on [data-anim], which the script sets on itself. With scripting off
   the attribute is never written, so nothing is ever hidden — the content does
   not depend on an observer that may never run. */

[data-anim] .reveal {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity .6s ease, transform .6s cubic-bezier(.22, .61, .36, 1);
}
[data-anim] .reveal.is-in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  [data-anim] .reveal { opacity: 1; transform: none; transition: none; }
}

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

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  padding: 13px 24px; border-radius: var(--radius-sm);
  font-family: var(--font-ui); font-weight: 500; font-size: 15.5px;
  text-decoration: none; cursor: pointer; border: 1px solid transparent;
  transition: background .16s ease, border-color .16s ease, color .16s ease;
}
html[dir="rtl"] .btn { font-family: var(--font-ar-head); font-size: 16px; }
.btn svg { inline-size: 18px; block-size: 18px; fill: currentColor; flex: none; }

/* The primary button is the one place the green ramp has to carry a label.
   White on green-500 is 3.10:1 and fails, so the fill is green-700: white on
   it is 5.40:1, and 7.56:1 on the green-800 it hovers to — the button gets
   DARKER under the pointer, which is also the direction the ghost and chip
   hovers move. Orange keeps the same job on a dark band (.btn--onband). */
.btn--primary { background: var(--green-700); color: #fff; }
.btn--primary:hover { background: var(--green-800); color: #fff; }

.btn--ghost { background: var(--bg); color: var(--brand-dark); border-color: var(--line-strong); }
.btn--ghost:hover { border-color: var(--brand); background: var(--brand-wash); color: var(--brand-dark); }

/* The band button carries ink on green-300 (7.42:1) and darkens to green-500
   on hover (5.26:1) — the same direction the primary button moves on white. */
.btn--onband { background: var(--band-accent); color: #231f20; }
.btn--onband:hover { background: var(--green-500); color: #231f20; }

/* On a photograph a white-bordered ghost reads; a grey-bordered one vanishes. */
.btn--outline {
  background: rgba(255, 255, 255, .12); color: #fff;
  border-color: rgba(255, 255, 255, .55);
}
.btn--outline:hover { background: rgba(255, 255, 255, .2); border-color: #fff; color: #fff; }

.btn--wide { inline-size: 100%; }

.btn-row { display: flex; flex-wrap: wrap; gap: 12px; margin-block-start: 26px; }

.arrow-link {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--font-head); font-weight: 700; font-size: 15.5px;
  color: var(--brand-deep); text-decoration: none;
}
html[dir="rtl"] .arrow-link { font-family: var(--font-ar-head); }
.arrow-link svg { inline-size: 17px; block-size: 17px; fill: currentColor; }
.arrow-link:hover { color: var(--brand-dark); text-decoration: underline; }

/* ------------------------------------------------- direction-carrying icons */
/* An arrow or a caret means "onward", and onward is leftward in Arabic. The
   flip belongs to the glyph, not to the components that hold one: the arrow
   appears in .btn, .arrow-link and the range cards, and flipping it per
   component is how .btn kept pointing the English way on every RTL page. */

.i-dir { transition: transform .16s ease; }
html[dir="rtl"] .i-dir { transform: scaleX(-1); }

.arrow-link:hover .i-dir { transform: translateX(3px); }
/* Specificity has to beat the rule above, or the hover state un-flips it. */
html[dir="rtl"] .arrow-link:hover .i-dir { transform: scaleX(-1) translateX(3px); }

/* ---------------------------------------------------- photographic bands */
/* Flat colour undersells this kind of business. So the dark bands carry
   the client's own product photography, moving slowly against the scroll.
   The rule that governs all of it: the photograph is decoration and the
   overlay is not optional. Text sits on the same effective colour it had over
   flat #0F2F36, so nothing on top loses a point of contrast. */

.band--photo { position: relative; isolation: isolate; overflow: clip; contain: paint; }

.band__bg {
  position: absolute; inset: -14% 0; z-index: -2;
  /* Promote it: without this the browser re-rasterises a 1700px-wide upscaled
     photograph on every scroll frame. With four of them on the homepage that
     starved the main thread completely — requestAnimationFrame stopped firing
     altogether. A parallax that costs the page its frame budget is not a
     nice touch, it is a bug. */
  will-change: transform;
  backface-visibility: hidden;
}
.band__bg img {
  inline-size: 100%; block-size: 100%;
  object-fit: cover; object-position: center;
}
/* The overlay. Two things changed here after the client said the pictures
   "look all green and unclear", and both were the same mistake:

   1. It was GREEN. A saturated wash does not darken a photograph, it recolours
      it — every image came out the same shade of moss regardless of what was
      in it. This one is near-neutral, so the picture keeps its own colour and
      only loses brightness.
   2. It was heavy. The overlay flattens the photograph by (1 - alpha), so the
      overlay and the image tone are one decision. Measured across the five
      band images: darkening the source to 0.52 needs only a 0.26 overlay and
      keeps 74% of the photograph's contrast, where leaving it bright at 0.76
      needed 0.49 and kept 51%. Darker picture, lighter wash, clearer result.

   0.30 is the floor, pinned to the ABSOLUTE brightest pixel in any of the five
   images at FULL resolution — rgb(146,142,111). Measuring on a downscaled copy
   first said 0.26, because resampling averages pixels away and hides the peak;
   at full size the pale eyebrow came in just under 4.5:1 there. On the real
   ground white is 5.4:1, the body tone 4.8:1 and the eyebrow 4.8:1. The
   gradient runs 0.36 down to 0.30, so the top of a band — where a heading
   usually sits — has a little more to spare than the floor. */
.band--photo::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(170deg, rgba(16, 14, 15, .36), rgba(22, 19, 20, .30));
}

/* There were two rules here giving a photo band its own paler eyebrow. They
   never applied: `.band .eyebrow` further down has the same specificity and
   comes later, so it won every time, and the eyebrow on a photograph was the
   full accent rather than the pale one the comment promised. Rather than
   restore a rule nobody has seen, the single `.band .eyebrow` rule below now
   carries --band-accent-soft for every band, photo or flat. */

/* ---------------------------------------------------- the leading hero --- */
/* This hero used to be an asymmetric split: the claim on one side, vision,
   mission and value stacked as three panels beside it. The client asked on
   2026-09-19 for that trio to live in the About Diamond section instead, so
   the hero is the claim alone now — mark, eyebrow, tagline, strapline, two
   buttons — on one measure rather than two columns. The .pillar rules went
   with the markup; the trio is plain .card work in the section below. */

.hero--lead { padding-block: clamp(52px, 7vw, 92px) clamp(76px, 9vw, 128px); }
.hero__lead { display: flex; flex-direction: column; align-items: flex-start; }
.hero__mark { inline-size: clamp(84px, 9vw, 116px); margin-block-end: 22px; }
.hero--lead .hero__title {
  font-size: clamp(30px, 3.6vw, 46px); font-weight: 900;
  max-inline-size: 14em; color: #fff; text-wrap: balance;
}
/* Wider than the old 34ch: the strapline no longer shares the row with the
   pillars, so it can run to a full reading measure instead of a column. */
.hero--lead .hero__lede { color: var(--on-band-dim); max-inline-size: 52ch; }
/* The lime eyebrow that used to be declared here was dead for the same reason
   as the .band--photo pair above — `.band .eyebrow` comes later. The hero now
   simply takes the band eyebrow like every other band. */

/* The numbers get their own slim strip under the hero rather than sitting
   inside it. */
.strip { background: var(--bg-soft); border-block-end: 1px solid var(--line); }
.strip .stats--row { margin-block: 0; max-inline-size: none; border: 0; }
.strip .stat { background: var(--bg-soft); padding-block: 26px; }

/* Three columns of lede rather than one very long measure. */
.lede-cols { columns: 3; column-gap: 40px; }
.lede-cols .lede { margin-block-start: 0; margin-block-end: 1em; max-width: none;
                   break-inside: avoid; }
@media (max-width: 1000px) { .lede-cols { columns: 2; } }
@media (max-width: 680px)  { .lede-cols { columns: 1; } }

/* ------------------------------------------------------------------ hero */

.hero {
  background:
    radial-gradient(1100px 420px at 78% -10%, rgba(52, 167, 73, .13), transparent 62%),
    var(--bg-soft);
  border-block-end: 1px solid var(--line);
  padding-block: clamp(46px, 7vw, 84px);
}

.hero--photo {
  background: var(--band);
  border-block-end: 0;
  padding-block: clamp(58px, 8vw, 104px);
}
.hero--photo .hero__title { color: #fff; }
.hero--photo .hero__title em { color: var(--band-accent); }
.hero--photo .eyebrow { color: var(--band-accent-soft); }
.hero--photo .eyebrow::before { background: var(--band-accent-soft); }
/* The logo is a green wordmark: 4.6:1 on this ground, and the petals carry it. */
.hero--photo .hero__logo { filter: drop-shadow(0 6px 20px rgba(0, 0, 0, .35)); }

/* No backdrop-filter here: blurring what is behind a panel forces the whole
   moving photograph beneath it to re-composite every frame. */
.hero--photo .stats {
  background: rgba(255, 255, 255, .16);
  border: 1px solid rgba(255, 255, 255, .22);
}
.hero--photo .stat { background: rgba(20, 17, 18, .5); }
.hero--photo .stat__n { color: #fff; }
.hero--photo .stat__l { color: var(--on-band-dim); }
/* The live site centres the logo, the tagline and one button. That lockup is
   kept — and it is also what makes the tagline readable. It is 108 characters:
   in a half-width column at display size it broke onto five lines. Full width
   at a smaller size, it is two. */
.hero__center { display: flex; flex-direction: column; align-items: center; text-align: center; }

.hero__title {
  font-size: clamp(25px, 3vw, 36px);
  font-weight: 700;
  max-inline-size: 22em;         /* measure follows the size, not the viewport */
  text-wrap: balance;
}
.hero__title em { font-style: normal; color: var(--brand-deep); }
/* Measure both languages: they do not break alike. The live Arabic hero is a
   different sentence from the English one and 60% longer, so it gets its own
   size and its own measure rather than inheriting a cap tuned on English. */
html[dir="rtl"] .hero__title {
  font-size: clamp(21px, 2.4vw, 29px);
  max-inline-size: 30em;
}

.hero__grid {
  display: grid; gap: clamp(28px, 4vw, 56px);
  grid-template-columns: 7fr 5fr; align-items: center;
}
@media (max-width: 900px) { .hero__grid { grid-template-columns: minmax(0, 1fr); } }

.hero__logo { inline-size: min(300px, 68%); margin-block-end: 22px; }

.btn-row--center { justify-content: center; }

.stats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 2px;
         background: var(--line); border-radius: var(--radius-sm); overflow: hidden; }
.stats--row {
  grid-template-columns: repeat(4, minmax(0, 1fr));
  inline-size: 100%; max-inline-size: 940px;
  margin-block-start: clamp(38px, 5vw, 58px);
  border: 1px solid var(--line);
  text-align: start;
}
@media (max-width: 760px) { .stats--row { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.stat { background: var(--bg); padding: 16px 18px; }
.stat__n {
  font-family: var(--font-head); font-weight: 800;
  font-size: 27px; line-height: 1.1; color: var(--brand-dark);
}
html[dir="rtl"] .stat__n { font-family: var(--font-ar-head); }
.stat__l { font-size: 13.5px; color: var(--ink-3); line-height: 1.45; margin-block-start: 4px; }

/* ----------------------------------------------------------------- cards */

.card {
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: var(--pad);
  display: flex; flex-direction: column; gap: 12px;
}
.card--link { text-decoration: none; color: inherit; transition: border-color .16s, box-shadow .16s, transform .16s; }
.card--link:hover { border-color: var(--brand); box-shadow: var(--shadow-2); transform: translateY(-3px); color: inherit; }
.card__title { font-family: var(--font-head); font-weight: 800; font-size: 19px; color: var(--ink); }
html[dir="rtl"] .card__title { font-family: var(--font-ar-head); }
.card__body { color: var(--ink-2); font-size: 16px; }
.card__foot { margin-block-start: auto; padding-block-start: 6px; }

.icon-tile {
  inline-size: 52px; block-size: 52px; border-radius: 14px;
  background: var(--brand-wash); color: var(--brand-dark);
  display: grid; place-items: center; flex: none;
}
.icon-tile svg { inline-size: 26px; block-size: 26px; fill: currentColor; }
.icon-tile--band { background: rgba(108, 193, 124, .16); color: var(--band-accent); }

/* A card on a photographic band. These used to carry their colours inline and
   still held #F2F7F8, the muted tone from when the bands were flat green — on
   a photograph it was far too weak to read. Body copy here is the same near
   white as the rest of the band, and the card has a real ground of its own
   rather than a 6% tint, so the text is never sitting straight on the picture. */
.band-card {
  background: rgba(20, 17, 18, .58);
  border-color: rgba(245, 240, 232, .22);
}
.band-card .card__title { color: #fff; }
.band-card .card__body { color: #faf7f2; }

/* A card that leads with a picture. The image bleeds to the card's edges, so
   it cancels the padding on three sides and the icon tile overlaps the seam. */
.card--media { padding-block-start: 0; overflow: hidden; }
.card__fig {
  display: block;
  margin: 0 calc(var(--pad) * -1) 4px;
  /* 4:3 made a wide card very deep, and the sources are 500px squares, so a
     4:3 crop was also being upscaled. 3:2 is shallower and, at the sizes these
     cards actually render, needs no upscaling at all. */
  aspect-ratio: 3 / 2;
  background: var(--bg-sunk);
  overflow: hidden;
}
.card__fig { position: relative; }
.card__fig img {
  position: absolute; inset: 0;
  inline-size: 100%; block-size: 100%; object-fit: cover;
  transition: transform .5s cubic-bezier(.22, .61, .36, 1);
}
.card--link:hover .card__fig img { transform: scale(1.05); }
@media (prefers-reduced-motion: reduce) {
  .card__fig img, .card--link:hover .card__fig img { transition: none; transform: none; }
}
/* The tile sits astride the picture's bottom edge rather than under it — and
   it has to be positioned to do that. The figure is position:relative so that
   its aspect-ratio governs the image inside it; a positioned box paints above
   its unpositioned siblings, so a static tile ends up BEHIND the picture and
   the overlapping 22px of it are simply cut off. Anything deliberately
   overlapping a positioned element needs a position of its own. */
.card--media .icon-tile {
  position: relative;
  z-index: 1;
  margin-block-start: -38px;
  box-shadow: var(--shadow-1);
  background: var(--bg);
}

.media-card__figure {
  margin: calc(var(--pad) * -1) calc(var(--pad) * -1) 0;
  background: var(--bg-sunk);
  border-radius: var(--radius) var(--radius) 0 0;
  overflow: hidden; aspect-ratio: 4 / 3;
  display: grid; place-items: center;
}
.media-card__figure img { inline-size: 100%; block-size: 100%; object-fit: cover; }

/* --------------------------------------------------------------- notices */

.notice {
  display: flex; gap: 14px; align-items: flex-start;
  background: var(--brand-wash);
  border: 1px solid var(--green-100);
  border-inline-start: 4px solid var(--brand);
  border-radius: var(--radius-sm);
  padding: 16px 18px; color: var(--ink-2); font-size: 15.5px;
}
.notice svg { inline-size: 20px; block-size: 20px; fill: var(--brand-dark); flex: none; margin-block-start: 3px; }
.notice--plain { background: var(--bg-soft); border-color: var(--line); border-inline-start-color: var(--line-strong); }
.notice--plain svg { fill: var(--ink-3); }

/* ------------------------------------------------------------ breadcrumbs */

.crumbs { padding-block: 16px; border-block-end: 1px solid var(--line); background: var(--bg-soft); }
.crumbs ol { display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
             list-style: none; margin: 0; padding: 0; font-size: 14.5px; }
.crumbs a { color: var(--ink-2); text-decoration: none; }
.crumbs a:hover { color: var(--brand-dark); text-decoration: underline; }
.crumbs li[aria-current] { color: var(--ink); font-weight: 600; }
.crumbs svg { inline-size: 15px; block-size: 15px; color: var(--ink-3); }

/* ------------------------------------------------------------------- wave */
/* The live site runs a wave along the bottom edge of every hero. Its own
   version animates margin-left, which lays out and paints on every frame at
   210% width; this one animates a transform instead — same motion, none of
   the cost. -52.4% of the element equals the -110% of the container the
   original used, because the element is 210% of the container. */

.wave {
  position: absolute; inset-inline: 0; inset-block-end: -1px;
  z-index: 2; line-height: 0; pointer-events: none;
  /* Elementor sets direction:ltr on its shape container and this is why: the
     SVG is wider than the box, and an overflowing box anchors to the END edge.
     Under RTL that put the wave's start off to the right, so the same negative
     drift walked it off the container entirely and the band showed through
     across most of the width. The wave is decoration with no text in it, so
     pinning its box direction costs nothing and makes the animation
     direction-independent. */
  direction: ltr;
}
.wave svg {
  display: block;
  /* The global reset caps every svg at max-width:100%, which silently held
     this one at container width — the drift then walked it clean off the right
     edge and the band showed through underneath. */
  max-inline-size: none;
  /* The SVG holds two identical copies of the wave, so it is twice as wide as
     the span we want on screen. 260% here shows one copy across roughly 130%
     of the container — the shape stays close to the live site's scale while
     the second copy waits off to the right. */
  inline-size: 260%;
  block-size: clamp(44px, 6.5vw, 92px);
  /* Linear, and exactly one copy of travel. At -50% the second copy sits
     precisely where the first began, so the restart is invisible and the wave
     drifts one way forever instead of sliding back on itself. Easing would
     reintroduce the very pulse the loop exists to remove. */
  animation: wave-drift 26s linear infinite;
  will-change: transform;
}
.wave path { fill: var(--wave-fill, var(--bg)); }

@keyframes wave-drift {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}
@media (prefers-reduced-motion: reduce) {
  .wave svg { animation: none; inline-size: 100%; max-inline-size: 100%; }
}

/* --------------------------------------------------------------- page top */

.page-head {
  position: relative;
  padding-block: clamp(52px, 7vw, 92px) clamp(72px, 9vw, 128px);
}
.page-head__inner > * { max-width: 68ch; }
.page-head h1 { color: #fff; }
.page-head .lede { color: var(--on-band-dim); }

/* The hero's own bottom padding has to clear the wave sitting in front of it. */
.hero--photo { padding-block-end: clamp(76px, 9vw, 132px); }

/* ------------------------------------------------------------- catalogue */

.cat { display: grid; grid-template-columns: var(--facets-w) minmax(0, 1fr); gap: 34px; }
@media (max-width: 1040px) { .cat { grid-template-columns: minmax(0, 1fr); } }

/* One panel, two presentations: a sticky sidebar on desktop, the same element
   as a slide-over below 1040px. No duplicated markup. */
.facets {
  position: sticky; inset-block-start: calc(var(--header-h) + 20px);
  align-self: start;
  max-block-size: calc(100vh - var(--header-h) - 40px);
  overflow-y: auto;
  padding-inline-end: 4px;
}
.facets__head { display: none; }
.facet { border-block-end: 1px solid var(--line); padding-block: 18px; }
.facet:first-child { padding-block-start: 0; }
.facet__title {
  font-family: var(--font-head); font-weight: 800; font-size: 13px;
  text-transform: uppercase; letter-spacing: .08em; color: var(--ink-3);
  margin-block-end: 12px;
}
html[dir="rtl"] .facet__title {
  font-family: var(--font-ar-head); text-transform: none;
  letter-spacing: normal; font-size: 14.5px;
}
.facet__list { display: flex; flex-wrap: wrap; gap: 8px; }

.chip {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 7px 13px; border-radius: 999px;
  border: 1px solid var(--line-strong); background: var(--bg);
  font-size: 14.5px; color: var(--ink-2); text-decoration: none;
  white-space: nowrap;
}
.chip:hover { border-color: var(--brand); background: var(--brand-wash); color: var(--brand-dark); }
.chip[aria-pressed="true"], .chip.is-on {
  background: var(--brand-dark); border-color: var(--brand-dark); color: #fff;
}
.chip__n { font-size: 12.5px; opacity: .75; font-variant-numeric: tabular-nums; }
.chip--static { pointer-events: none; }

.results__bar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 12px;
  margin-block-end: 20px;
}
.results__count { font-family: var(--font-head); font-weight: 700; color: var(--ink-2); font-size: 15.5px; }
html[dir="rtl"] .results__count { font-family: var(--font-ar-head); }

.search {
  position: relative; display: flex; align-items: center;
  margin-block-end: 20px;
}
.search svg {
  position: absolute; inset-inline-start: 15px;
  inline-size: 19px; block-size: 19px; fill: var(--ink-3); pointer-events: none;
}
.search input {
  inline-size: 100%; padding: 14px 18px; padding-inline-start: 46px;
  border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  font: inherit; font-size: 16.5px; color: var(--ink); background: var(--bg);
}
.search input:focus-visible { border-color: var(--brand); }

.filters-btn { display: none; }
.facets__apply { display: none; }
@media (max-width: 1040px) {
  .filters-btn { display: inline-flex; }
  .facets {
    position: fixed; inset: 0; z-index: 55;
    max-block-size: none; overflow: visible;
    padding: 0; display: grid;
    grid-template-columns: 1fr min(380px, 90vw);
    /* The sidebar above 1040px is a sticky, content-height box; its
       align-self:start follows the element in here and, on an out-of-flow box,
       means "size to content" rather than "fill the insets" — the sheet stopped
       short of the bottom of the screen and the page showed through under it. */
    align-self: stretch;
  }
  /* Restated: an author display:grid in a media query beats the UA [hidden]. */
  .facets[hidden] { display: none !important; }
  .facets::before {
    content: ""; grid-area: 1 / 1 / 2 / 3;
    background: rgba(20, 17, 18, .55);
    opacity: 0; transition: opacity .22s ease; pointer-events: none;
  }
  .facets.is-open::before { opacity: 1; }
  .facets__inner {
    grid-area: 1 / 2 / 2 / 3;
    background: var(--bg); overflow-y: auto; overscroll-behavior: contain;
    padding: 0 var(--pad) var(--pad);
    transform: translateX(100%); transition: transform .24s ease;
    display: flex; flex-direction: column;
  }
  /* Same rule as the drawer: the grid mirrors itself, only the sign flips. */
  html[dir="rtl"] .facets__inner { transform: translateX(-100%); }
  .facets.is-open .facets__inner { transform: translateX(0); }
  .facets__head {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    padding-block: 16px; border-block-end: 1px solid var(--line);
    position: sticky; inset-block-start: 0; background: var(--bg); z-index: 1;
    margin-block-end: 4px;
  }
  .facets__apply { display: block; margin-block-start: auto; padding-block-start: 20px; }
}

.pgrid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--gutter); }
@media (max-width: 1240px) { .pgrid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 900px)  { .pgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 480px)  { .pgrid { grid-template-columns: minmax(0, 1fr); } }

.pcard {
  --pcard-pad: 14px;
  display: flex; flex-direction: column;
  background: var(--bg); border: 1px solid var(--line);
  border-radius: var(--radius); overflow: hidden;
  text-decoration: none; color: inherit;
  transition: border-color .16s, box-shadow .16s, transform .16s;
}
.pcard:hover { border-color: var(--brand); box-shadow: var(--shadow-2); transform: translateY(-3px); color: inherit; }
/* The picture is inset to the same measure as the text beneath it rather than
   bleeding to the card's edges, so the two line up on both sides. */
.pcard__fig {
  /* 3/4 made a very deep card. 4/5 is still portrait, which suits the
     photography, without the grid turning into columns of tall slabs. */
  aspect-ratio: 4 / 5;
  background: var(--bg-sunk);
  position: relative; overflow: hidden;
  margin: var(--pcard-pad) var(--pcard-pad) 0;
  border-radius: var(--radius-sm);
}
/* Absolutely positioned, because otherwise the image's own intrinsic height
   wins: aspect-ratio only states a PREFERRED size, and an in-flow child taller
   than the ratio pushes the box open. That is why these cards were rendering
   503px and 506px tall instead of a uniform 485 — the ratio was being ignored
   and every card was a slightly different height. */
.pcard__fig img {
  position: absolute; inset: 0;
  inline-size: 100%; block-size: 100%; object-fit: cover;
  transition: transform .5s cubic-bezier(.22, .61, .36, 1);
}
.pcard:hover .pcard__fig img { transform: scale(1.05); }
@media (prefers-reduced-motion: reduce) {
  .pcard__fig img, .pcard:hover .pcard__fig img { transition: none; transform: none; }
}

/* Five of twelve references have no photograph. A designed plate, not a grey box. */
.plate {
  inline-size: 100%; block-size: 100%;
  display: grid; place-items: center; gap: 6px;
  background: linear-gradient(150deg, var(--green-50), var(--green-100));
  color: var(--brand-dark); text-align: center; padding: 18px;
}
.plate__glyph { font-family: var(--font-head); font-weight: 800; font-size: 46px; line-height: 1; }
.plate__code { font-family: var(--font-mono); font-size: 12.5px; letter-spacing: .05em; opacity: .8; }

.pcard__body { padding: 14px var(--pcard-pad) 18px; display: flex; flex-direction: column; gap: 8px; flex: 1; }
.pcard__name { font-family: var(--font-head); font-weight: 800; font-size: 18px; color: var(--ink); }
.pcard__meta { font-size: 14px; color: var(--ink-3); }
.pcard__tags { display: flex; flex-wrap: wrap; gap: 6px; margin-block-start: auto; padding-block-start: 8px; }
.tag {
  font-size: 12.5px; padding: 4px 10px; border-radius: 999px;
  background: var(--bg-soft); border: 1px solid var(--line); color: var(--ink-2);
}

.empty {
  border: 1px dashed var(--line-strong); border-radius: var(--radius);
  padding: 46px var(--pad); text-align: center; color: var(--ink-2);
  background: var(--bg-soft);
}
.empty h3 { margin-block-end: 8px; }

/* --------------------------------------------------------- product detail */

.detail { display: grid; grid-template-columns: 5fr 7fr; gap: clamp(26px, 3.5vw, 50px); align-items: start; }
@media (max-width: 900px) { .detail { grid-template-columns: minmax(0, 1fr); } }

.detail__fig {
  background: var(--bg-sunk); border: 1px solid var(--line);
  border-radius: var(--radius); overflow: hidden; aspect-ratio: 3 / 4;
  position: sticky; inset-block-start: calc(var(--header-h) + 20px);
}
@media (max-width: 900px) { .detail__fig { position: static; } }
.detail__fig { position: relative; }
.detail__fig img {
  position: absolute; inset: 0;
  inline-size: 100%; block-size: 100%; object-fit: cover;
}

.spec { inline-size: 100%; border-collapse: collapse; margin-block-start: 8px; }
.spec caption { text-align: start; color: var(--ink-3); font-size: 14px; padding-block-end: 10px; }
.spec th, .spec td {
  text-align: start; padding: 15px 4px;
  border-block-end: 1px solid var(--line); vertical-align: top;
}
.spec th {
  inline-size: 34%; font-family: var(--font-head); font-weight: 700;
  font-size: 14px; color: var(--ink-3); white-space: nowrap;
}
html[dir="rtl"] .spec th { font-family: var(--font-ar-head); white-space: normal; }
.spec td { color: var(--ink); }

.pager {
  display: flex; flex-wrap: wrap; justify-content: space-between; gap: 14px;
  border-block-start: 1px solid var(--line); padding-block-start: 26px; margin-block-start: 40px;
}
.pager a { display: inline-flex; flex-direction: column; gap: 2px; text-decoration: none; max-inline-size: 46%; }
.pager span { font-size: 13px; color: var(--ink-3); }
.pager strong { font-family: var(--font-head); font-weight: 700; color: var(--brand-deep); font-size: 16px; }
.pager a:hover strong { color: var(--brand-dark); text-decoration: underline; }
.pager .is-end { margin-inline-start: auto; text-align: end; }

/* ----------------------------------------------------------------- table */

.table-wrap { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--radius); }
.dtable { inline-size: 100%; border-collapse: collapse; font-size: 16px; min-inline-size: 420px; }
.dtable caption { text-align: start; padding: 16px var(--pad) 0; color: var(--ink-3); font-size: 14.5px; }
.dtable th, .dtable td { text-align: start; padding: 14px var(--pad); border-block-end: 1px solid var(--line); }
.dtable thead th {
  font-family: var(--font-head); font-size: 13px; text-transform: uppercase;
  letter-spacing: .07em; color: var(--ink-3); background: var(--bg-soft);
}
html[dir="rtl"] .dtable thead th {
  font-family: var(--font-ar-head); text-transform: none; letter-spacing: normal; font-size: 14.5px;
}
.dtable tbody tr:last-child th, .dtable tbody tr:last-child td { border-block-end: 0; }

/* A key/value table whose values are sentences rather than numbers. The 420px
   minimum above is right for the principal pages, where every value is a date
   or a count, but on About it pushes a seven-row table into a horizontal
   scroll on a phone. Below that width this variant stacks each row instead:
   label above value, the row rule kept so the pairs stay readable. */
@media (max-width: 560px) {
  .dtable--stack { min-inline-size: 0; }
  .dtable--stack tr { display: block; border-block-end: 1px solid var(--line); }
  .dtable--stack tbody tr:last-child { border-block-end: 0; }
  .dtable--stack th, .dtable--stack td { display: block; border-block-end: 0; }
  .dtable--stack th { padding-block-end: 2px; }
  .dtable--stack td { padding-block-start: 0; color: var(--ink-2); }
}
.dtable .num { font-variant-numeric: tabular-nums; color: var(--ink-2); }

.bar { block-size: 8px; border-radius: 4px; background: var(--brand); min-inline-size: 3px; }
.bar--zero { background: var(--line-strong); }

/* ------------------------------------------------------------------ band */

.band { background: var(--band); color: var(--on-band); }
.band h1, .band h2, .band h3 { color: #fff; }
.band p { color: var(--on-band-dim); }
/* Soft, not the full accent: this is the one place brand-coloured text sits
   directly on a photograph. 4.6:1 against the brightest pixel of every band,
   measured — green-300 would be 2.2:1 here. */
.band .eyebrow { color: var(--band-accent-soft); }
.band .eyebrow::before { background: var(--band-accent-soft); }

/* The closing band carries the motto and the newsletter over one photograph.
   They used to be two stacked photographic strips, which put a hard seam
   across the page and left the motto shouting on its own. */
.closing { padding-block: var(--section); }
.motto {
  color: #fff; text-align: center;
  padding-block-end: clamp(30px, 4vw, 48px);
  margin-block-end: clamp(30px, 4vw, 48px);
  border-block-end: 1px solid rgba(245, 240, 232, .18);
}
.motto__text {
  font-family: var(--font-head); font-weight: 800;
  font-size: clamp(19px, 2.3vw, 27px); letter-spacing: .02em;
}
html[dir="rtl"] .motto__text { font-family: var(--font-ar-head); letter-spacing: normal; }
.motto__rule {
  inline-size: 54px; block-size: 4px; background: var(--band-accent);
  border-radius: 2px; margin: 14px auto 0;
}

/* ------------------------------------------------------------ newsletter */

.news-band { background: var(--band); color: var(--on-band); padding-block: var(--section); }
.news-band__grid { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(24px, 4vw, 48px); align-items: center; }
@media (max-width: 860px) { .news-band__grid { grid-template-columns: minmax(0, 1fr); } }

.nl-form { display: flex; gap: 10px; flex-wrap: wrap; }
.nl-form input {
  flex: 1 1 240px; padding: 14px 18px; font: inherit; font-size: 16.5px;
  border: 1px solid rgba(245, 240, 232, .28); border-radius: var(--radius-sm);
  background: rgba(255, 255, 255, .07); color: #fff;
}
.nl-form input::placeholder { color: var(--on-band-dim); }
.nl-form input:focus-visible { border-color: var(--band-accent); background: rgba(255, 255, 255, .12); }

.form-msg { margin-block-start: 14px; font-size: 15.5px; }
.form-msg[hidden] { display: none !important; }
.band .form-msg { color: var(--band-accent-soft); }
.form-msg--bad { color: #b3261e; }
.band .form-msg--bad { color: #ffb4ab; }

/* ----------------------------------------------------------------- forms */

.form-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px; }
@media (max-width: 620px) { .form-grid { grid-template-columns: minmax(0, 1fr); } }
.field--full { grid-column: 1 / -1; }

.field { display: flex; flex-direction: column; gap: 7px; }
.field label {
  font-family: var(--font-head); font-weight: 700; font-size: 14.5px; color: var(--ink-2);
}
html[dir="rtl"] .field label { font-family: var(--font-ar-head); font-size: 15.5px; }
.field input, .field select, .field textarea {
  padding: 13px 15px; font: inherit; font-size: 16.5px; color: var(--ink);
  background: var(--bg); border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm); inline-size: 100%;
}
.field textarea { min-block-size: 140px; resize: vertical; }
.field input:focus-visible, .field select:focus-visible, .field textarea:focus-visible {
  border-color: var(--brand);
}
.field .err { font-size: 14px; color: #b3261e; min-block-size: 0; }
.field .err[hidden] { display: none !important; }
.field.is-bad input, .field.is-bad select, .field.is-bad textarea { border-color: #b3261e; }

/* --------------------------------------------------------------- contact */

.contact-grid { display: grid; grid-template-columns: 5fr 7fr; gap: clamp(26px, 4vw, 54px); align-items: start; }
@media (max-width: 900px) { .contact-grid { grid-template-columns: minmax(0, 1fr); } }

.deets { list-style: none; margin: 0; padding: 0; display: grid; gap: 18px; }
.deets li { display: flex; gap: 14px; align-items: flex-start; }
.deets .icon-tile { inline-size: 42px; block-size: 42px; border-radius: 11px; }
.deets .icon-tile svg { inline-size: 21px; block-size: 21px; }
.deets dt, .deets .k {
  font-family: var(--font-head); font-weight: 700; font-size: 13px;
  text-transform: uppercase; letter-spacing: .07em; color: var(--ink-3);
}
html[dir="rtl"] .deets .k {
  font-family: var(--font-ar-head); text-transform: none; letter-spacing: normal; font-size: 14.5px;
}
.deets .v { color: var(--ink); }
.deets a { text-decoration: none; }
.deets a:hover { text-decoration: underline; }

/* ---------------------------------------------------------------- footer */

/* The footer used to run #F2F7F8 on #0F2F36 — legible, but a washed-out green
   on green. White reads as a deliberate choice rather than a faded one, and it
   takes the contrast from 6.6:1 to 13.3:1. */
.footer { background: var(--band); color: #ffffff; padding-block: 56px 0; font-size: 15.5px; }
.footer h3 {
  color: #fff; font-size: 14px; text-transform: uppercase; letter-spacing: .08em;
  margin-block-end: 14px;
}
html[dir="rtl"] .footer h3 { text-transform: none; letter-spacing: normal; font-size: 16px; }
.footer__grid { display: grid; grid-template-columns: 2fr 1fr 1fr 1fr; gap: 32px; }
@media (max-width: 900px) { .footer__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .footer__grid { grid-template-columns: minmax(0, 1fr); } }
.footer ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 9px; }
.footer a { color: #ffffff; text-decoration: none; }
.footer a:hover { color: var(--band-accent); text-decoration: underline; }
.footer__logo { inline-size: 168px; margin-block-end: 16px; }
.footer .icon-link { color: #ffffff; }
.footer .icon-link:hover { background: rgba(255, 255, 255, .1); color: var(--band-accent); }
.footer__bar {
  margin-block-start: 44px; border-block-start: 1px solid rgba(245, 240, 232, .16);
  padding-block: 20px;
  display: flex; flex-wrap: wrap; gap: 10px 20px; justify-content: space-between;
  font-size: 14.5px;
}


/* ==========================================================================================
   CMS ADDITIONS — not in the approved preview (Diamond CMS phase 4, 2026-09-21)

   The static preview has no numbered paging and never waits for a server, so it has no rules for
   either. The CMS pages the chemicals catalogue and the news list on the server (Daisy ADR-0025) and
   shows skeleton cards while the next view loads (Daisy ADR-0031). These two blocks are carried over
   VERBATIM from Daisy CMS's stylesheet, which is the same design system: every token they name
   (--brand, --brand-wash, --brand-dark, --line-strong, --bg-sunk ...) exists here with Diamond's
   values, so they take Diamond's green without a single colour of their own. Contrast: the current
   page is white on --brand-dark (green-800, 7.56:1); hover is --brand-dark on --brand-wash.

   Everything ABOVE this line is the preview's diamond.css, byte for byte. Change the design there
   and re-copy; change only CMS behaviour here.
   ========================================================================================== */

/* ========================================================================== pagination
   ADR-0025. The approved preview has no numbered pagination — only .pager, for previous and next
   product — so this is built from the design's own vocabulary: the chip's pill shape and border, the
   brand-dark fill for the current page that an active chip already uses, and the head face for the
   numbers. Logical properties only; the arrows mirror through .i-dir. */

.pagination {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: 10px; margin-block-start: 36px;
}
.pagination__pages {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  list-style: none; margin: 0; padding: 0;
}
.pagination__page,
.pagination__step {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  min-inline-size: 42px; block-size: 42px; padding-inline: 12px;
  border: 1px solid var(--line-strong); border-radius: 999px; background: var(--bg);
  font-family: var(--font-head); font-weight: 700; font-size: 15px; color: var(--ink-2);
  text-decoration: none; font-variant-numeric: tabular-nums;
  transition: border-color .16s, background-color .16s, color .16s;
}
html[dir="rtl"] .pagination__page,
html[dir="rtl"] .pagination__step { font-family: var(--font-ar-head); }
.pagination__page:hover,
.pagination__step:hover { border-color: var(--brand); background: var(--brand-wash); color: var(--brand-dark); }
.pagination__page.is-current {
  background: var(--brand-dark); border-color: var(--brand-dark); color: #fff;
}
.pagination__step { padding-inline: 16px; }
.pagination__step svg { inline-size: 17px; block-size: 17px; }
/* "Previous" points against the reading direction: the forward arrow, turned round. Under RTL .i-dir
   is already mirrored once, so the back arrow is mirrored back. */
.pagination__back .i-dir { transform: scaleX(-1); }
html[dir="rtl"] .pagination__back .i-dir { transform: none; }
.pagination__gap { padding-inline: 4px; color: var(--ink-3); }
@media (prefers-reduced-motion: reduce) {
  .pagination__page, .pagination__step { transition: none; }
}

/* ======================================================================= skeleton loaders
   ADR-0025, amended by ADR-0031. Placeholder cards shown INSIDE the grid being reloaded — the
   products grid or the news grid — while the next view is on its way. site.js copies them from the
   <template>s in PublicLayout into the [data-skeleton-host], hides the real cards and marks the host
   aria-busy. The cards sit in the grid's own columns, so nothing around the grid moves. */

[data-skeleton-host].is-loading > :not(.skeleton__card) { display: none !important; }

.skeleton__card {
  display: grid; gap: 12px; align-content: start; padding: 14px;
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--bg);
  animation: skeleton-in .2s ease-out both;
}
.skeleton__fig { aspect-ratio: 1 / 1; border-radius: var(--radius-sm); }
.skeleton__card--news .skeleton__fig { aspect-ratio: 16 / 9; }
.skeleton__line { block-size: 13px; border-radius: 999px; }
.skeleton__line--title { block-size: 20px; inline-size: 72%; }
.skeleton__line--short { inline-size: 48%; }

.skeleton__fig,
.skeleton__line {
  background: linear-gradient(90deg, var(--bg-sunk) 0%, var(--bg-soft) 50%, var(--bg-sunk) 100%);
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.3s ease-in-out infinite;
}
/* The shimmer travels in the reading direction. */
html[dir="rtl"] .skeleton__fig,
html[dir="rtl"] .skeleton__line { animation-direction: reverse; }

@keyframes skeleton-shimmer {
  from { background-position: 100% 0; }
  to   { background-position: -100% 0; }
}
@keyframes skeleton-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .skeleton__card, .skeleton__fig, .skeleton__line { animation: none; }
}

/* ⚠️ Blazor's <FocusOnNavigate Selector="h1"> moves focus to the page heading after a navigation — a
   real accessibility win: a screen-reader user lands at the top of the new page. To do it, it gives the
   h1 tabindex="-1", and the browser then matches :focus-visible and paints the focus ring around the
   title of every page. The client's approved design has no such ring. (Carried over from Daisy CMS.)

   Suppressed only for a heading focused this way. A heading with tabindex="-1" is not something anyone
   can tab to, so no keyboard affordance is removed; every real control keeps its indicator. Do not widen
   this rule. */
:is(h1, h2)[tabindex="-1"]:focus-visible { outline: none; }

/* The chemical card's picture area when there is no photo but there IS a short description (owner,
   2026-09-22, Diamond ADR-0016): the text sits on the same green plate as the initials, so a card with
   no photo is still a designed card and not an empty box. --brand-dark on the plate's green-50/100
   gradient is the pairing .plate__glyph already uses. Clamped so a long description cannot stretch
   one card taller than its row. */
.plate--text { place-items: center start; padding: 22px; text-align: start; }
.plate__text {
  font-family: var(--font-head); font-weight: 700; font-size: 16px; line-height: 1.45;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 8; line-clamp: 8; overflow: hidden;
}

/* A chemical's own page (ADR-0016) is the first page to use .detail__fig. The rules above make it sticky with
   inset-block-start: header + 20px, then set position: relative — and a RELATIVE box with an inset is moved by it,
   so the picture sat ~98px below the title and covered the pager's "Previous" (seen 2026-09-22). Sticky on a wide
   screen, as the first rule meant (a sticky box is still the absolute image's containing block); relative with no
   offset once the columns stack. */
.detail__fig { position: sticky; }
@media (max-width: 900px) { .detail__fig { position: relative; inset-block-start: auto; } }

/* ================================================================== product picker
   The contact form's optional, searchable product list (owner, 2026-09-24), built by site.js from a plain
   <select multiple data-refpick>. Carried over from Daisy CMS's stylesheet — every token exists here with
   Diamond's values; the one colour Daisy named (#d8efe7 on the initials plate) is replaced by the catalogue
   plate's own green-50/100 gradient. Added for Diamond: .refpick__group, the range heading above each
   group of options. Logical properties only. */

.refpick { position: relative; }

.refpick__button {
  display: flex; align-items: center; gap: 10px; inline-size: 100%; min-block-size: 52px;
  padding-block: 6px; padding-inline: 10px 14px;
  font: inherit; font-size: 16.5px; color: var(--ink); text-align: start;
  background: var(--bg); border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  cursor: pointer;
}
.refpick__button:focus-visible,
.refpick__button[aria-expanded="true"] { border-color: var(--brand); }
.refpick__button > svg { flex: none; inline-size: 18px; block-size: 18px; margin-inline-start: auto; color: var(--ink-3); }
.field.is-bad .refpick__button { border-color: #b3261e; }

.refpick__panel {
  position: absolute; inset-inline: 0; inset-block-start: calc(100% + 6px); z-index: 20;
  padding: 8px; background: var(--bg);
  border: 1px solid var(--line-strong); border-radius: var(--radius-sm); box-shadow: var(--shadow-2);
}
.refpick__panel[hidden] { display: none; }

.field .refpick__search { padding: 10px 12px; font-size: 15.5px; }

.refpick__list { list-style: none; margin: 8px 0 0; padding: 0; max-block-size: 320px; overflow-y: auto; }
.refpick__option {
  display: flex; align-items: center; gap: 10px;
  padding: 6px 8px; border-radius: 8px; cursor: pointer;
}
.refpick__option[hidden] { display: none; }

/* The range a run of options belongs to. --ink-3 on --bg is the pairing the field captions already use. */
.refpick__group {
  padding: 12px 8px 4px;
  font-family: var(--font-ui); font-size: 12.5px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  color: var(--ink-3);
}
.refpick__group:first-child { padding-block-start: 4px; }
.refpick__group[hidden] { display: none; }
html[dir="rtl"] .refpick__group { letter-spacing: 0; text-transform: none; font-size: 14px; }

.refpick__thumb {
  flex: none; display: grid; place-items: center; overflow: hidden;
  inline-size: 40px; block-size: 40px; border-radius: 8px;
  background: var(--bg-soft); border: 1px solid var(--line);
}
.refpick__thumb img { inline-size: 100%; block-size: 100%; object-fit: cover; }
.refpick__thumb--plate {
  background: linear-gradient(150deg, var(--green-50), var(--green-100));
  font-family: var(--font-head); font-weight: 800; font-size: 14px; color: var(--brand-dark);
}

.refpick__text { display: flex; flex-direction: column; min-inline-size: 0; line-height: 1.3; }
.refpick__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.refpick__code { font-size: 13px; color: var(--ink-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.refpick__button .refpick__text { flex: 1 1 auto; }

.refpick__empty { margin: 0; padding: 10px 8px; font-size: 15px; color: var(--ink-3); }
.refpick__empty[hidden] { display: none; }

/* Several products chosen: their thumbnails overlap, the first on top. */
.refpick__stack { display: flex; flex: none; }
.refpick__stack .refpick__thumb + .refpick__thumb { margin-inline-start: -16px; box-shadow: 0 0 0 2px var(--bg); }

/* Picked products, unmistakably: a checkbox that fills with the brand colour and a tinted row. The
   keyboard/hover highlight is a quieter outline, so "picked" and "under the cursor" never look alike. */
.refpick__check {
  flex: none; display: grid; place-items: center;
  inline-size: 20px; block-size: 20px;
  border: 1.5px solid var(--line-strong); border-radius: 5px;
  background: var(--bg); color: transparent;
}
.refpick__check svg { inline-size: 14px; block-size: 14px; }

.refpick__option.is-active { background: var(--bg-soft); box-shadow: inset 0 0 0 1px var(--line-strong); }
.refpick__option[aria-selected="true"] { background: var(--brand-wash); }
.refpick__option[aria-selected="true"] .refpick__name { color: var(--brand-dark); font-weight: 700; }
.refpick__option[aria-selected="true"].is-active { box-shadow: inset 0 0 0 1px var(--brand); }
.refpick__option[aria-selected="true"] .refpick__check {
  background: var(--brand-dark); border-color: var(--brand-dark); color: #fff;
}
