
/* ==========================================================================
   Ariana Precious Stones — Phase 2 components
   Capability, provenance chain, offices map, Studio tools, rarity matrix,
   trade shows, language switcher, capability sheet.
   Loads after style.css and depends on its custom properties.
   ========================================================================== */

/* --------------------------------------------------------------------------
   0. Light-surface token overrides
   The site is dark throughout. The capability sheet is the one exception —
   it is a document, sized to A4 and meant to leave the screen on paper, so
   it stays on white. The dark-theme greys and golds do not carry enough
   contrast there. Redefining the tokens fixes every consumer at once, which
   per-class overrides could not: anything reading var(--muted) directly (the
   availability matrix, the breadcrumbs) was missed by those.
   -------------------------------------------------------------------------- */

.sheet {
  --muted: #55605b;
  --muted-dark: #66716c;
  --gold: var(--gold-ink);
  --gold-light: var(--gold-deep);
  --rule: rgba(122, 98, 48, 0.38);
  --rule-soft: rgba(10, 15, 13, 0.14);
}

/* --------------------------------------------------------------------------
   1. Stone rendering refinements
   -------------------------------------------------------------------------- */

/* Jardin is an emerald trait. Tourmaline reuses the same cut symbols and
   must render clean, so the texture is opt-in per stone. */
[data-species="emerald"],
.is-emerald {
  --jardin: 0.34;
}

/* Caustic — the pool of colour a lit stone throws onto its plinth */
.gem-stage::before,
.frame__inner::before {
  content: "";
  position: absolute;
  left: 50%;
  bottom: 12%;
  width: 62%;
  height: 16%;
  translate: -50% 0;
  background: radial-gradient(
    ellipse at center,
    color-mix(in srgb, var(--gem, var(--emerald)) 60%, transparent) 0%,
    transparent 70%
  );
  filter: blur(10px);
  opacity: 0.7;
  pointer-events: none;
}

.frame__inner {
  position: relative;
}

/* Image slot — drop real photography in without touching layout.
   Same 4:3 box as .gem-stage so cards stay aligned during the swap. */
.stone-photo {
  position: relative;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: linear-gradient(160deg, var(--ink-700), var(--ink-900));
}

.stone-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--dur-slow) var(--ease-out);
}

.gem-card:hover .stone-photo img {
  transform: scale(1.05);
}

/* --------------------------------------------------------------------------
   2. Capability band
   -------------------------------------------------------------------------- */

.capability {
  display: grid;
  gap: 1px;
  background: var(--rule-soft);
  border: 1px solid var(--rule-soft);
}

@media (min-width: 46rem) {
  .capability { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 68rem) {
  .capability { grid-template-columns: repeat(4, 1fr); }
}

.capability__item {
  background: var(--surface);
  padding: clamp(1.5rem, 3.5vw, 2.25rem);
  display: grid;
  gap: 0.75rem;
  align-content: start;
  transition: background var(--dur) var(--ease-out);
}

.capability__item:hover { background: var(--surface-hi); }

.capability__word {
  font-family: var(--font-display);
  font-size: var(--step-3);
  line-height: 1;
  color: var(--gold-light);
}

.capability__item h3 {
  font-family: var(--font-body);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--muted);
}

.capability__item p {
  font-size: var(--step--1);
  color: var(--muted);
  line-height: 1.6;
}

.capability__item ul {
  display: grid;
  gap: 0.35rem;
  font-size: var(--step--2);
  color: var(--muted);
  letter-spacing: 0.06em;
}

.capability__item li {
  display: flex;
  gap: 0.6em;
  align-items: baseline;
}

.capability__item li::before {
  content: "";
  width: 4px;
  height: 4px;
  flex-shrink: 0;
  transform: rotate(45deg);
  background: var(--gold);
}

/* --------------------------------------------------------------------------
   3. Provenance chain diagram
   -------------------------------------------------------------------------- */

.chain { display: grid; gap: var(--space-xl); }
.chain__lane { display: grid; gap: var(--space-m); }

.chain__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
}

.chain__head h3 { font-size: var(--step-1); }

.chain__tally {
  font-size: var(--step--2);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--muted);
}

.chain__track {
  display: flex;
  align-items: stretch;
  overflow-x: auto;
  padding-bottom: 0.5rem;
  scrollbar-width: thin;
  position: relative;
}

.chain__node {
  flex: 1 0 auto;
  min-width: 108px;
  display: grid;
  justify-items: center;
  gap: 0.55rem;
  text-align: center;
  position: relative;
  padding-inline: 0.35rem;
}

.chain__node::before {
  content: "";
  width: 100%;
  height: 1px;
  position: absolute;
  top: 13px;
  left: -50%;
  background: var(--rule-soft);
  z-index: 0;
}

.chain__node:first-child::before { display: none; }

.chain__dot {
  width: 26px;
  height: 26px;
  display: grid;
  place-items: center;
  position: relative;
  z-index: 1;
}

.chain__dot i {
  width: 10px;
  height: 10px;
  transform: rotate(45deg);
  background: var(--muted-dark);
  display: block;
}

.chain__label {
  font-size: var(--step--2);
  line-height: 1.35;
  color: var(--muted);
  letter-spacing: 0.04em;
}

.chain__margin {
  font-size: var(--step--3);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #c07a5e;
}

.chain__lane--ours .chain__dot i {
  background: var(--gold);
  box-shadow: 0 0 0 4px rgba(194, 161, 95, 0.16);
}

.chain__lane--ours .chain__node::before { background: var(--rule); }
.chain__lane--ours .chain__label { color: var(--bone-100); }

.chain__pulse {
  position: absolute;
  top: 12px;
  left: 0;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--gold-light);
  box-shadow: 0 0 12px 3px rgba(227, 205, 154, 0.6);
  animation: chainRun 3.4s var(--ease-in-out) infinite;
  pointer-events: none;
  z-index: 2;
}

@keyframes chainRun {
  0%   { left: 8%;  opacity: 0; }
  12%  { opacity: 1; }
  88%  { opacity: 1; }
  100% { left: 88%; opacity: 0; }
}

/* --------------------------------------------------------------------------
   4. Offices & world map
   -------------------------------------------------------------------------- */

.worldmap { position: relative; width: 100%; }

.worldmap svg { width: 100%; height: auto; display: block; }

/* The dots are dashes: the path is one straight run per row of land, and a
   round-capped stroke of width 2R with a (nearly) zero dash every cell puts
   one dot at every cell. See build-worldmap.mjs. R = 2.7, cell = 10. */
.worldmap__dot {
  fill: none;
  stroke: rgba(247, 244, 237, 0.19);
  stroke-width: 5.4;
  stroke-linecap: round;
  stroke-dasharray: 0.01 9.99;
}

.office-pin { cursor: default; }

/* A hairline ring with a small solid centre, plus an expanding "ping".
   The previous filled halo rendered as a muddy brown disc over the map;
   a stroked ring stays crisp at any size and keeps the marker legible. */
.office-pin__ring {
  fill: none;
  stroke: var(--gold);
  stroke-width: 1;
  stroke-opacity: 0.55;
  transition: stroke-opacity var(--dur) var(--ease-out);
}

.office-pin__ping {
  fill: none;
  stroke: var(--gold);
  stroke-width: 1;
  opacity: 0;
  animation: pinPing 4.5s var(--ease-out) infinite;
  animation-delay: var(--delay, 0s);
}

@keyframes pinPing {
  0%        { transform: scale(0.7); opacity: 0; }
  12%       { opacity: 0.5; }
  60%, 100% { transform: scale(2.6); opacity: 0; }
}

.office-pin__dot {
  fill: var(--gold-light);
  transition: fill var(--dur) var(--ease-out);
}

.office-pin__label {
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 500;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  fill: var(--bone-200);
  pointer-events: none;
  transition: fill var(--dur) var(--ease-out);
  /* Knock the label out of the dot field behind it: the stroke is painted
     first, in the page colour, so the type stays crisp over the texture. */
  paint-order: stroke fill;
  stroke: var(--ink-900);
  stroke-width: 3px;
  stroke-linejoin: round;
}

.office-pin:hover .office-pin__ring,
.office-pin.is-active .office-pin__ring { stroke-opacity: 1; }

.office-pin:hover .office-pin__dot,
.office-pin.is-active .office-pin__dot { fill: #fff; }

.office-pin:hover .office-pin__label,
.office-pin.is-active .office-pin__label { fill: var(--bone-100); }

/* The map is 2000 user units wide and scales to whatever it is given, so a
   label written in user units renders at container/2000 of its nominal size:
   12 units is about 7px on a desktop and 2px on a phone.
   Below the width where the office cards stop sitting side by side there is
   no size that both fits between the pins and can be read — Amsterdam and
   Antwerp are 150km apart and would overprint long before it was legible.
   The labels come off there and the cards underneath carry the names, in the
   same order, which is where a reader on a phone is looking anyway. The map
   keeps its <title>, so nothing is lost to a screen reader. */
@media (max-width: 51.99rem) {
  .office-pin__label,
  .bench-pin__label {
    display: none;
  }

  /* Same arithmetic sinks the markers: a 10-unit ring is under 2px once the
     map is 350px wide, which is not a mark, it is a speck. Each pin is scaled
     about its own centre so it stays on its city. fill-box measures only the
     circles now that the labels are gone. */
  .office-pin,
  .bench-pin {
    transform: scale(2.4);
    transform-box: fill-box;
    transform-origin: center;
  }
}

.offices {
  display: grid;
  gap: 1px;
  background: var(--rule-soft);
  border: 1px solid var(--rule-soft);
}

/* Three offices, so the grid goes straight from one column to three. A
   two-column stage would always orphan the third card, and the old
   repeat(5, 1fr) — sized for six desks — would now leave two columns empty
   and squeeze three cards into a fifth of the width each. */
@media (min-width: 52rem) {
  .offices { grid-template-columns: repeat(3, 1fr); }
}

.office {
  background: var(--surface);
  padding: clamp(1.1rem, 2.6vw, 1.6rem);
  display: grid;
  gap: 0.5rem;
  align-content: start;
  text-align: left;
  width: 100%;
  transition: background var(--dur) var(--ease-out);
  cursor: pointer;
  font: inherit;
  color: inherit;
}

.office:hover,
.office.is-active { background: var(--surface-hi); }

.office.is-active { box-shadow: inset 0 2px 0 var(--gold); }

.office__city {
  font-family: var(--font-display);
  font-size: var(--step-2);
  line-height: 1.1;
}

.office__role {
  font-size: var(--step--2);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--gold);
}

.office__time {
  font-variant-numeric: tabular-nums;
  font-size: var(--step--1);
  color: var(--muted);
  display: flex;
  align-items: center;
  gap: 0.5em;
}

.office__time::before {
  content: "";
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--emerald-bright);
  flex-shrink: 0;
}

.office__time[data-open="false"]::before { background: var(--muted-dark); }

.office__note {
  font-size: var(--step--2);
  /* --muted, not --muted-dark: an active card lightens to --ink-600 and
     the darker grey drops to 4.38:1 against it. */
  color: var(--muted);
  line-height: 1.5;
}

/* --------------------------------------------------------------------------
   5. Studio — shared tool chrome
   -------------------------------------------------------------------------- */

.tool {
  border: 1px solid var(--rule-soft);
  background: linear-gradient(180deg, rgba(23, 33, 29, 0.5), rgba(10, 15, 13, 0.2));
  overflow: hidden;
}

.tool__head {
  padding: clamp(1.25rem, 3vw, 2rem);
  border-bottom: 1px solid var(--rule-soft);
  display: grid;
  gap: 0.6rem;
}

.tool__head h2, .tool__head h3 { font-size: var(--step-2); }

.tool__head p {
  font-size: var(--step--1);
  color: var(--muted);
  max-width: 64ch;
}

.tool__body { padding: clamp(1.25rem, 3vw, 2rem); }

.tool__split { display: grid; gap: clamp(1.5rem, 4vw, 2.5rem); }

@media (min-width: 58rem) {
  .tool__split {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    align-items: start;
  }
}

.control { display: grid; gap: 0.6rem; margin-bottom: var(--space-m); }

.control__label {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  font-size: 0.72rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--muted);
}

.control__value {
  font-family: var(--font-display);
  font-size: var(--step-1);
  letter-spacing: 0;
  text-transform: none;
  color: var(--gold-light);
  font-variant-numeric: tabular-nums;
}

input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 26px;
  background: transparent;
  cursor: pointer;
}

input[type="range"]::-webkit-slider-runnable-track {
  height: 2px;
  background: var(--rule);
  border-radius: 2px;
}

input[type="range"]::-moz-range-track {
  height: 2px;
  background: var(--rule);
  border-radius: 2px;
}

input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 16px;
  height: 16px;
  margin-top: -7px;
  border-radius: 50%;
  background: var(--gold-light);
  border: 1px solid var(--gold-deep);
  box-shadow: 0 0 0 0 rgba(194, 161, 95, 0.3);
  transition: box-shadow var(--dur-fast) var(--ease-out);
}

input[type="range"]::-moz-range-thumb {
  width: 15px;
  height: 15px;
  border-radius: 50%;
  background: var(--gold-light);
  border: 1px solid var(--gold-deep);
}

input[type="range"]:hover::-webkit-slider-thumb,
input[type="range"]:focus-visible::-webkit-slider-thumb {
  box-shadow: 0 0 0 7px rgba(194, 161, 95, 0.18);
}

.segmented { display: flex; flex-wrap: wrap; gap: 0.4rem; }

.segmented button {
  padding: 0.6em 1em;
  border: 1px solid var(--rule-soft);
  font-size: var(--step--2);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  border-radius: 2px;
  transition: color var(--dur-fast) var(--ease-out),
    border-color var(--dur-fast) var(--ease-out),
    background var(--dur-fast) var(--ease-out);
  white-space: nowrap;
}

.segmented button:hover { color: var(--bone-100); border-color: var(--rule); }

.segmented button[aria-pressed="true"] {
  background: var(--gold);
  border-color: var(--gold);
  color: var(--ink-900);
  font-weight: 500;
}

/* --------------------------------------------------------------------------
   6. Tool 1 — carat size visualiser
   -------------------------------------------------------------------------- */

.sizer__stage {
  position: relative;
  display: grid;
  place-items: center;
  min-height: 350px;
  padding: var(--space-l);
  background:
    radial-gradient(60% 60% at 50% 46%,
      color-mix(in srgb, var(--gem, var(--emerald)) 20%, transparent) 0%,
      transparent 72%),
    var(--ink-900);
  border: 1px solid var(--rule-soft);
  overflow: hidden;
}

/* 10 mm grid, so the true-scale claim is legible */
.sizer__grid {
  position: absolute;
  inset: 0;
  opacity: 0.5;
  pointer-events: none;
  background-image:
    linear-gradient(to right, var(--rule-soft) 1px, transparent 1px),
    linear-gradient(to bottom, var(--rule-soft) 1px, transparent 1px);
  background-size: var(--mm10, 37.8px) var(--mm10, 37.8px);
}

.sizer__gem {
  position: relative;
  z-index: 1;
  display: block;
  filter: drop-shadow(0 10px 26px color-mix(in srgb, var(--gem, var(--emerald)) 50%, transparent));
}

.sizer__scalebar {
  position: absolute;
  left: 50%;
  bottom: 16px;
  translate: -50% 0;
  z-index: 2;
  display: grid;
  justify-items: center;
  gap: 0.35rem;
  font-size: var(--step--3);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--muted);
}

.sizer__scalebar i {
  display: block;
  height: 6px;
  border-left: 1px solid var(--gold);
  border-right: 1px solid var(--gold);
  border-bottom: 1px solid var(--gold);
  width: var(--mm10, 37.8px);
}

.sizer__readout {
  display: grid;
  gap: 0;
  border-top: 1px solid var(--rule-soft);
  margin-top: var(--space-m);
}

.sizer__readout > div {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1.5rem;
  padding-block: 0.7rem;
  border-bottom: 1px solid var(--rule-soft);
}

.sizer__readout dt {
  font-size: var(--step--2);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}

.sizer__readout dd {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--step-1);
  color: var(--bone-100);
  font-variant-numeric: tabular-nums;
}

.calib {
  margin-top: var(--space-m);
  padding: var(--space-m);
  border: 1px dashed var(--rule);
  display: grid;
  gap: var(--space-s);
}

.calib summary {
  cursor: pointer;
  font-size: var(--step--2);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--gold);
  list-style: none;
}

.calib summary::-webkit-details-marker { display: none; }
.calib summary::before { content: "+ "; }
.calib[open] summary::before { content: "\2212 "; }

.calib__card {
  height: 54px;
  width: var(--cardw, 323px);
  max-width: 100%;
  border: 1px solid var(--gold);
  border-radius: 6px;
  background: linear-gradient(120deg, rgba(194, 161, 95, 0.14), transparent);
  display: grid;
  place-items: center;
  font-size: var(--step--2);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--gold-light);
  text-align: center;
  padding-inline: 0.5rem;
}

/* --------------------------------------------------------------------------
   7. Tool 2 — colour explorer
   -------------------------------------------------------------------------- */

/* Grid rather than flex-wrap: a lone item on the last flex line would
   stretch to full width, and aspect-ratio:1 then made it enormous. */
/* auto-FILL, not auto-fit. With auto-fit the empty tracks collapse, so a
   species that comes in one colour — emerald, ruby — stretched its single
   swatch across the whole strip and came out as one enormous rectangle.
   auto-fill keeps the tracks, so one swatch is swatch-sized. */
.spectrum {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(66px, 1fr));
  gap: 0.4rem;
}

.spectrum__swatch {
  aspect-ratio: 1;
  width: 100%;
  border: 1px solid transparent;
  border-radius: 2px;
  background: linear-gradient(155deg,
    color-mix(in srgb, var(--sw) 78%, #fff) 0%,
    var(--sw) 46%,
    color-mix(in srgb, var(--sw) 64%, #000) 100%);
  position: relative;
  overflow: hidden;
  transition: transform var(--dur) var(--ease-out),
    box-shadow var(--dur) var(--ease-out);
}

.spectrum__swatch:hover { transform: translateY(-4px); }

.spectrum__swatch[aria-pressed="true"] {
  box-shadow: 0 0 0 2px var(--gold), 0 10px 26px rgba(0, 0, 0, 0.4);
  transform: translateY(-4px);
}

.spectrum__swatch span {
  position: absolute;
  inset: auto 0 0 0;
  padding: 0.3rem 0.25rem;
  font-size: 0.5rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-align: center;
  color: #fff;
  background: linear-gradient(0deg, rgba(0, 0, 0, 0.68), transparent);
  line-height: 1.2;
}

.hue-detail { display: grid; gap: var(--space-s); align-content: start; }
.hue-detail h3 { font-size: var(--step-2); }

.rarity-meter { display: flex; gap: 3px; align-items: center; }

.rarity-meter i {
  width: 20px;
  height: 4px;
  background: var(--rule-soft);
  display: block;
}

.rarity-meter i.on { background: var(--gold); }

/* --------------------------------------------------------------------------
   8. Tool 3 — cut comparator
   -------------------------------------------------------------------------- */

.cuts {
  display: grid;
  gap: var(--space-s);
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (min-width: 46rem) {
  .cuts { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

.cut-item {
  display: grid;
  gap: 0.5rem;
  padding: var(--space-s);
  border: 1px solid var(--rule-soft);
  text-align: center;
  justify-items: center;
  transition: border-color var(--dur) var(--ease-out),
    background var(--dur) var(--ease-out);
  cursor: pointer;
  width: 100%;
  font: inherit;
  color: inherit;
}

.cut-item:hover,
.cut-item[aria-pressed="true"] {
  border-color: var(--gold);
  background: rgba(194, 161, 95, 0.07);
}

.cut-item .gem { width: 66px; }

.cut-item strong {
  font-family: var(--font-display);
  font-size: var(--step-0);
  font-weight: 400;
}

.cut-item span {
  font-size: var(--step--3);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  line-height: 1.4;
}

/* --------------------------------------------------------------------------
   9. Tool 4 — specification builder
   -------------------------------------------------------------------------- */

.spec-summary {
  border: 1px solid var(--rule);
  background: rgba(5, 8, 7, 0.45);
  padding: clamp(1.25rem, 3vw, 1.75rem);
  display: grid;
  gap: var(--space-s);
  align-content: start;
}

@media (min-width: 58rem) {
  .spec-summary {
    position: sticky;
    top: calc(var(--header-h) + 1rem);
  }
}

.spec-summary h3 { font-size: var(--step-1); }

.spec-summary dl {
  display: grid;
  gap: 0;
  border-top: 1px solid var(--rule-soft);
}

.spec-summary dl > div {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding-block: 0.6rem;
  border-bottom: 1px solid var(--rule-soft);
  font-size: var(--step--1);
}

.spec-summary dt {
  font-size: var(--step--2);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}

.spec-summary dd { margin: 0; text-align: right; color: var(--bone-100); }

/* --------------------------------------------------------------------------
   10. Rarity & availability matrix
   -------------------------------------------------------------------------- */

.matrix-scroll { overflow-x: auto; padding-bottom: 0.5rem; }

.matrix {
  border-collapse: separate;
  border-spacing: 3px;
  width: 100%;
  min-width: 640px;
}

.matrix caption {
  text-align: left;
  font-size: var(--step--2);
  color: var(--muted);
  padding-bottom: var(--space-s);
}

.matrix th {
  font-family: var(--font-body);
  font-size: var(--step--3);
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
  padding: 0.5rem 0.4rem;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

.matrix th[scope="row"] {
  text-align: left;
  white-space: nowrap;
  padding-right: 0.9rem;
  color: var(--bone-200);
  font-size: var(--step--2);
  letter-spacing: 0.1em;
}

.matrix th[scope="row"] i {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--sw, var(--emerald));
  margin-right: 0.55em;
}

.matrix td {
  padding: 0;
  height: 44px;
  border-radius: 2px;
  text-align: center;
  vertical-align: middle;
  font-size: var(--step--3);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  background: color-mix(in srgb, var(--sw, var(--emerald)) calc(var(--lvl, 0) * 18%), transparent);
  border: 1px solid var(--rule-soft);
  color: var(--bone-100);
  transition: transform var(--dur-fast) var(--ease-out),
    border-color var(--dur-fast) var(--ease-out);
}

.matrix td:hover { transform: scale(1.05); border-color: var(--gold); }
.matrix td[data-lvl="0"] { color: var(--muted-dark); }

.matrix-key {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-s) var(--space-m);
  margin-top: var(--space-m);
  font-size: var(--step--2);
  color: var(--muted);
  letter-spacing: 0.06em;
}

.matrix-key span { display: flex; align-items: center; gap: 0.5em; }

.matrix-key i {
  width: 20px;
  height: 11px;
  border: 1px solid var(--rule-soft);
  background: color-mix(in srgb, var(--gold) calc(var(--lvl, 0) * 18%), transparent);
  display: block;
}

/* --------------------------------------------------------------------------
   11. Trade shows
   -------------------------------------------------------------------------- */

.shows { display: grid; gap: 0; border-top: 1px solid var(--rule-soft); }

.show {
  display: grid;
  gap: 0.5rem 1.5rem;
  grid-template-columns: 1fr;
  padding-block: clamp(1.1rem, 3vw, 1.6rem);
  border-bottom: 1px solid var(--rule-soft);
  align-items: baseline;
}

@media (min-width: 48rem) {
  .show { grid-template-columns: 12ch minmax(0, 1fr) auto; }
}

.show__when {
  font-size: var(--step--2);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--gold);
}

.show__what { display: grid; gap: 0.3rem; }

.show__what strong {
  font-family: var(--font-display);
  font-size: var(--step-1);
  font-weight: 400;
}

.show__what span { font-size: var(--step--1); color: var(--muted); }

.show__status {
  font-size: var(--step--3);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 0.4em 0.85em;
  border: 1px solid var(--rule);
  color: var(--gold-light);
  white-space: nowrap;
  justify-self: start;
}

.show__status--quiet {
  color: var(--muted);
  border-color: var(--rule-soft);
}

/* --------------------------------------------------------------------------
   12. Language switcher + script support
   -------------------------------------------------------------------------- */

.langsel { display: none; }

@media (min-width: 54rem) {
  .langsel { display: block; }
}

.langsel select {
  appearance: none;
  background-color: transparent;
  border: 1px solid var(--rule-soft);
  border-radius: 2px;
  color: var(--bone-200);
  font-size: var(--step--3);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 0.62em 2.1em 0.62em 0.9em;
  cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' fill='none' stroke='%23c2a15f' stroke-width='1.5'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.7rem center;
  background-size: 10px;
  transition: border-color var(--dur-fast) var(--ease-out);
}

.langsel select:hover { border-color: var(--rule); }

/* --------------------------------------------------------------------------
   Language picker with flags

   Drawn over the native <select>, which stays in the DOM and keeps working
   without JavaScript and on touch, where the OS picker is the better
   control. Styled to match the select it replaces, so the header does not
   change shape when the script runs.
   -------------------------------------------------------------------------- */

.langpick { position: relative; }

.langpick__btn {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  width: 100%;
  background: transparent;
  border: 1px solid var(--rule-soft);
  border-radius: 2px;
  color: var(--bone-200);
  font: inherit;
  font-size: var(--step--3);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 0.62em 0.9em;
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease-out);
}

.langpick__btn:hover { border-color: var(--rule); }
.langpick.is-open .langpick__btn { border-color: var(--gold-deep); }

.langpick__caret {
  margin-inline-start: auto;
  width: 9px;
  height: 6px;
  flex: none;
  background: var(--gold);
  /* A drawn caret rather than a background image, so it can be rotated when
     the list opens and inherits the gold without a second asset. */
  clip-path: polygon(0 0, 100% 0, 50% 100%);
  transition: rotate var(--dur-fast) var(--ease-out);
}

.langpick.is-open .langpick__caret { rotate: 180deg; }

/* The flag itself. A hairline border stops the white-heavy flags — Japan,
   Israel — dissolving into a pale background, and keeps every flag the same
   visual weight in the column. */
.flag {
  width: 20px;
  height: 13.34px;
  flex: none;
  border: 1px solid rgba(255, 255, 255, 0.22);
  border-radius: 1px;
  display: block;
}

.langpick__list {
  position: absolute;
  z-index: 120;
  top: calc(100% + 6px);
  inset-inline-end: 0;
  min-width: max(100%, 15rem);
  max-height: min(60vh, 26rem);
  overflow-y: auto;
  overscroll-behavior: contain;
  margin: 0;
  padding: 0.3rem;
  list-style: none;
  background: #0d1512;
  border: 1px solid var(--rule);
  border-radius: 2px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.55);
  opacity: 0;
  visibility: hidden;
  translate: 0 -6px;
  transition: opacity var(--dur-fast) var(--ease-out),
    translate var(--dur-fast) var(--ease-out), visibility var(--dur-fast);
}

.langpick.is-open .langpick__list {
  opacity: 1;
  visibility: visible;
  translate: 0 0;
}

.langpick__opt {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.5rem 0.6rem;
  border-radius: 2px;
  cursor: pointer;
  /* The endonyms are set in their own scripts, so this row must not inherit
     the uppercasing and wide tracking of the Latin chrome around it. */
  font-family: var(--font-body);
  font-size: 0.78rem;
  letter-spacing: 0;
  text-transform: none;
  color: var(--bone-200);
  white-space: nowrap;
}

.langpick__opt:hover,
.langpick__opt.is-active {
  background: rgba(194, 161, 95, 0.12);
  color: var(--bone-100);
}

.langpick__opt[aria-selected="true"] { color: var(--gold); }

.langpick__list:focus-visible { outline: 2px solid var(--gold-deep); outline-offset: 2px; }

/* In the drawer the list has room to sit inline rather than float. */
.drawer__lang .langpick__list {
  inset-inline: 0;
  min-width: 0;
}

.langsel select option { background: #101815; color: #f7f4ed; }

.drawer__lang select {
  width: 100%;
  padding: 0.8em 1em;
  background: var(--ink-700);
  border: 1px solid var(--rule-soft);
  color: var(--bone-100);
  border-radius: 2px;
  font-size: var(--step--1);
  appearance: none;
}

/* Right-to-left support: Arabic, Dari, Pashto */
[dir="rtl"] .rule-label--start { flex-direction: row-reverse; }
[dir="rtl"] .rule-label--start::after { background: linear-gradient(90deg, transparent, var(--gold)); }

[dir="rtl"] .specs dd,
[dir="rtl"] .spec-summary dd,
[dir="rtl"] .sizer__readout dd { text-align: left; }

[dir="rtl"] .link svg,
[dir="rtl"] .btn svg { transform: scaleX(-1); }
[dir="rtl"] .link:hover svg { transform: scaleX(-1) translateX(4px); }

[dir="rtl"] .office.is-active { box-shadow: inset 0 2px 0 var(--gold); }

/* Non-Latin scripts.
   The display serif is NOT swapped out wholesale. Cormorant simply has no
   Arabic/CJK/Thai/Devanagari glyphs, so the browser already falls back
   per-character through the font stack — and a blanket
   `[lang="ar"] h1 { font-family: … }` on <html> would strip the serif from
   the English headings too, since some copy stays English until a language
   reaches 100%.

   What genuinely does need resetting is the wide Latin letterspacing and
   uppercasing, which are wrong for these scripts. Those are scoped with
   :not([lang="en"]) so they only touch actually-translated elements —
   untranslated blocks are explicitly marked lang="en" by the switcher.

   :is() keeps this to one list. Adding a language used to mean editing
   forty selectors and forgetting one. */

:is([lang="he"], [lang="ar"], [lang="fa-AF"], [lang="ps"], [lang="ur"],
    [lang="zh-Hant"], [lang="zh-Hans"], [lang="ja"], [lang="th"], [lang="hi"])
  :is(.eyebrow, .rule-label, .btn, .nav a, .drawer__nav a):not([lang="en"]) {
  letter-spacing: 0.06em;
  text-transform: none;
}

/* Thai stacks tone marks above and vowel marks below the line; the default
   leading collides them with the neighbouring rows. */
[lang="th"] [data-i18n]:not([lang="en"]) {
  line-height: 1.9;
}

/* Kinsoku shori. Chrome's default line-break lets a line begin on a small
   kana, so "キャリブレーション" was breaking between キ and ャ — the Japanese
   equivalent of starting a line with a lone diacritic. `strict` also keeps
   the CJK closing brackets and the long-vowel mark off the start of a line,
   which the same headings hit.

   Only line-break, deliberately. Pairing it with `overflow-wrap: normal`
   looked tidier and cost six pages a horizontal scrollbar at 360px: the
   Latin runs these pages still carry — info@arianapreciousstones.com,
   "B.V." — have no break opportunity inside them, so they need the
   inherited wrapping left alone. */
:is([lang="ja"], [lang="zh-Hant"], [lang="zh-Hans"]) :not([lang="en"]) {
  line-break: strict;
}

/* Urdu is set in Nastaliq, which cascades steeply from right to left and
   needs far more vertical room than Naskh. If no Nastaliq face is installed
   the Arabic stack below it renders perfectly readable Naskh instead, so the
   extra leading is the only thing that would look odd — hence it is scoped to
   translated elements only. */
[lang="ur"] [data-i18n]:not([lang="en"]) {
  font-family: "Noto Nastaliq Urdu", "Jameel Noori Nastaleeq", "Urdu Typesetting",
               "Segoe UI", "Noto Naskh Arabic", serif;
  line-height: 2.1;
}

/* The 2.1 above is right for a paragraph at 1rem and absurd on a 4rem heading,
   where it opens a gap the width of a whole line between the two halves of a
   title. Nastaliq still needs more room than Latin at display sizes — the
   cascade runs below the baseline — but it scales with the type, not with the
   ratio. Single-line chrome (buttons, nav) gets less again. */
[lang="ur"] :is(h1, h2, h3, .card__title, .stat__value):not([lang="en"]) {
  line-height: 1.55;
}

[lang="ur"] :is(.btn, .nav a, .drawer__nav a, .eyebrow, .rule-label,
                .chip, .office__city):not([lang="en"]) {
  line-height: 1.4;
}

/* Devanagari and the Arabic-script languages sit low against a Latin
   baseline at display sizes; a touch more leading stops headings touching. */
:is([lang="hi"], [lang="ar"], [lang="fa-AF"], [lang="ps"], [lang="he"])
  :is(h1, h2):not([lang="en"]) {
  line-height: 1.35;
}

/* --------------------------------------------------------------------------
   13. Capability sheet (screen + print)
   -------------------------------------------------------------------------- */

.sheet-page {
  background: #f2efe8;
  color: #111;
  min-height: 100vh;
  padding: clamp(1rem, 4vw, 3rem) var(--gutter);
}

.sheet {
  max-width: 210mm;
  margin-inline: auto;
  background: #fff;
  color: #141a18;
  padding: clamp(1.5rem, 5vw, 16mm);
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.18);
}

.sheet h1, .sheet h2, .sheet h3 { color: #0a0f0d; }

.sheet h1 { font-size: 30pt; font-weight: 400; line-height: 1.05; }
.sheet h2 { font-size: 12pt; }

.sheet .eyebrow, .sheet .rule-label { color: var(--gold-ink); }

.sheet__rule { border-top: 2px solid #8d7238; margin-block: 1.1rem; }
.sheet__hr { border-top: 1px solid #d8d2c4; margin-block: 1rem; }

.sheet__grid {
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (min-width: 40rem) {
  .sheet__grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

.sheet__cell h3 {
  font-family: var(--font-body);
  font-size: 7.5pt;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: #6b7570;
  margin-bottom: 0.3rem;
}

.sheet__cell p, .sheet__cell li { font-size: 9pt; line-height: 1.5; color: #333c38; }

.sheet__cell ul { display: grid; gap: 0.2rem; }

.sheet__cell li { padding-left: 0.9em; position: relative; }

.sheet__cell li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.55em;
  width: 4px;
  height: 4px;
  transform: rotate(45deg);
  background: #8d7238;
}

.sheet__foot {
  margin-top: 1.4rem;
  padding-top: 0.9rem;
  border-top: 1px solid #d8d2c4;
  font-size: 8pt;
  color: #6b7570;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.5rem;
  justify-content: space-between;
}

@media print {
  /* 10mm, not 12. The sheet is called a one-pager and was printing as two:
     its content runs about 1063px tall, against 1032px of usable height on A4
     at 12mm margins. It overflowed by roughly eight millimetres, which is a
     second sheet of paper carrying one rule and a footer — on the single
     document a buyer prints and takes away. */
  @page { size: A4; margin: 10mm; }
  html, body { background: #fff !important; }
  .sheet-page { padding: 0; background: #fff; min-height: 0; }
  .sheet { box-shadow: none; padding: 0; max-width: none; }
  .no-print, .site-header, .drawer, .site-footer, .cta { display: none !important; }

  /* And the rest of the margin comes out of the rules between sections, which
     are the most generous vertical spacing on the page and the least missed. */
  .sheet__rule { margin-block: 0.8rem; }
  .sheet__hr { margin-block: 0.7rem; }
  .sheet__foot { margin-top: 1rem; padding-top: 0.6rem; }

  /* Never break a block of specifications across the fold. */
  .sheet__cell,
  .sheet__grid { break-inside: avoid; }

  /* Languages that simply say more.

     The sheet is typed in points for print, so a parent font-size cannot
     scale it — zoom can, and it takes the rules, gaps and tables with it.

     These are measured outcomes, not arithmetic. The obvious approach —
     take each language's natural height and divide — does not work, because
     zoom reflows the text.

     MEASURED WITH THE WEBFONT BLOCKED, which is the case that matters.
     font-display is `optional`, so a reader whose cache is cold gets the
     fallback serif for that page and keeps it: Cormorant Garamond sets about
     13% narrower than the serif standing in for it, so the fallback is the
     wider, worse case, and it is the one that has to fit. The earlier values
     were tuned with the webfont loaded and were never true for a first
     visit; once font-display changed they stopped being true at all, and
     Dutch and Russian spilled onto a second sheet.

     Each value is the largest hundredth that leaves the sheet at or under
     1037px — 277mm of usable A4 at 96dpi, less 10px of room. Re-run
     scratchpad zoomsearch (fonts blocked, print media, step 0.01) rather
     than adjusting by eye: a language that slips over prints a second sheet
     carrying nothing but a rule and a footer, on the one document a buyer
     takes away with them.

     Everything not listed fits at full size even in the fallback: English,
     Arabic, Hebrew, Dari, Pashto, Hindi, Japanese and both Chinese. */
  [lang="th"] .sheet { zoom: 0.87; }
  [lang="ru"] .sheet { zoom: 0.89; }
  [lang="ur"] .sheet { zoom: 0.90; }
  [lang="de"] .sheet { zoom: 0.92; }
  :is([lang="nl"], [lang="fr"], [lang="es"]) .sheet { zoom: 0.93; }
  [lang="it"] .sheet { zoom: 0.95; }
  /* pt-BR ran 1050px against 1047 of A4 after the retranslation — measured,
     not guessed, so it gets its own value rather than sharing Italian's. */
  [lang="pt-BR"] .sheet { zoom: 0.94; }
  [lang="tr"] .sheet { zoom: 0.98; }
  /* Added when the offices line changed. "Dubai - the company / Kabul -
     source and export / Amsterdam - European office" sets longer than the
     line it replaced, and these three tipped 9-13px past A4 because of it.
     Measured, not guessed: ar and he ran 1056px against 1047, ja 1060. */
  :is([lang="ar"], [lang="he"]) .sheet { zoom: 0.99; }
  [lang="ja"] .sheet { zoom: 0.98; }
}

/* --------------------------------------------------------------------------
   14. Photographed stones
   The illustrations are lit by a tinted glow and a caustic pool. Real
   photographs arrive with their own backgrounds — black, white or matrix —
   so rather than fighting that, the photo fills the same stage and the
   lighting is rebuilt around it: a vignette to seat any background into the
   dark theme, a soft-light wash in the stone's own hue, and the caustic
   glow kept underneath. The hover push-in is retained.
   -------------------------------------------------------------------------- */

.gem-stage--photo {
  padding: 0;
  overflow: hidden;
}

.stone-photo {
  position: absolute;
  inset: 0;
  overflow: hidden;
  background: var(--ink-900);
}

.stone-photo picture,
.stone-photo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.stone-photo img {
  transition: transform 1.1s var(--ease-out), filter var(--dur) var(--ease-out);
  filter: saturate(1.06) contrast(1.04);
}

/* Vignette: seats a white studio background into the dark page without
   touching the stone itself, and does nothing visible on a black one. */
.stone-photo::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(78% 78% at 50% 45%, transparent 38%, rgba(5, 8, 7, 0.62) 100%),
    linear-gradient(180deg, rgba(5, 8, 7, 0.18) 0%, transparent 32%, rgba(5, 8, 7, 0.42) 100%);
}

/* Three of the placeholder photographs are studio shots on white seamless,
   and the vignette above — tuned for a stone on matrix — leaves them reading
   as lit panels cut out of a dark page. Measured at the outer 12% of each
   frame they sit at 179–201 mean luminance against 0–75 for every other
   photograph, so they are tagged rather than the vignette being deepened for
   all of them, which would only muddy the ones already dark.
   This goes when the house's own photography arrives. */
.stone-photo[data-bg="light"]::after {
  background:
    radial-gradient(72% 72% at 50% 45%, rgba(5, 8, 7, 0.1) 20%, rgba(5, 8, 7, 0.88) 100%),
    linear-gradient(180deg, rgba(5, 8, 7, 0.36) 0%, rgba(5, 8, 7, 0.08) 42%, rgba(5, 8, 7, 0.62) 100%);
}

.stone-photo[data-bg="light"] img {
  filter: saturate(1.06) contrast(1.04) brightness(0.82);
}

/* A wash in the stone's own colour, so a page of photographs from different
   sources still reads as one set. */
.stone-photo::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  mix-blend-mode: soft-light;
  background: radial-gradient(
    64% 64% at 50% 44%,
    color-mix(in srgb, var(--gem, var(--emerald)) 60%, transparent) 0%,
    transparent 72%
  );
}

.gem-card:hover .stone-photo img,
.feature:hover .stone-photo img {
  transform: scale(1.055);
  filter: saturate(1.14) contrast(1.06);
}

/* Keep the caustic pool under a photographed stone too */
.gem-stage--photo::before {
  z-index: 2;
  opacity: 0.55;
}

/* Placeholder marker — these are not our stones, and the page says so */
.photo-note {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  font-size: var(--step--2);
  letter-spacing: 0.04em;
  color: var(--muted);
  border: 1px dashed var(--rule);
  padding: 0.55em 0.9em;
  border-radius: 2px;
}

.photo-note::before {
  content: "";
  width: 6px;
  height: 6px;
  transform: rotate(45deg);
  background: var(--gold);
  flex-shrink: 0;
}

/* Lot cards read as a parcel rather than a single stone */
.gem-card__tag--lot {
  color: var(--ink-900);
  background: var(--gold);
  border-color: var(--gold);
  font-weight: 600;
}

.card__weight {
  font-family: var(--font-display);
  font-size: var(--step-1);
  color: var(--gold-light);
  line-height: 1;
}

/* --------------------------------------------------------------------------
   15. Cutting-bench markers
   Distinguished from office pins: a small emerald lozenge rather than a gold
   ring, so the map shows two networks at once without the eye confusing them.
   Antwerp and Kabul are both office and bench, and are drawn once as offices.
   -------------------------------------------------------------------------- */

.bench-pin__mark {
  fill: var(--emerald-bright);
  fill-opacity: 0.9;
  stroke: var(--ink-900);
  stroke-width: 1.5;
}

.bench-pin__label {
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  fill: var(--emerald-bright);
  fill-opacity: 0.92;
  pointer-events: none;
  paint-order: stroke fill;
  stroke: var(--ink-900);
  stroke-width: 3px;
  stroke-linejoin: round;
}

/* Legend under the map */
.map-key {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-s) var(--space-l);
  justify-content: center;
  margin-top: var(--space-m);
  font-size: var(--step--2);
  color: var(--muted);
  letter-spacing: 0.06em;
}

.map-key span { display: flex; align-items: center; gap: 0.6em; }

.map-key i {
  width: 10px;
  height: 10px;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--gold-light);
  box-shadow: 0 0 0 3px rgba(194, 161, 95, 0.25);
}

.map-key i.is-bench {
  border-radius: 1px;
  transform: rotate(45deg);
  background: var(--emerald-bright);
  box-shadow: none;
}

/* --------------------------------------------------------------------------
   Callout
   A single point that deserves to stop the eye mid-section — used for the
   cutting facility, where the interesting part is the tension between the
   machine and the hand rather than a list of capabilities.
   -------------------------------------------------------------------------- */

.callout {
  border: 1px solid var(--rule);
  border-left: 2px solid var(--gold);
  background: color-mix(in srgb, var(--ink-800) 60%, transparent);
  padding: clamp(1.25rem, 3.5vw, 2.25rem);
  display: grid;
  gap: 0.85rem;
  max-width: 78ch;
  margin-inline: auto;
}

.callout h3 {
  font-size: var(--step-1);
  color: var(--bone-100);
  margin: 0;
}

.callout p {
  color: var(--muted);
  font-size: var(--step--1);
  line-height: 1.7;
  margin: 0;
}

.callout strong { color: var(--bone-200); }

/* --------------------------------------------------------------------------
   Origin photography
   A landscape between sections, so the reader sees the ground the material
   comes out of rather than another photograph of a faceted stone. Held to a
   band so a portrait-format frame cannot run away down the page.
   -------------------------------------------------------------------------- */

/* A pair of bench photographs above the five-bench grid. Same documentary
   treatment as the origin shots so they read as one body of work, but side
   by side, because the two say different things: one is the wheel, the other
   is the decision made before the wheel. */
.bench-photos {
  display: grid;
  gap: var(--space-m);
  margin-bottom: var(--space-xl);
}

@media (min-width: 46rem) {
  /* Two landscape frames and one portrait clip. The portrait gets the narrow
     track so all three finish at roughly the same height instead of the tall
     one forcing the row open. */
  .bench-photos { grid-template-columns: 1.3fr 1fr 0.62fr; align-items: start; }
}

@media (min-width: 46rem) and (max-width: 74rem) {
  /* Not enough width for three: the clip drops to a second line, spanning
     both tracks so it is centred rather than stranded in one of them. */
  .bench-photos { grid-template-columns: 1.35fr 1fr; }
  .bench-photos > .bench-clip { grid-column: 1 / -1; max-width: 420px; margin-inline: auto; }
}

.bench-photo { margin: 0; }

.bench-photo picture {
  display: block;
  overflow: hidden;
  border: 1px solid var(--rule);
}

.bench-photo img {
  display: block;
  width: 100%;
  height: clamp(200px, 32vh, 340px);
  object-fit: cover;
  filter: saturate(0.86) contrast(1.04) brightness(0.94);
}

.bench-photo figcaption {
  margin-top: 0.7rem;
  font-size: var(--step--1);
  color: var(--muted);
  line-height: 1.5;
}

.origin-photo {
  margin: 0 auto var(--space-xl);
  max-width: min(96ch, 100%);
  padding-inline: var(--gutter);
}

.origin-photo picture {
  display: block;
  position: relative;
  overflow: hidden;
  border: 1px solid var(--rule);
}

.origin-photo img {
  display: block;
  width: 100%;
  height: clamp(220px, 42vh, 460px);
  object-fit: cover;
  /* These are documentary photographs, not studio work; a slight desaturation
     and a lift of the blacks settles them against the dark theme instead of
     letting a bright sky punch a hole in the page. */
  filter: saturate(0.86) contrast(1.04) brightness(0.94);
}

.origin-photo figcaption {
  margin-top: 0.7rem;
  font-size: var(--step--2);
  line-height: 1.6;
  color: var(--muted);
  letter-spacing: 0.02em;
}

.origin-photo figcaption .muted { color: var(--muted-dark); }

/* --------------------------------------------------------------------------
   Chain diagram on small screens
   The whole argument of this diagram is five hands against one, seen at the
   same time. Laid out horizontally on a phone it ran off the edge at "Kabul
   exporter" — the remaining four steps sat behind a side-scroll nobody
   discovers, so the comparison simply did not happen. Below 700px it becomes
   a vertical list instead, which keeps both lanes fully visible.
   -------------------------------------------------------------------------- */

@media (max-width: 700px) {
  .chain__track {
    flex-direction: column;
    overflow-x: visible;
    padding-bottom: 0;
  }

  .chain__node {
    grid-template-columns: 26px 1fr;
    justify-items: start;
    text-align: left;
    align-items: center;
    gap: 0.1rem 0.85rem;
    min-width: 0;
    padding-inline: 0;
    padding-block: 0.5rem;
  }

  .chain__dot {
    grid-row: 1 / span 2;
    grid-column: 1;
  }

  .chain__label,
  .chain__margin { grid-column: 2; }

  .chain__label { font-size: var(--step--1); }

  /* The connector runs down the column of dots rather than across. */
  .chain__node::before {
    width: 1px;
    height: 100%;
    top: -50%;
    left: 13px;
    transform: translateX(-0.5px);
  }
}

/* A photomicrograph beside the clarity-type explanation. Narrower than the
   origin shots — it is evidence for the paragraph above it, not a header
   image, and at full bleed it would read as decoration. */
.incl-photo {
  margin: var(--space-l) 0 0;
  max-width: 62ch;
}

.incl-photo picture {
  display: block;
  overflow: hidden;
  border: 1px solid var(--rule);
}

.incl-photo img {
  display: block;
  width: 100%;
  height: clamp(180px, 26vh, 300px);
  object-fit: cover;
  /* Left unmuted, unlike the documentary photographs: the colour IS the
     information here, and desaturating it would misrepresent the stone. */
}

.incl-photo figcaption {
  margin-top: 0.7rem;
  font-size: var(--step--1);
  color: var(--muted);
  line-height: 1.5;
}

/* ==========================================================================
   Phones
   ==========================================================================

   Everything below was found by loading all 171 pages at 360px wide with a
   touch pointer and measuring, rather than by looking. Each rule fixes
   something that is fine on a desktop and wrong in the hand.
   ========================================================================== */

@media (max-width: 700px) {
  /* Filter chips were 36-39px tall. A thumb needs 44, and these sit in a row
     where mis-taps land on the neighbouring filter rather than on nothing. */
  .chip {
    min-height: 46px;
    display: inline-flex;
    align-items: center;
  }

  /* The Studio sliders were 26px of draggable height. The visible track stays
     a 2px hairline; the input box around it grows to a thumb's worth, which
     is invisible and makes the difference between dragging the stone size and
     scrolling the page by accident. */
  input[type="range"] {
    /* 46, for the same reason as the buttons: a value set exactly at the
       threshold rounds under on some builds, and the audit then flags a
       different language each run rather than a real regression. */
    height: 46px;
  }

  /* Every remaining control in the Studio and the register toolbar. */
  .studio button,
  .toolbar button,
  .lightbox button {
    min-height: 46px;
  }

  /* Map labels are drawn in SVG user units and scale with the map, so at this
     width they land at 9px — smaller than anything else on the site and not
     readable. The same names are set as real text in the offices list and the
     origins list directly below, so the map keeps its dots and loses its
     captions rather than showing type nobody can read. */
  .office-pin__label,
  .map__label {
    display: none;
  }

  /* 8px colour names inside the spectrum swatches. The swatch itself carries
     the meaning here — it is a colour — so the label becomes the caption it
     already is elsewhere rather than growing and breaking the chip. */
  .spectrum__swatch span {
    font-size: var(--step--3);
  }

  /* The Studio's colour and cut options. They sit in rows, so a mis-tap picks
     the wrong stone rather than doing nothing.

     46, not 44. Setting the minimum to exactly the minimum leaves nothing for
     sub-pixel rounding: the measured height came back a hair under on some
     builds and not others, so the audit flagged a different set of languages
     on every run — English one time, Thai and Portuguese the next — which
     reads as flaky when it is simply a value sitting on its own boundary. Two
     pixels of headroom makes it unambiguous. */
  .segmented button {
    min-height: 46px;
  }

  /* The email address on the contact page is the single most-tapped thing on
     the site, and it was a 30px-high line of text. */
  .contact-item a {
    display: inline-flex;
    align-items: center;
    min-height: 46px;
  }

  }

/* The capability sheet is laid out as an A4 document and typed in points, so
   it prints correctly — and so at 360px it renders at seven and eight point,
   around 9px, which is unreadable on a phone. Screen only: print keeps the
   points it was designed with. */
@media screen and (max-width: 700px) {
  /* !important, and matched on the style attribute, because the sizes are
     set inline in capability-sheet.html — that page is laid out as a printed
     document and the point sizes belong to the print design. An inline style
     cannot be beaten by specificity, only by weight, and rewriting the sheet's
     markup to move them into classes would put the printed artefact at risk to
     fix a screen problem. Print is untouched: this is screen-only. */
  .sheet [style*="font-size:7pt"],
  .sheet [style*="font-size:7.5pt"],
  .sheet [style*="font-size:8pt"] { font-size: var(--step--3) !important; }

  .sheet [style*="font-size:9pt"],
  .sheet [style*="font-size:9.5pt"],
  .sheet [style*="font-size:10.5pt"] { font-size: var(--step--2) !important; }

  .sheet h1,
  .sheet [style*="font-size:19pt"] { font-size: var(--step-2) !important; }

  .sheet h2 { font-size: var(--step--1); }
  .sheet__foot { font-size: var(--step--3); }
  .sheet__cell h3 { font-size: var(--step--2); }
  .sheet__cell p,
  .sheet__cell li { font-size: var(--step--2); }
}

/* The no-JavaScript language list that tools/prerender-i18n.mjs puts at the
   end of every page. It is only ever rendered when scripting is off, so it
   cannot affect an ordinary visitor — but when it does render it should look
   like part of the site rather than a raw browser list. */
.noscript-langs {
  border-top: 1px solid var(--rule-soft);
  padding: var(--space-m) var(--space-m) var(--space-l);
  background: var(--ink-900);
}

.noscript-langs ul {
  list-style: none;
  margin: 0 auto;
  padding: 0;
  max-width: 72rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.2rem;
}

.noscript-langs a {
  color: var(--muted);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  min-height: 46px;
}

.noscript-langs a:hover,
.noscript-langs a:focus-visible { color: var(--gold-light); }

/* A photograph in a media column, standing beside the prose rather than
   spanning the measure. The base rule crops to a fixed band height, which is
   right for a landscape across the full width and wrong here: it would take a
   portrait photograph and letterbox it inside its own column. These keep a
   portrait proportion and fill the column they are given. */
.origin-photo--tall {
  margin: var(--space-m) 0 0;
  max-width: none;
  padding-inline: 0;
}

.origin-photo--tall img {
  height: auto;
  aspect-ratio: 3 / 4;
}

/* A band across the measure, capped by height rather than forced to one. A
   near-square photograph forced into the base band height loses most of its
   subject; capped instead, it crops to a band without being gutted.

   It also has to span the SAME width as the section around it. The base rule
   centres the figure inside 96ch, which is right for a figure sitting alone in
   a column of prose and wrong for one placed above a full-width tile grid: the
   heading and the tiles ran the whole measure while the photograph sat inset
   between them, with a band of empty ground down either side. */
.origin-photo--band {
  max-width: none;
  padding-inline: 0;
  margin-bottom: clamp(2.5rem, 6vw, var(--space-2xl));   /* the head's own margin, verbatim */
}

/* A band that follows a three-column row rather than a heading: the row has
   no bottom margin of its own, so the band supplies the same gap above. */
.origin-photo--after-row {
  margin-top: clamp(2.5rem, 6vw, var(--space-2xl));
  margin-bottom: 0;
}

.origin-photo--band img {
  height: auto;
  max-height: min(52vh, 480px);
}

@media (max-width: 720px) {
  .origin-photo--tall img { aspect-ratio: 4 / 3; }
}

/* Shown whole, never cropped.

   The band rule caps height and the base rule crops to fill, which is the
   right behaviour for a photograph used as a decorative strip and the wrong
   behaviour for one where the subject IS the frame — men sitting out on the
   scree reading a parcel. Cropping it to a letterbox cut the group in half and
   then stretched what was left, which is what made it look soft. This keeps
   the whole frame at its own proportion and limits how much of the page it
   takes by width instead. */
.origin-photo--uncropped {
  /* Scaled down, not cropped. At 900px the full frame dominated the section
     and pushed everything under it off the screen; the instruction was to
     keep the whole frame, not to give it the whole page. */
  max-width: min(620px, 100%);
  margin-inline: auto;
}

.origin-photo--uncropped img {
  max-height: none;
  height: auto;
  object-fit: contain;
}

/* A portrait photograph used between blocks of prose.

   A tall frame cannot span the measure: cropped to a band it loses its
   subject, and left at its own proportion across a wide column it becomes a
   wall. Held to a narrow column and centred, it reads as a plate in a book —
   whole, uncropped, and not competing with the text around it. */
.origin-photo--portrait {
  max-width: min(420px, 100%);
  margin-inline: auto;
}

.origin-photo--portrait img {
  height: auto;
  max-height: none;
  object-fit: contain;
}

/* Never wider than the file itself.

   Each figure carries its own native pixel width as --nat (written by
   tools/cap-image-width.mjs from the img's width attribute). A column wider
   than the photograph would otherwise stretch it — measured, one 580px frame
   was being shown at 1438px. Capping here fixes every placement at once and
   keeps working when a photograph is swapped for a different one. */
.origin-photo[style*="--nat"] {
  max-width: min(var(--nat), 100%);
  margin-inline: auto;
}

/* Same cap for the bench photographs on the home page: a 627px frame was
   being shown at 701px. Small, but it is the same fault and the same fix. */
.bench-photo[style*="--nat"] {
  max-width: min(var(--nat), 100%);
}

/* Geography: map, text and photograph as one row of three.

   These were a two-column split with the photograph dropped underneath, which
   left a tall column of empty ground beside it and read as an afterthought
   rather than as part of the section. Three abreast on a wide screen, stacking
   in order on a narrow one. The photograph is last so that on a phone the
   argument still reads map, then text, then picture. */
.origins-three {
  display: grid;
  gap: var(--space-l);
  align-items: center;
}

@media (min-width: 62rem) {
  /* Two columns, not three.

     Three abreast fixed the stacking but not the composition: the map is a
     wide, shallow shape and the prose is a tall one, so a single row of three
     left the map stranded at the top of a column twice its height with a void
     under it, and shrank all three objects to fit. Measured, the map came out
     174px tall in a 694px row.

     Stacking the two pictures in one column against the text in the other
     lets both fill their space — the column's height is now shared between
     the map and the photograph instead of wasted under the map — and both are
     substantially larger for it. */
  .origins-three:not(.origins-three--province) {
    grid-template-columns: 0.98fr 1.02fr;
    grid-template-rows: auto 1fr;
    gap: var(--space-l) var(--space-xl);
    align-items: start;
  }

  .origins-three:not(.origins-three--province) > .map {
    grid-column: 1;
    grid-row: 1;
    align-self: center;
  }

  .origins-three:not(.origins-three--province) > .split__body {
    grid-column: 2;
    grid-row: 1 / span 2;
  }

  .origins-three:not(.origins-three--province) > .origin-photo {
    grid-column: 1;
    grid-row: 2;
    width: 100%;
  }
}

.origin-photo--col {
  margin: 0;
  padding-inline: 0;
  width: 100%;
  max-width: min(var(--nat), 100%);
}

.origin-photo--col img {
  height: auto;
  max-height: none;
  object-fit: contain;
}

/* House footage. Sized like the portrait photographs and given the same
   border, so a clip and a still read as the same kind of object rather than
   as a video player dropped into the page. */
.house-clip video {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--rule);
  filter: saturate(0.86) contrast(1.04) brightness(0.94);
}

@media (prefers-reduced-motion: reduce) {
  /* A reader who has asked for stillness gets the poster frame and nothing
     that moves. The clip carries no information, so nothing is lost. */
  .house-clip video { display: none; }
  .house-clip { background-size: cover; background-position: center; }
}

/* The province rows carry a turning stone, a column of prose and a
   photograph. The prose is the widest of the three because it is the thing
   being read; the stone and the picture flank it. */
@media (min-width: 62rem) {
  .origins-three--province {
    grid-template-columns: 1.05fr 1.2fr 1.05fr;
    align-items: center;
  }
}

/* Heading beside its photograph, not stacked above it.

   A centred heading with a full-width photograph dropped underneath and a tile
   grid under that is three full-width blocks in a column — a vertical dump.
   Pairing the words with the picture gives the section a shape and halves its
   height, and the tiles below then read as the detail rather than as a third
   slab. */
.origins-pair {
  display: grid;
  gap: var(--space-l);
  align-items: center;
  /* One rhythm. This is the section-head's own bottom margin, verbatim, so
     a heading-with-picture leaves exactly the space under it that a bare
     heading does. It had been a smaller token, so on the same page the tiles
     sat 36px under a pair and 80px under a head. */
  margin-bottom: clamp(2.5rem, 6vw, var(--space-2xl));
}

@media (min-width: 62rem) {
  /* Even columns. The heading had the larger share, which left the picture as
     the smaller half of a pair whose whole point is the picture — and where
     the heading is short, most of its column was empty anyway. */
  .origins-pair { grid-template-columns: 1fr 1fr; gap: var(--space-xl); align-items: center; }
  .origins-pair .section-head { text-align: left; margin: 0; }
}

/* Media in a pair fills the column it is given, up to its own native size.
   It was inheriting a narrow cap meant for a figure sitting inside a column of
   prose, so a 596px photograph beside a large display heading read as a
   thumbnail. */
.origins-pair > .origin-photo,
.origins-pair > figure {
  width: 100%;
  max-width: min(var(--nat), 100%);
  margin: 0;
  padding-inline: 0;
  justify-self: end;
}

.origins-pair > figure img,
.origins-pair > figure video {
  width: 100%;
  height: auto;
  max-height: none;
  object-fit: contain;
}


/* The map is artwork, not a photograph — it is an SVG and scales without loss,
   so there is no reason for it to sit small inside its column. */
.origins-three .map svg {
  width: 100%;
  height: auto;
}

/* A clip sitting in the bench row reads as one of the set, not as a video
   dropped on the page. It was floating above the row on its own, centred, with
   empty ground either side — a lone block with nothing to relate to. */
.bench-clip video {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--rule);
  filter: saturate(0.86) contrast(1.04) brightness(0.94);
}

@media (prefers-reduced-motion: reduce) {
  .bench-clip video { display: none; }
}

@media (max-width: 48rem) {
  /* 0.72rem is 11.5px on a phone — under the 12px floor for text that has to
     be read, and these are the labels on the Studio's controls. */
  .control__label { font-size: 0.75rem; }
}

@media (max-width: 48rem) {
  /* The availability table scrolls sideways on a phone, which is right for a
     six-column grid — but its caption is laid out at the table's full 741px,
     so the sentence introducing the table was clipped at the screen edge and
     could only be read by scrolling the table. The caption is held to the
     visible width and pinned to the left, so it stays readable while the
     grid behind it scrolls. */
  /* Spec-builder field labels: 0.72rem is 11.5px here, under the 12px floor. */
  .field label { font-size: 0.75rem; }
}

/* The availability table's introduction, as a paragraph above the scroller
   rather than a <caption> inside it: laid out by the page, so it wraps at the
   screen edge instead of at the table's. Styled as the caption was. */
.matrix-note {
  text-align: left;
  font-size: var(--step--2);
  color: var(--muted);
  padding-bottom: var(--space-s);
  max-width: 96ch;
}

/* --------------------------------------------------------------------------
   Phone: tables as stacked cards, and the chain's pulse running downward
   -------------------------------------------------------------------------- */
@media (max-width: 48rem) {
  /* A six-column table on a phone was a horizontal scroller. Each row is now
     a card: the row's name across the top, then its cells two abreast, each
     labelled with the column it came from. The label is the column heading's
     own translated text, carried on the cell as data-band. */
  .matrix-scroll { overflow: visible; padding-bottom: 0; }
  .matrix { display: block; min-width: 0; border-spacing: 0; }
  .matrix thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .matrix tbody { display: grid; gap: var(--space-s); }
  .matrix tr {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 6px;
    padding: 0.9rem;
    border: 1px solid var(--rule-soft);
    background: var(--surface);
  }
  .matrix th[scope="row"] {
    grid-column: 1 / -1;
    white-space: normal;
    padding: 0 0 0.4rem;
    font-size: var(--step--1);
  }
  .matrix td {
    display: grid;
    gap: 0.25rem;
    align-content: center;
    height: auto;
    min-height: 48px;
    padding: 0.5rem 0.6rem;
    text-align: left;
  }
  .matrix td::before {
    content: attr(data-band);
    display: block;
    font-size: var(--step--3);
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--muted);
  }

  /* The chain is a column here, so the pulse travels DOWN the line of dots.
     Its keyframes animated `left`, so on a phone it slid sideways across the
     first entry instead. */
  .chain__pulse {
    left: 13px;
    top: 0;
    transform: translateX(-50%);
    animation-name: chainRunDown;
  }
}

@keyframes chainRunDown {
  0%   { top: 4%;  opacity: 0; }
  12%  { opacity: 1; }
  88%  { opacity: 1; }
  100% { top: 96%; opacity: 0; }
}
