/* ============================================================================
   Daisy General Trading Co. — "Clear" direction
   ----------------------------------------------------------------------------
   Written after the client found the Premium Minimalism preview hard to read.
   The structure of the live daisy-jo.com site is kept; the legibility is not.

   What changed, and why. Note what is NOT on this list: primary contrast.
   Minimalism ran #1a1a1a on #fbf9f4, which measures 16.5:1 — it was never the
   problem, and saying so would have been an easy, wrong diagnosis. What made
   it hard to read was everything else:
     · Base size is 17px at 1.75 leading. Minimalism ran 16px at 1.6 with
       positive letter-spacing on the body — small, tight and tracked out.
     · Secondary text is #6B7A74 (4.5:1), over the AA line. Minimalism's
       --ink-muted was #747878 at 4.2:1, which is under it, and it carried
       nav links, meta lines and counts.
     · Borders are visible (#DBE6E1, 1px solid) rather than 15%-alpha
       hairlines, so a card looks like a card and a button like a button.
     · Sans throughout. Playfair Display is gone: it has no Arabic coverage at
       all, and it was setting long paragraphs it was never cut for.
     · Nothing is set in full capitals at paragraph length. The live supplier
       page is entirely uppercase; that alone costs a reader real speed.

   Colour is the client's own logo, and ADR-005's addendum governs it:
     green  #1EAF8A  — the wordmark. 2.8:1 on white: NEVER carries text.
     yellow #FADD21  — the petals.   1.3:1 on white: dark surfaces only.
   So the green that carries text is #0E7A5F (5.3:1 on white) and the fill
   behind white text is #0A5644 (8.7:1). White on the logo green is 2.8:1 and
   fails, which is why no button is ever filled with it. The bright green is
   for marks, rules and icon fills only.

   Logical properties only — one stylesheet serves LTR English and RTL Arabic.
   The two exceptions are transforms, which have no logical form; each is
   flipped explicitly under [dir="rtl"] and marked.
   ========================================================================== */

:root {
  /* Ground */
  --bg:            #ffffff;
  --bg-soft:       #f4f9f7;
  --bg-sunk:       #eaf2ef;

  /* Dark bands — footer, motto, hero panel */
  --band:          #073f32;
  --band-2:        #0a5644;
  --on-band:       #eaf5f1;
  /* Was #A9C8BD. Nothing consumes it unoverridden any more, but leaving a
     weak tone as the DEFAULT means the next dark section anyone adds inherits
     the exact bug we just fixed. The safe value is the default. */
  --on-band-dim:   #eaf5f1;

  /* Ink */
  --ink:           #12211c;
  --ink-2:         #46554f;
  /* Was #6B7A74, which is 4.51:1 on white and therefore "fine" — but it also
     lands on --bg-soft (4.23:1) and --bg-sunk (3.96:1), where it fails. A muted
     tone has to clear AA on the LIGHTEST ground it is used on AND the darkest;
     #61706A clears all three (5.21 / 4.89 / 4.57). */
  --ink-3:         #61706a;

  /* Brand */
  --brand:         #1eaf8a;   /* logo green — fills and marks, never text on white */
  --brand-deep:    #0e7a5f;   /* text-safe green */
  --brand-dark:    #0a5644;   /* button fill behind white text */
  --brand-wash:    #e7f6f1;
  --yellow:        #fadd21;   /* dark surfaces only */

  /* Structure */
  --line:          #dbe6e1;
  --line-strong:   #b3c8c0;
  --radius:        14px;
  --radius-sm:     9px;
  --shadow-1:      0 1px 2px rgba(7, 63, 50, .06), 0 2px 8px rgba(7, 63, 50, .05);
  --shadow-2:      0 6px 14px rgba(7, 63, 50, .09), 0 18px 40px rgba(7, 63, 50, .08);

  /* Type — the live site's own faces. Its stylesheets declare Roboto 165
     times and Cairo 25: Roboto carries the Latin pages, Cairo the Arabic
     ones. Weight does the work that a second family used to. */
  --font-head: "Roboto", "Segoe UI", system-ui, -apple-system, sans-serif;
  --font-body: "Roboto", "Segoe UI", system-ui, -apple-system, sans-serif;
  --font-mono: "Roboto Mono", ui-monospace, Consolas, "Liberation Mono", monospace;

  /* Cairo covers Latin as well as Arabic, which is what keeps a product code
     legible inside an Arabic sentence. */
  --font-ar-head: "Cairo", "Segoe UI", Tahoma, sans-serif;
  --font-ar-body: "Cairo", "Segoe UI", Tahoma, sans-serif;

  /* 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: 17px;
  line-height: 1.75;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

html[dir="rtl"] body { font-family: var(--font-ar-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(--yellow); 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(--yellow); }

/* ⚠️ Blazor's <FocusOnNavigate Selector="h1"> moves focus to the page heading after an enhanced
   navigation, which is a real accessibility win — a screen-reader user is put at the top of the
   new page rather than left where the old one was. To do it, it gives the h1 tabindex="-1", and
   Chrome then matches :focus-visible on it and paints the yellow ring above around the title of
   every page. The client's approved design has no such ring.

   Suppressed only for a heading focused this way. A heading with tabindex="-1" is not something
   anyone can tab to, so there is no keyboard affordance being removed here; every real control
   keeps its indicator. Do not widen this rule. */
:is(h1, h2)[tabindex="-1"]:focus-visible { outline: none; }

.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-head);
  font-size: 13px; font-weight: 800;
  text-transform: uppercase; letter-spacing: .09em;
  color: var(--brand-deep);
  margin-block-end: 12px;
}
.eyebrow::before {
  content: ""; inline-size: 22px; block-size: 3px;
  background: var(--brand); 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(--yellow); font-weight: 700; }
.preview-bar a { color: var(--yellow); }

/* ---------------------------------------------------------------- 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 {
  inline-size: 42px; block-size: 42px; border-radius: 50%;
  background: var(--brand); 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-head); font-weight: 700; 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; }

.nav__panel {
  position: absolute; inset-block-start: calc(100% + 6px); inset-inline-start: 0;
  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; transform: translateY(-6px);
  transition: opacity .16s ease, transform .16s ease, visibility .16s;
}
.nav__item:hover .nav__panel,
.nav__item:focus-within .nav__panel {
  opacity: 1; visibility: visible; transform: translateY(0);
}
.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(7, 33, 27, .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; }

/* A grid whose children arrive one after another rather than as one block.
   The delay is a custom property the script sets per child, so the stagger is
   declared here and only the index comes from JavaScript — with scripting off
   --reveal-delay is simply unset and every child animates at 0s, which is the
   same as the plain .reveal above. */
[data-anim] .reveal-stagger > * {
  opacity: 0;
  transform: translateY(16px);
  transition:
    opacity .6s ease var(--reveal-delay, 0s),
    transform .6s cubic-bezier(.22, .61, .36, 1) var(--reveal-delay, 0s);
}
[data-anim] .reveal-stagger.is-in > * { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  [data-anim] .reveal { opacity: 1; transform: none; transition: none; }
  [data-anim] .reveal-stagger > *,
  [data-anim] .reveal-stagger.is-in > * { 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-head); font-weight: 700; 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; }

/* White on the logo green is 2.8:1 and fails. The fill is the deep tone. */
.btn--primary { background: var(--brand-dark); color: #fff; }
.btn--primary:hover { background: #084435; 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); }

.btn--onband { background: var(--yellow); color: #12211c; }
.btn--onband:hover { background: #ffe95c; color: #12211c; }

/* 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 */
/* Daisy sells fragrance; flat colour undersells it. 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 #073F32, 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(8, 22, 18, .36), rgba(12, 30, 24, .30));
}

/* Over a photograph the accent needs more headroom: pure #FADD21 is dropped
   for a pale lemon. The yellow keeps its job on buttons and flat surfaces. */
.band--photo .eyebrow { color: #fff3a8; }
.band--photo .eyebrow::before { background: #fff3a8; }

/* ------------------------------------------------------------------ hero */

.hero {
  background:
    radial-gradient(1100px 420px at 78% -10%, rgba(30, 175, 138, .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(--yellow); }
.hero--photo .eyebrow { color: var(--yellow); }
.hero--photo .eyebrow::before { background: var(--yellow); }
/* 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(6, 52, 42, .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(250, 221, 33, .16); color: var(--yellow); }

/* A card on a photographic band. These used to carry their colours inline and
   still held #A9C8BD, 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(6, 30, 24, .58);
  border-color: rgba(234, 245, 241, .22);
}
.band-card .card__title { color: #fff; }
.band-card .card__body { color: #eaf5f1; }

/* 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;
  /* 4/3 made the news grid far taller than its text needed. 16/9 is the
     shallowest ratio that still reads as a photograph rather than a strip.
     These are landscape scene photographs, so cover is correct here — nothing
     is cut that matters. */
  overflow: hidden; aspect-ratio: 16 / 9;
  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 #bfe6d9;
  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(7, 33, 27, .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 was still too tall in review — the grid read
     as columns of slabs and a phone showed barely one card. Square is the
     shortest box that still holds a bottle without the crop eating it.
     The image still COVERS the box. An earlier pass used contain, on the assumption
     that these were bottle shots that a square crop would decapitate. They are not:
     the catalogue photography is scene work — cut limes, blossom, spices — where a
     centre crop loses nothing and letterboxing just puts grey bars down both sides
     of every card. Checked against the approved preview before changing it back. */
  aspect-ratio: 1 / 1;
  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(--brand-wash), #d8efe7);
  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);
  /* Was 3/4 — a full-height slab beside a short specification table, which left the
     page bottom-heavy on a laptop. Square, and covering for the same reason as the
     catalogue card above. */
  border-radius: var(--radius); overflow: hidden; aspect-ratio: 1 / 1;
  position: sticky; inset-block-start: calc(var(--header-h) + 20px);
}
/* ⚠️ On a phone the image covered the product's name (owner, 2026-09-15). Measured at 390px: the figure was drawn
   82px below its own grid row — exactly calc(var(--header-h) + 20px). The sticky offset above stays in force, and the
   unconditional "position: relative" below turns it into a plain downward shift, drawn over whatever follows. So the
   offset is cancelled here, where the layout is one column, and the figure gets room of its own beneath it. The
   "position: static" this rule used to set never applied — the relative rule after it always won — and static would
   also have let the absolutely positioned image escape the box. */
@media (max-width: 900px) { .detail__fig { inset-block-start: auto; margin-block-end: 10px; } }
.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); }

/* The olfactive-family pills in the specification table sat edge to edge: .tag has no spacing of its own, and only
   the product card's .pcard__tags gives it a gap (owner, 2026-09-15). Inline-block so a margin applies, and a margin
   on the inline end so it mirrors on an Arabic page. */
.spec td .tag { display: inline-block; margin-block: 3px; margin-inline-end: 6px; }

/* ------------------------------------------------------- technical documents */
/* DocumentTable.razor — ADR-0037. A table on wider screens; below 760px a swipeable row of cards, each with its
   Download button underneath (owner, 2026-09-15). Plain CSS scroll-snap: no script, nothing for the CSP to allow,
   and it still works when scripting is off. The next card peeks in at the edge, which is what says "swipe". */
.doc-rail { display: none; }
.doc-rail__meta { margin: 0; color: var(--ink-3); font-size: 14.5px; }

@media (max-width: 760px) {
  .doc-table { display: none; }

  .doc-rail {
    display: flex; gap: 14px; margin: 0; padding: 2px 0 12px; list-style: none;
    overflow-x: auto; scroll-snap-type: x mandatory; overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
  }
  .doc-rail > li { flex: 0 0 84%; scroll-snap-align: start; display: flex; }
  .doc-rail > li:only-child { flex-basis: 100%; }
  .doc-rail .card { display: flex; flex-direction: column; gap: 8px; inline-size: 100%; }
  .doc-rail .card__title { overflow-wrap: anywhere; }
  .doc-rail .btn { margin-block-start: auto; }
}

.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; }

/* --------------------------------------------------------- scent pyramid */
/* The live site stacks three full-width bands, one per tier, fading in a
   second apart. Same three tiers, drawn as the shape the trade actually means:
   top notes are what you meet first and hold the narrowest band, base notes
   are what is still there an hour later and hold the widest. */

.pyr { margin-block-start: 34px; }
.pyr__h {
  font-size: 15px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .08em;
  color: var(--ink-3); margin-block-end: 14px;
}
html[dir="rtl"] .pyr__h { text-transform: none; letter-spacing: normal; font-size: 16.5px; }

.pyr__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }

.pyr__tier {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px;
  margin-inline: auto;
  padding: 14px 20px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--bg-soft);
}
/* The widths are the pyramid. */
.pyr__tier--1 { inline-size: 74%; background: #f2faf7; }
.pyr__tier--2 { inline-size: 87%; background: #eaf6f1; }
.pyr__tier--3 { inline-size: 100%; background: var(--brand-wash); }
@media (max-width: 620px) {
  .pyr__tier--1, .pyr__tier--2, .pyr__tier--3 { inline-size: 100%; }
}

.pyr__label {
  font-family: var(--font-head); font-weight: 700;
  font-size: 12.5px; text-transform: uppercase; letter-spacing: .07em;
  color: var(--brand-dark); flex: none; min-inline-size: 92px;
}
html[dir="rtl"] .pyr__label {
  font-family: var(--font-ar-head); text-transform: none;
  letter-spacing: normal; font-size: 14px;
}
.pyr__notes { display: flex; flex-wrap: wrap; gap: 6px; }
.pyr__note {
  font-size: 14.5px; padding: 3px 11px; border-radius: 999px;
  background: var(--bg); border: 1px solid var(--line); color: var(--ink);
}
.pyr__note-text { margin-block-start: 12px; font-size: 14px; color: var(--ink-3); }

/* ----------------------------------------------------------------- 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; }
.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); }
.band .eyebrow { color: var(--yellow); }
.band .eyebrow::before { background: var(--yellow); }

/* The closing band carries the motto and a way to get in touch over one photograph (the newsletter
   it carried until 2026-09-22 was never real — ClosingBand.razor).
   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(234, 245, 241, .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(--yellow);
  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(234, 245, 241, .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(--yellow); 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(--yellow); }
.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 #A9C8BD on #073F32 — 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(--yellow); 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(--yellow); }
.footer__bar {
  margin-block-start: 44px; border-block-start: 1px solid rgba(234, 245, 241, .16);
  padding-block: 20px;
  display: flex; flex-wrap: wrap; gap: 10px 20px; justify-content: space-between;
  font-size: 14.5px;
}

/* ========================================================================== 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; }
}

/* ================================================================== reference picker
   The contact form's searchable "Reference" list, built by site.js from a plain <select
   data-refpick>. It borrows the form field's own measure — border, radius, the 16.5px text — so it
   reads as the same control as the selects beside it, and the catalogue plate's gradient for a
   product with no picture. 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: 300px; 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; }
.refpick__option.is-active { background: var(--brand-wash); }
.refpick__option[aria-selected="true"] .refpick__name { color: var(--brand-dark); font-weight: 700; }

.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(--brand-wash), #d8efe7);
  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); }

.refpick__empty { margin: 0; padding: 10px 8px; font-size: 15px; color: var(--ink-3); }
.refpick__empty[hidden] { display: none; }

/* Several references 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); }

/* The reCAPTCHA v2 checkbox, when the invisible check asks for it. */
#enquiry-captcha:not([hidden]) { min-block-size: 78px; }

/* Picked references, unmistakably: a checkbox that fills with the brand colour and a tinted row.
   The keyboard/hover highlight is a separate, quieter outline, so "picked" and "under the cursor"
   never look alike. Placed after the earlier .refpick rules so these win at equal specificity. */
.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"].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;
}

/* The chosen names stay on one line and truncate, whatever is picked. */
.refpick__button .refpick__text { flex: 1 1 auto; }
.refpick__code { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
