/* Mithqal web — the app's own palette, reproduced for the browser.
   Tokens come straight from lib/core/theme/app_palette.dart and app_colors.dart
   so the page and the Flutter screen read as one product.

   Layout is desktop-first in the sense that the desktop gets the wide,
   information-dense treatment it can carry; every block still collapses to one
   column on a phone, which is where most of the traffic is. */

@font-face {
  font-family: 'Cairo';
  src: url('fonts/Cairo-Variable.ttf') format('truetype-variations');
  font-weight: 200 1000;
  font-display: swap;
}

:root {
  /* brand — constant across themes */
  --navy: #000F2F;
  --gold: #D6A438;
  --gold-soft: #E0B85A;
  --cream: #F5E8D1;
  --success: #66BB6A;
  --error: #E57373;

  /* dark palette (AppPalette.dark) */
  --bg: #000F2F;
  --surface: #2C2C2E;
  --card: #2C2C2E;
  --card-border: #3E3E42;
  --muted-surface: #1A2438;
  --text: #FFFFFF;
  --text-2: #F5E8D1;
  --text-3: #B8B0A0;
  --caption: #A39E94;
  --divider: #3E3E42;
  --shadow: 0 2px 8px rgba(0, 0, 0, .18);
  --shadow-lg: 0 18px 48px rgba(0, 0, 0, .35);
  --bar: rgba(0, 15, 47, .88);
  --glow: rgba(214, 164, 56, .16);
  color-scheme: dark;

  /* layout */
  --max: 1128px;
  --gutter: 24px;
  --r-sm: 10px;
  --r: 14px;
  --r-lg: 22px;
}

:root[data-theme='light'] {
  /* AppPalette.light */
  --bg: #F5E8D1;
  --surface: #FFF8EE;
  --card: #FFF8EE;
  --card-border: #D6C4A4;
  --muted-surface: #EDE0C8;
  --text: #000F2F;
  --text-2: #2C2C2E;
  --text-3: #5A5A62;
  --caption: #6E6E76;
  --divider: #D6C4A4;
  --shadow: 0 2px 8px rgba(0, 0, 0, .06);
  --shadow-lg: 0 18px 48px rgba(0, 15, 47, .12);
  --bar: rgba(245, 232, 209, .9);
  --glow: rgba(214, 164, 56, .22);
  color-scheme: light;
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; scroll-padding-top: 96px; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

html, body { margin: 0; background: var(--bg); color: var(--text); }

body {
  font-family: 'Cairo', 'Segoe UI', Tahoma, sans-serif;
  line-height: 1.75;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  transition: background-color .2s ease, color .2s ease;
}

h1, h2, h3, h4 { line-height: 1.4; margin: 0; }
p { margin: 0; }
a { color: inherit; text-decoration: none; }
img { max-width: 100%; }

/* Every figure is Latin-digit and grouped, so it has to read left-to-right
   even inside an RTL sentence. One class, used everywhere. */
.num {
  direction: ltr;
  unicode-bidi: isolate;
  font-variant-numeric: tabular-nums;
}

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* Parked above the viewport, not beside it. The usual `left: -9999px` trick is
   an inline offset, and in an RTL document that pushes the link off the right
   edge — which is the side the page scrolls from, so every phone opened on a
   page shifted sideways. Moving it vertically cannot do that. */
.skip {
  position: absolute; inset-inline-start: 12px; top: -80px; z-index: 100;
  background: var(--gold); color: var(--navy);
  padding: 10px 18px; border-radius: 0 0 var(--r-sm) var(--r-sm); font-weight: 700;
}
.skip:focus { top: 0; }

:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

.shell {
  width: 100%;
  max-width: var(--max);
  margin: 0 auto;
  padding: 0 var(--gutter);
}
.shell-narrow { max-width: 820px; }

/* ── buttons ─────────────────────────────────────────────────────────── */
/*
 * `hidden` has to actually hide.
 *
 * The attribute works through a *user-agent* rule, `[hidden] { display: none }`,
 * and any author rule that sets `display` beats it regardless of specificity —
 * author origin simply wins. Every component below that sets `display` on a
 * class therefore silently opts out of `hidden`, and `el.hidden = true` from
 * JavaScript becomes a no-op that leaves the element on screen.
 *
 * This had already been patched once, one element at a time, with a
 * `.drawer[hidden]` rule. It went unnoticed on the sign-in page until the
 * OAuth origin was authorised: Google's own button started rendering, the
 * script correctly set `hidden` on our hand-built fallback, and **both buttons
 * stayed on screen** because the fallback's `.gsi-button { display: flex }`
 * outranked the attribute. Reported from the live site 2026-09-21.
 *
 * `!important` is the right tool here and not a shortcut: `hidden` is a
 * statement that the element is not relevant, and no layout rule should be
 * able to argue with that.
 */
[hidden] { display: none !important; }

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 11px 22px;
  border-radius: 999px;
  border: 1px solid transparent;
  font: inherit; font-size: .88rem; font-weight: 700;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color .15s ease, border-color .15s ease, transform .15s ease;
}
.btn:active { transform: translateY(1px); }
.btn-sm { padding: 8px 16px; font-size: .8rem; }
.btn-lg { padding: 14px 30px; font-size: .95rem; }
.btn-block { width: 100%; }

.btn-gold { background: var(--gold); color: var(--navy); }
.btn-gold:hover { background: var(--gold-soft); }

.btn-ghost { border-color: var(--card-border); color: var(--text); background: transparent; }
.btn-ghost:hover { border-color: var(--gold); color: var(--gold); }

.btn[disabled] { opacity: .5; cursor: default; }

/* ── top bar ─────────────────────────────────────────────────────────── */
.topbar {
  position: sticky; top: 0; z-index: 20;
  background: var(--bar);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--divider);
  /* Installed on iOS the status bar is translucent and the page runs under it
     (apple-mobile-web-app-status-bar-style). Zero in a browser tab. */
  padding-top: env(safe-area-inset-top);
}
.topbar-inner {
  display: flex; align-items: center; gap: 28px;
  min-height: 66px;
}

.brand { display: flex; align-items: center; gap: 12px; flex: none; }

/* The mark is the M alone now, and it is wider than it is tall — so height is
   what is fixed and the width follows, rather than forcing it into a square and
   letterboxing it. No border-radius: it is a transparent silhouette, not a
   tile, and rounding would clip the serifs of the M itself. The attributes stay
   on the <img> to reserve the space before the file arrives; without them the
   header jumps as it loads. */
.brand-logo { height: 35px; width: auto; display: block; }

/* Gold on the dark bar, navy on the light one — the inverse pairing the brand
   artwork uses. Driven by the attribute `<head>` sets before first paint, so
   there is no flash of the wrong mark and nothing waits for a script.
   Dark is the default, matching the default theme. */
.brand-logo.for-light { display: none; }
:root[data-theme='light'] .brand-logo.for-dark { display: none; }
:root[data-theme='light'] .brand-logo.for-light { display: block; }
.brand-name { display: block; font-size: 1.2rem; font-weight: 800; }
.brand-sub  { display: block; font-size: .72rem; color: var(--caption); margin-top: -3px; }
/* A phone gives the header about 100px of usable width beside the burger and
   the theme toggle, so the desktop mark is scaled back rather than allowed to
   push the navigation off the row. */
@media (max-width: 620px) {
  .brand-logo { height: 27px; width: auto; }
  .brand-name { font-size: 1.05rem; }
}

.nav { display: flex; align-items: center; gap: 22px; }

/* `nowrap` because an Arabic nav label is two or three words and breaking one
 * across two lines turns the whole bar into two rows of fragments. It went
 * unnoticed until the account button appeared: signed out it reads «دخول»,
 * signed in it carries a person's full name, and the extra width was enough to
 * start wrapping every item beside it. Reported from the live site 2026-09-21.
 *
 * The bar is hidden below the tablet breakpoint anyway, so this cannot squeeze
 * a phone — the drawer takes over there. */
.nav a {
  font-size: .85rem; font-weight: 600; color: var(--text-3); padding: 6px 0;
  white-space: nowrap;
}
.nav a:hover { color: var(--text); }
.nav a.on { color: var(--gold); }

.top-actions { margin-inline-start: auto; display: flex; align-items: center; gap: 8px; }

/* A signed-in header shows the person's name, and a name has no maximum
 * length. Capped and ellipsised so the longest one cannot push the navigation
 * into wrapping — the failure this pairs with above. */
.top-actions .btn-account {
  max-width: 11rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.icon-btn {
  width: 38px; height: 38px; flex: none;
  display: grid; place-items: center;
  border-radius: 11px;
  background: var(--muted-surface);
  border: 1px solid var(--card-border);
  color: var(--gold);
  cursor: pointer;
}
.icon-btn:hover { border-color: var(--gold); }
.burger { display: none; }

/* `only-dark` is shown only in the dark theme — so the toggle, which sits
   in it, offers the light one. This rule was inverted until 2026-09-26 and
   both theme buttons offered the theme already on screen. */
:root[data-theme='light'] .only-dark,
:root[data-theme='dark'] .only-light { display: none; }

/* ── mobile drawer ───────────────────────────────────────────────────── */
.drawer { position: fixed; inset: 0; z-index: 40; background: rgba(0, 0, 0, .5); }
.drawer-panel {
  position: absolute; inset-block: 0; inset-inline-end: 0;
  width: min(310px, 84vw);
  background: var(--bg);
  border-inline-start: 1px solid var(--divider);
  padding: 16px;
  display: flex; flex-direction: column; gap: 14px;
  overflow-y: auto;
}
.drawer-head { display: flex; align-items: center; justify-content: space-between; }
.drawer-nav { display: flex; flex-direction: column; }
.drawer-nav a {
  display: flex; align-items: center; justify-content: space-between;
  padding: 13px 4px;
  font-size: .92rem; font-weight: 600;
  color: var(--text-3);
  border-bottom: 1px solid var(--divider);
}
.drawer-nav a.on { color: var(--gold); }
.drawer-nav .ico { opacity: .5; }

/* ── ticker ──────────────────────────────────────────────────────────── */
.ticker {
  background: var(--muted-surface);
  border-bottom: 1px solid var(--divider);
  font-size: .78rem;
  overflow-x: auto;
  scrollbar-width: none;
}
.ticker::-webkit-scrollbar { display: none; }
.ticker-inner {
  display: flex; align-items: center; gap: 22px;
  padding-block: 9px;
  white-space: nowrap;
}
.ticker-live { display: inline-flex; align-items: center; gap: 7px; color: var(--text-3); font-weight: 700; }
.ticker-item { color: var(--caption); }
.ticker-item b { color: var(--text); font-weight: 800; margin-inline: 3px; }
.ticker-time { margin-inline-start: auto; display: inline-flex; align-items: center; gap: 6px; }
.ticker-time .ico { opacity: .6; }

/* The live indicator, which now also carries the direction.
 *
 * Green when the day is up, red when it is down, gold while there is nothing
 * to say — a freshly deployed site has no 24-hour basis yet, and a green light
 * then would be claiming a rise that has not been measured. Colour is never the
 * only signal: the figure beside it carries the sign and an arrow. */
.dot {
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--gold);
  box-shadow: 0 0 6px rgba(214, 164, 56, .75);
  animation: pulse 2s ease-in-out infinite;
  flex: none;
  transition: background .3s ease, box-shadow .3s ease;
}
.dot.up   { background: var(--success); box-shadow: 0 0 7px rgba(76, 175, 80, .85); }
.dot.down { background: var(--error);   box-shadow: 0 0 7px rgba(229, 83, 83, .85); }
@keyframes pulse { 50% { opacity: .35; } }
@media (prefers-reduced-motion: reduce) { .dot { animation: none; } }

.up   { color: var(--success); }
.down { color: var(--error); }
.flat { color: var(--caption); }   /* no movement is neither, and must not read as a rise */

/* ── the price flash ─────────────────────────────────────────────────── */
/* The ounce is read every twenty seconds, so the headline figure rewrites
   itself while the page sits open — and a number that changes in place is a
   number nobody sees change. One flash, in the direction it moved, and none at
   all when a poll brings back the same figure. See setPrice() in app.js.

   The wash is painted with `box-shadow` spread rather than padding, so a number
   that flashes never nudges the line it sits on. A layout shift on every price
   move would be a far worse thing than the silence it is fixing. */
.flash-up, .flash-down {
  border-radius: 8px;
  animation: price-flash .9s ease-out 1;
}
.flash-up  { --flash: var(--success); --flash-wash: rgba(102, 187, 106, .22); }
.flash-down { --flash: var(--error); --flash-wash: rgba(229, 115, 115, .22); }

@keyframes price-flash {
  0% {
    color: var(--flash);
    background: var(--flash-wash);
    box-shadow: 0 0 0 6px var(--flash-wash);
  }
  100% {
    color: var(--text);
    background: transparent;
    box-shadow: 0 0 0 6px transparent;
  }
}

/* A colour that pulses is still something moving on the page, and the badge
   under the figure already says which way it went. Nobody who has asked for
   less motion loses information here. */
@media (prefers-reduced-motion: reduce) {
  .flash-up, .flash-down { animation: none; }
}

/* Stale means the backend went quiet and these are the last good numbers.
   Dim the figures, not the whole page — the rest is still perfectly true. */
body.stale .num { opacity: .62; }

/* ── section scaffolding ─────────────────────────────────────────────── */
.section { padding-block: 56px; }
.section-tight { padding-block: 36px; }
.section-alt { background: var(--muted-surface); border-block: 1px solid var(--divider); }

.section-head { margin-bottom: 26px; }
.stack-gap { margin-top: 34px; }
.section-head.center { text-align: center; }
.section-head h2 { font-size: clamp(1.25rem, 2.4vw, 1.75rem); font-weight: 800; }
.section-head p { margin-top: 8px; color: var(--text-3); font-size: .92rem; }
.eyebrow {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: .75rem; font-weight: 700; color: var(--gold);
  background: var(--glow);
  border-radius: 999px; padding: 5px 13px;
  margin-bottom: 12px;
}

.card {
  background: var(--card);
  border: 1px solid var(--card-border);
  border-radius: var(--r);
  padding: 16px;
  box-shadow: var(--shadow);
}
.label { font-size: .78rem; color: var(--caption); }

/* ── hero ────────────────────────────────────────────────────────────── */
.hero { position: relative; padding-block: 60px 52px; overflow: hidden; }
.hero::before {
  content: ''; position: absolute; z-index: 0;
  inset-inline-end: -140px; top: -180px;
  width: 520px; height: 520px; border-radius: 50%;
  background: radial-gradient(circle, var(--glow), transparent 68%);
  pointer-events: none;
}
.hero-grid {
  position: relative; z-index: 1;
  display: grid; grid-template-columns: 1fr 1fr;
  column-gap: 56px; row-gap: 34px;
  align-items: center;
}

/* The ounce and the dollar take the whole first row, half of it each, above
   both columns. Stacked on top of the price card instead — where they started —
   they made that column half again as tall as the text beside it, and
   `align-items: center` paid the difference out as empty space above and below
   the headline. Across the top the two columns below finish close to level.
   The 16px is the strip's own gap between its two boxes; the space under it
   belongs to the grid's row-gap. */
.hero-grid > .market-strip { grid-column: 1 / -1; margin-bottom: 0; }
.hero-copy h1 {
  font-size: clamp(1.7rem, 3.6vw, 2.75rem);
  font-weight: 800;
  letter-spacing: -.5px;
}
.hero-copy h1 .accent { color: var(--gold); }
.hero-copy .lead { margin-top: 16px; color: var(--text-3); font-size: 1rem; max-width: 48ch; }
.hero-cta { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 26px; }
.hero-points { display: flex; flex-wrap: wrap; gap: 18px; margin-top: 26px; }
.hero-points span { display: inline-flex; align-items: center; gap: 7px; font-size: .82rem; color: var(--text-3); }
.hero-points .ico { color: var(--gold); }

/* The rotated gold panel behind the price card — the one piece of pure
   decoration on the page, and the thing that stops the hero reading as a form.
   Nothing else may sit inside this wrapper: the ::before spans its whole box,
   so a sibling above the card gets painted over. */
.hero-card-wrap { position: relative; }
.hero-card-wrap::before {
  content: ''; position: absolute; inset: 18px -14px -14px 18px;
  background: var(--gold);
  border-radius: var(--r-lg);
  transform: rotate(-4deg);
  opacity: .9;
}
.hero-card {
  position: relative;
  background: var(--card);
  border: 1px solid var(--card-border);
  border-radius: var(--r-lg);
  padding: 22px;
  box-shadow: var(--shadow-lg);
}
.hero-card-top { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.hero-card-top .label { display: inline-flex; align-items: center; gap: 7px; }
.hero-price {
  margin-top: 10px;
  display: flex; align-items: baseline; gap: 8px;
}
.hero-price .v { font-size: clamp(2rem, 4.4vw, 2.8rem); font-weight: 800; letter-spacing: -1px; }
.hero-price .cur { font-size: .95rem; font-weight: 600; color: var(--caption); }
.hero-sub { display: flex; align-items: center; gap: 12px; margin-top: 4px; font-size: .85rem; }
.hero-sub .chg { font-weight: 800; }
.hero-sub .of { color: var(--caption); font-size: .8rem; }

.hero-mini { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 18px; }
.hero-mini > div {
  background: var(--muted-surface);
  border: 1px solid var(--card-border);
  border-radius: var(--r-sm);
  padding: 11px 13px;
}
.hero-mini .label { display: block; font-size: .72rem; }
.hero-mini .v { display: block; font-weight: 800; font-size: 1rem; margin-top: 2px; }

/* ── converter ───────────────────────────────────────────────────────── */
/* The same price block, reused inside an ordinary card on the prices page —
   smaller than in the hero, because there it is one of four rather than the
   whole point of the screen. */
.card .hero-price { margin-top: 6px; }
.card .hero-price .v { font-size: 1.5rem; }

.fx-card { display: flex; align-items: center; gap: 12px; }
.fx-art { flex: none; object-fit: contain; }

/* No top margin. It is a grid cell beside the figure cards, and 16px here
   pushed it a notch below the two boxes it sits next to — the gap between it
   and them belongs to the grid. */
.converter {
  background: var(--muted-surface);
  border: 1px solid var(--card-border);
  border-radius: var(--r);
  padding: 16px;
}
.conv-head { display: flex; align-items: center; gap: 8px; }
.conv-head h3 { font-size: .92rem; font-weight: 700; }
.conv-head .ico { color: var(--gold); }
.conv-karats { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }
.conv-fields {
  display: grid; grid-template-columns: 1fr auto 1fr;
  align-items: end; gap: 10px;
  margin-top: 14px;
}
.conv-swap { display: grid; place-items: center; height: 44px; color: var(--gold); opacity: .7; }
.field { display: block; }
.field-label { display: block; font-size: .72rem; color: var(--caption); margin-bottom: 5px; }
.field input {
  width: 100%; height: 44px;
  background: var(--card);
  border: 1px solid var(--card-border);
  border-radius: var(--r-sm);
  color: var(--text);
  font: inherit; font-size: 1rem; font-weight: 800;
  padding: 0 12px;
  text-align: start;
}
.field input:focus { border-color: var(--gold); outline: none; }
.conv-hint { margin-top: 10px; font-size: .72rem; color: var(--caption); }
.conv-usd { margin-top: 10px; font-size: .8rem; color: var(--text-3); }
.conv-usd .num { font-weight: 800; color: var(--text); }

/* ── the full calculator ─────────────────────────────────────────────── */
.calc-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; align-items: start; }
.calc-card { display: flex; flex-direction: column; }
.calc-head { display: flex; align-items: center; gap: 8px; margin-bottom: 14px; }
.calc-head h3 { font-size: .95rem; font-weight: 700; }
.calc-head .ico { color: var(--gold); }
.calc-intro { margin-top: -6px; margin-bottom: 12px; }
.calc-inputs { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }

.calc-table { width: 100%; border-collapse: collapse; margin-top: 14px; }
.calc-table th, .calc-table td { text-align: start; padding: 9px 8px; font-size: .82rem; }
.calc-table thead th {
  font-size: .68rem; font-weight: 600; color: var(--caption);
  border-bottom: 1px solid var(--divider);
}
.calc-table tbody th { font-weight: 700; white-space: nowrap; }
.calc-table tbody tr + tr th, .calc-table tbody tr + tr td { border-top: 1px solid var(--divider); }
.calc-table td { font-weight: 700; text-align: right; }
.calc-table .calc-weight { color: var(--gold); }

.pl-karats { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }

.pl-out {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px;
  margin-top: 14px;
}
.pl-out > div {
  background: var(--muted-surface);
  border: 1px solid var(--card-border);
  border-radius: var(--r-sm);
  padding: 10px;
}
.pl-out .label { display: block; font-size: .68rem; }
.pl-out .v { display: block; font-weight: 800; font-size: .92rem; margin-top: 3px; }

#pl-save { margin-top: 14px; align-self: flex-start; }

.saved { margin-top: 18px; border-top: 1px solid var(--divider); padding-top: 14px; }
.saved h4 { font-size: .82rem; font-weight: 700; margin-bottom: 10px; }
.saved ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.saved li {
  background: var(--muted-surface);
  border: 1px solid var(--card-border);
  border-radius: var(--r-sm);
  padding: 10px 12px;
}
.saved-head { font-size: .76rem; color: var(--text-3); }
.saved-body { display: flex; align-items: center; gap: 10px; margin-top: 4px; }
.saved-body .num:first-child { font-weight: 800; font-size: .9rem; }
.saved-body .num + .num { font-size: .74rem; font-weight: 700; }
.saved-del {
  margin-inline-start: auto;
  width: 26px; height: 26px; flex: none;
  display: grid; place-items: center;
  border-radius: 8px;
  border: 1px solid var(--card-border);
  background: transparent;
  color: var(--text-3);
  font: inherit; font-size: 1.05rem; line-height: 1;
  cursor: pointer;
}
.saved-del:hover { border-color: var(--error); color: var(--error); }

/* ── karat chips ─────────────────────────────────────────────────────── */
.karats { display: none; align-items: center; flex-wrap: wrap; gap: 8px; margin-bottom: 14px; }
.karats-label { font-size: .78rem; color: var(--caption); margin-inline-end: 2px; }
.chip {
  padding: 7px 16px;
  border-radius: 999px;
  border: 1px solid var(--card-border);
  background: var(--card);
  color: var(--text-3);
  font: inherit; font-size: .82rem; font-weight: 700;
  cursor: pointer;
}
.chip-sm { padding: 5px 13px; font-size: .76rem; }
.chip:hover { border-color: var(--gold); }
.chip[aria-pressed='true'] { background: var(--gold); border-color: var(--gold); color: var(--navy); }

/* ── the price matrix ────────────────────────────────────────────────── */
/* Weights down, karats across. On a desktop the whole thing is visible at
   once, which is the entire point — no scrolling to compare two figures. */
.matrix-scroll { width: 100%; }
.matrix {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0 8px;
  table-layout: fixed;
}
.matrix th, .matrix td { text-align: start; }

/* The header row carries the brand.
 *
 * It was grey text floating above the rows, which made the busiest table on the
 * site read as one undifferentiated block — the customer's note on 2026-08-02
 * asked for a header that is actually distinguishable. It is now a gold band,
 * so it reads as the label strip it is rather than as a first row of data.
 *
 * `border-spacing` puts 8px between every row, which would leave the band
 * floating clear of the table; the negative margin on the cells closes that one
 * gap without disturbing the rows below. */
.matrix thead th {
  padding: 11px 14px;
  font-size: .8rem; font-weight: 800;
  color: var(--navy);
  background: linear-gradient(180deg, var(--gold-soft), var(--gold));
  border-block: 1px solid var(--gold);
}
.matrix thead tr th:first-child {
  border-inline-start: 1px solid var(--gold);
  border-start-start-radius: var(--r);
  border-end-start-radius: var(--r);
}
.matrix thead tr th:last-child {
  border-inline-end: 1px solid var(--gold);
  border-start-end-radius: var(--r);
  border-end-end-radius: var(--r);
}
.matrix thead .k-name { display: block; }
/* On gold, --caption is nearly invisible. These two follow the band's own
   foreground instead, softened rather than recoloured. */
.matrix thead .k-note { display: block; font-size: .66rem; font-weight: 600; opacity: .72; }
.matrix thead .th-weight { font-size: .78rem; }

.matrix tbody th, .matrix tbody td {
  background: var(--card);
  border-block: 1px solid var(--card-border);
  padding: 12px 14px;
  vertical-align: middle;
}
.matrix tbody tr th:first-child {
  border-inline-start: 1px solid var(--card-border);
  border-start-start-radius: var(--r);
  border-end-start-radius: var(--r);
}
.matrix tbody tr td:last-child {
  border-inline-end: 1px solid var(--card-border);
  border-start-end-radius: var(--r);
  border-end-end-radius: var(--r);
}
.matrix tbody tr:hover th, .matrix tbody tr:hover td { border-color: var(--gold); }

.matrix .w-name { display: block; font-size: .9rem; font-weight: 700; }
.matrix .w-note { display: block; font-size: .68rem; color: var(--caption); }

.matrix .cell-price { display: block; font-size: .95rem; font-weight: 800; letter-spacing: -.3px; }
.matrix .cell-chg { display: block; font-size: .68rem; font-weight: 700; }

/* These are .num blocks, so their own direction is ltr — which makes `start`
   mean left and pulls them away from the right-aligned header above them. The
   document is rtl and always will be, so say right and be done. */
.matrix .cell-price,
.matrix .cell-chg { text-align: right; }

.matrix td + td, .matrix thead th + th { border-inline-start: 1px solid var(--divider); }

.table-note {
  margin-top: 14px;
  font-size: .74rem; color: var(--caption);
  border: 1px dashed var(--card-border);
  border-radius: var(--r-sm);
  padding: 10px 14px;
}

.table-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin-top: 18px; }
.table-actions .updated { font-size: .76rem; color: var(--caption); margin-inline-start: auto; }
.table-actions.center { justify-content: center; }

/* ── stats band ──────────────────────────────────────────────────────── */
/* Kept for the pages that still use it; the landing page replaced its copy
   with the advertising slot below on 2026-08-02. */
.stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; }
.stat { text-align: center; padding: 20px 12px; }
.stat .v { font-size: 1.6rem; font-weight: 800; color: var(--gold); }
.stat .k { font-size: .82rem; color: var(--text-3); margin-top: 2px; }

/* ── advertising banners ─────────────────────────────────────────────── */
/* The slot that replaced the stats band. Rounded and carrying the brand's own
   border, so a supplied image sits inside the page rather than on top of it —
   an advertisement that ignores the surrounding design reads as an injected ad
   even when it is ours.

   auto-fit with a floor means one banner spans the row and three share it, with
   no per-count class. The aspect ratio is fixed so the band does not change
   height when the customer uploads a differently-proportioned file; `cover`
   crops rather than letterboxes, which is why the panel asks for roughly 4:1. */
.banners {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 16px;
}
.banner {
  display: block;
  border: 1px solid var(--card-border);
  border-radius: var(--r);
  overflow: hidden;
  background: var(--card);
  transition: border-color .2s ease, transform .2s ease;
}
.banner img { display: block; width: 100%; aspect-ratio: 4 / 1; object-fit: cover; }
a.banner:hover { border-color: var(--gold); transform: translateY(-2px); }
@media (prefers-reduced-motion: reduce) { a.banner:hover { transform: none; } }

/* ── social accounts ─────────────────────────────────────────────────── */
/* Named tiles rather than a row of bare glyphs. On the page somebody opens
   specifically to find an account, a labelled tile is findable and an
   unlabelled icon is a guess.

   Each network's own colour is applied on hover only. At rest the grid is one
   material and reads as part of the site; six brand colours side by side turn
   the section into somebody else's logo wall. */
.social-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 12px;
}
.social-tile {
  display: flex; align-items: center; gap: 12px;
  padding: 14px 16px;
  background: var(--card);
  border: 1px solid var(--card-border);
  border-radius: var(--r);
  color: var(--text-2);
  transition: border-color .2s ease, color .2s ease, transform .2s ease;
}
.social-mark {
  display: grid; place-items: center;
  width: 38px; height: 38px; flex: none;
  border-radius: 11px;
  background: var(--muted-surface);
  color: var(--text-3);
  transition: background .2s ease, color .2s ease;
}
.social-name { font-size: .88rem; font-weight: 700; }

.social-tile:hover { transform: translateY(-2px); color: var(--text); }
.social-tile:hover .social-mark { color: #fff; }

.social-facebook:hover  { border-color: #1877F2; }
.social-facebook:hover  .social-mark { background: #1877F2; }
.social-instagram:hover { border-color: #C13584; }
.social-instagram:hover .social-mark { background: linear-gradient(45deg, #F58529, #DD2A7B, #8134AF); }
.social-telegram:hover  { border-color: #29A9EB; }
.social-telegram:hover  .social-mark { background: #29A9EB; }
.social-whatsapp:hover  { border-color: #25D366; }
.social-whatsapp:hover  .social-mark { background: #25D366; }
.social-tiktok:hover    { border-color: #FE2C55; }
.social-tiktok:hover    .social-mark { background: #010101; }
.social-youtube:hover   { border-color: #FF0000; }
.social-youtube:hover   .social-mark { background: #FF0000; }

@media (prefers-reduced-motion: reduce) { .social-tile:hover { transform: none; } }

/* The footer strip stays icon-only — there is no room for labels there, and the
   accounts are named in full on the contact page. */
.foot-social a:hover { color: var(--gold); }

/* ── the landing page's range card ───────────────────────────────────── */
/* Tabs, headline price, sparkline, then the window's movement, high and low.
   Rendered by the server and repainted by app.js on a tab click; absent
   entirely until there is a series to draw. */
.range-card {
  margin-top: 16px;
  padding: 14px;
  border: 1px solid var(--card-border);
  border-radius: var(--r);
  background: var(--muted-surface);
}

.range-tabs {
  display: flex;
  gap: 4px;
  padding: 3px;
  border-radius: 999px;
  background: var(--surface-2, rgba(255, 255, 255, .04));
}
.range-tab {
  flex: 1;
  padding: 7px 6px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--text-3);
  font: inherit;
  font-size: .74rem;
  font-weight: 700;
  cursor: pointer;
  white-space: nowrap;
  transition: background .2s ease, color .2s ease;
}
.range-tab:hover { color: var(--text); }
.range-tab.is-on { background: var(--gold); color: var(--navy); }

.range-body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  align-items: center;
  gap: 12px;
  margin-top: 14px;
}
.range-price { font-size: 1.25rem; font-weight: 800; letter-spacing: -.4px; color: var(--gold); }
.range-price .num { font-size: 1.35rem; }
.range-label { margin-top: 3px; font-size: .78rem; color: var(--text-2); font-weight: 600; }
.range-sub   { margin-top: 1px; font-size: .68rem; color: var(--caption); }

/* preserveAspectRatio:none on the <svg> lets one drawing stretch to whatever
   width the card gives it, so no resize listener has to recompute anything.
   The line keeps its weight because it is drawn with vector-effect. */
/* `position: relative` so the readout has something to be absolute against,
 * and `pan-y` for the same reason the full chart needs it: without naming the
 * axis we want, the browser claims a horizontal drag for its own gestures and
 * stops sending pointer moves, so the value follows a finger briefly and then
 * freezes. This card sits above the fold on the landing page, so leaving
 * vertical scrolling with the browser matters more here than anywhere. */
.range-chart {
  min-width: 0;
  position: relative;
  direction: ltr;
  touch-action: pan-y;
  cursor: crosshair;
}
.spark { display: block; width: 100%; height: 84px; }

/* The card's plot is 84px against the full chart's 240, so the label is
   tightened to match — at the full size it covers a third of the line. */
.range-chart .chart-tip { top: 2px; padding: 3px 7px; font-size: .68rem; }
.range-chart .chart-tip-time { font-size: .62rem; }
.range-chart .chart-dot { width: 8px; height: 8px; margin: -4px 0 0 -4px; }

.range-stats {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--divider);
  text-align: center;
}
.range-stats .v { display: block; font-size: .82rem; font-weight: 800; }
.range-stats .k { display: block; font-size: .66rem; color: var(--caption); margin-top: 1px; }

@media (max-width: 520px) {
  /* Below this the two columns leave the sparkline about 110px wide, which is
     not a chart. It goes under the figure and gets the full width instead. */
  .range-body { grid-template-columns: 1fr; }
  .spark { height: 70px; }
  .range-tab { font-size: .68rem; padding: 7px 4px; }
}

/* ── the price chart ─────────────────────────────────────────────────── */
.chart-card { padding: 18px 20px 14px; }
.chart-ranges { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 14px; }

/* Fixed height so the card does not jump between "loading", "no data" and the
   drawing itself — three states one visitor can see in a second. */
.chart-box {
  position: relative;
  min-height: 260px;
  display: flex; flex-direction: column; justify-content: center;
}
/* preserveAspectRatio:none on the <svg> means the drawing stretches to whatever
   width it is given, so no resize listener has to recompute coordinates. The
   line keeps its weight because it is drawn with vector-effect. */
.chart-svg { width: 100%; height: 240px; display: block; }
.chart-empty { text-align: center; color: var(--caption); font-size: .85rem; }

/* ── reading a value off the chart ─────────────────────────────────────
 *
 * Added 2026-09-21. The line said the price moved; it never said to what.
 *
 * `touch-action: pan-y` is the load-bearing line. The default lets the browser
 * claim a horizontal drag for its own gestures and stop sending pointer moves,
 * so on a phone the readout would follow the finger for a moment and then
 * freeze. Naming `pan-y` gives horizontal movement to us and leaves vertical
 * scrolling with the browser — so the page still scrolls through the chart,
 * which matters because it sits mid-page and is wider than a thumb.
 *
 * `direction: ltr` for the same reason the axis row has it: the plot runs
 * oldest-left, and the overlay is positioned from the left edge.
 */
.chart-plot {
  position: relative;
  direction: ltr;
  touch-action: pan-y;
  cursor: crosshair;
}

/* All three are `pointer-events: none`. They sit under the pointer by
   definition, and without this the element being hovered would be the dot
   rather than the plot — which stalls the readout the instant it catches up
   with the finger. */
.chart-cursor,
.chart-dot,
.chart-tip { pointer-events: none; }

.chart-cursor {
  position: absolute;
  top: 0; bottom: 0;
  width: 1px;
  opacity: .45;
}

/* Centred on its coordinate by pulling back half its own size, so the dot
   lands *on* the sample rather than hanging below and to the right of it. */
.chart-dot {
  position: absolute;
  width: 10px; height: 10px;
  margin: -5px 0 0 -5px;
  border-radius: 50%;
  box-shadow: 0 0 0 3px var(--surface);
}

.chart-tip {
  position: absolute;
  top: 6px;
  transform: translateX(-50%);
  display: flex; flex-direction: column; align-items: center; gap: 1px;
  padding: 5px 10px;
  border-radius: 8px;
  background: var(--surface);
  border: 1px solid var(--card-border);
  box-shadow: 0 6px 18px rgb(0 0 0 / .18);
  white-space: nowrap;
  font-size: .72rem;
  line-height: 1.25;
}
.chart-tip-value { font-weight: 800; color: var(--text); }
.chart-tip-time { color: var(--caption); font-size: .66rem; }

/* `direction: ltr`, and it is not cosmetic.
 *
 * The plot runs oldest-left to newest-right, which is how a time axis reads in
 * every language including this one. The labels are a flex row, and in the RTL
 * document that row lays out right-to-left — so the *oldest* date printed first
 * landed under the *newest* end of the line, and the chart said the price had
 * risen when it had fallen. Same class of bug as the `.num` note in CLAUDE.md.
 * The children are already `.num`, so their digits are unaffected. */
.chart-axis {
  direction: ltr;
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-top: 6px;
  font-size: .7rem; color: var(--caption);
}
.chart-axis .chart-range { color: var(--text-3); font-weight: 700; }

@media (max-width: 620px) {
  .chart-svg { height: 190px; }
  .chart-box { min-height: 210px; }
  /* The two date labels are the ones that survive; the range in the middle is
     the first thing to go when there is no room for all three. */
  .chart-axis .chart-range { display: none; }
}

/* ── the market strip: the ounce and the dollar ──────────────────────── */
/* The two inputs every price on the site is built from, side by side. The
   ounce is first in source order, which in this RTL layout puts it on the
   right — where the calculation starts. They stack on a narrow screen rather
   than shrinking into two unreadable columns. */
/* 16px, the same gap every other grid on the site uses. It was 12 here, which
   on the prices page — where the block below splits the shell in exactly the
   same two halves — left the strip's inner edge 2px off the one under it. */
.market-strip {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
  margin-bottom: 16px;
}
@media (max-width: 560px) {
  .market-strip { grid-template-columns: 1fr; }
}

/* Framed, because these are the one pair of figures in the hero that do not
   move minute to minute — inside a card headed "live price" they implied that
   they did. */
.usd-strip {
  display: flex; align-items: center; gap: 14px;
  padding: 14px 16px;
  /* The gap belongs to .market-strip now; a margin here would double it. */
  background: var(--card);
  border: 1px solid var(--gold);
  border-radius: var(--r);
}
.usd-art { width: 52px; height: auto; flex: none; }
.usd-body { min-width: 0; }
.usd-strip .label { font-size: .74rem; color: var(--caption); }
.usd-value { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; margin-top: 2px; }
.usd-value .v { font-size: 1.55rem; font-weight: 800; letter-spacing: -.5px; }
.usd-value .cur { font-size: .72rem; color: var(--caption); }
/* The ounce's day, beside the ounce. Colour comes from .up/.down, so this only
   sizes it — and it is the last item in a wrapping flex row, which is what lets
   it drop under the figure on a narrow phone instead of squeezing it. */
.usd-value .chg { font-size: .74rem; font-weight: 800; white-space: nowrap; }
/* The span is always in the DOM so the poll has something to write into; on a
   day with nothing to report it must not still spend the row's 8px gap. */
.usd-value .chg:empty { display: none; }
/* Which rate priced the gold below. Two rates exist about 14% apart, and a page
   that shows one while pricing from the other gives the reader two figures that
   do not divide out. */
.usd-note { display: block; margin-top: 3px; font-size: .7rem; color: var(--caption); line-height: 1.5; }
.usd-note b { color: var(--text-3); }

/* ── the prices page's lead block ────────────────────────────────────── */
/* The strip, then the figure cards beside the converter, with one 16px gap in
   every direction and the same column split as the strip above them.
   Deliberately its own pair of classes rather than the shared `.grid-2`: this
   block needs its two halves to end level, and `.grid-2` is used on pages
   where stretching a column would be wrong. */
.price-lead {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
  align-items: stretch;
}

/* The converter is the taller half, so the figures take their height from it:
   `1fr` rows divide whatever the row ends up being, and the two columns finish
   on the same line instead of one stopping 30px short. The cards centre their
   contents so that borrowed height reads as room to breathe rather than as a
   card whose text ran out. */
.price-figures {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-auto-rows: 1fr;
  gap: 16px;
}
.price-figures .card { display: flex; flex-direction: column; justify-content: center; }

/* Three cards in a two-column grid leave a hole, and it falls right beside the
   converter where it is impossible to miss. The world ounce used to fill it and
   now lives in the strip, so the last card takes the row instead. */
.price-figures .card:last-child { grid-column: 1 / -1; }

@media (max-width: 880px) {
  .price-lead { grid-template-columns: 1fr; }
}
@media (max-width: 560px) {
  .price-figures { grid-template-columns: 1fr; grid-auto-rows: auto; }
}

/* ── feature / step grids ────────────────────────────────────────────── */
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
.grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; }
.grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; }

.feature { display: flex; flex-direction: column; gap: 8px; }
.feature .badge {
  width: 42px; height: 42px; border-radius: 12px;
  display: grid; place-items: center;
  background: var(--glow); color: var(--gold);
}
.feature h3 { font-size: .95rem; font-weight: 700; }
.feature p { font-size: .84rem; color: var(--text-3); }

.step { position: relative; padding-top: 8px; }
.step .n {
  width: 34px; height: 34px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--gold); color: var(--navy);
  font-weight: 800; font-size: .9rem;
}
.step h3 { font-size: .95rem; font-weight: 700; margin-top: 10px; }
.step p { font-size: .84rem; color: var(--text-3); margin-top: 4px; }

/* ── app section ─────────────────────────────────────────────────────── */
.app-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 48px; align-items: center; }
.phone {
  position: relative;
  width: min(280px, 78vw);
  margin-inline: auto;
  border: 9px solid var(--surface);
  border-radius: 34px;
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  background: var(--surface);
}
/* height:auto is not optional here. The <img> carries width/height attributes
   so the box is reserved before it loads, and those apply as a presentational
   height — overriding only the width stretches the screenshot to the literal
   1280px instead of scaling it. */
.phone img { display: block; width: 100%; height: auto; }
/* One capture per theme, swapped the way the header logo is: dark by default,
   since that is the theme a page starts in before the script sets one. */
.phone img.for-light { display: none; }
:root[data-theme='light'] .phone img.for-dark { display: none; }
:root[data-theme='light'] .phone img.for-light { display: block; }
.app-list { display: grid; gap: 12px; margin-top: 20px; list-style: none; padding: 0; }
.app-list li { display: flex; gap: 10px; align-items: flex-start; font-size: .88rem; color: var(--text-3); }
.app-list .ico { color: var(--gold); flex: none; margin-top: 4px; }
.app-cta { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin-top: 24px; }

/* Apple's App Store badge. Its size and spacing are Apple's rules, not ours:
   never under 40px tall, and clear space of a quarter of its height — 12px at
   48px, which is .app-cta's gap. See app_store_badge() in src/layout.php. */
.store-badge { display: inline-flex; flex: none; line-height: 0; border-radius: 9px; }
.store-badge img { height: 48px; width: auto; }
.store-badge:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }
.app-meta { margin-top: 10px; font-size: .76rem; color: var(--caption); }

/* Sideloading instructions. The app is not on Play, so the "unknown sources"
   prompt is the single biggest place a download is abandoned — spelling it out
   is worth the space. */
.install-steps {
  margin-top: 22px;
  background: var(--card);
  border: 1px solid var(--card-border);
  border-radius: var(--r);
  padding: 16px;
}
.install-steps h3 { display: flex; align-items: center; gap: 8px; font-size: .9rem; font-weight: 700; }
.install-steps h3 .ico { color: var(--gold); }
.install-steps p { margin-top: 8px; font-size: .84rem; color: var(--text-3); }
.install-steps ol { margin: 10px 0 0; padding-inline-start: 20px; font-size: .84rem; color: var(--text-3); }
.install-steps li { margin-bottom: 6px; }
.install-steps strong { color: var(--text-2); }
.install-steps .app-meta { margin-top: 12px; }

/* ── FAQ ─────────────────────────────────────────────────────────────── */
.faq { display: grid; gap: 10px; }
.faq details {
  background: var(--card);
  border: 1px solid var(--card-border);
  border-radius: var(--r);
  padding: 4px 16px;
}
.faq summary {
  list-style: none;
  cursor: pointer;
  padding: 12px 0;
  font-size: .92rem; font-weight: 700;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: '+';
  color: var(--gold); font-size: 1.3rem; font-weight: 700; line-height: 1;
  flex: none;
}
.faq details[open] summary::after { content: '−'; }
.faq details[open] summary { color: var(--gold); }
.faq .answer { padding: 0 0 14px; font-size: .87rem; color: var(--text-3); border-top: 1px solid var(--divider); padding-top: 12px; }
.faq .answer p + p { margin-top: 10px; }
.faq .answer ul { margin: 10px 0 0; padding-inline-start: 20px; }
.faq .answer li { margin-bottom: 6px; }

/* ── long-form content ───────────────────────────────────────────────── */
.prose { font-size: .92rem; color: var(--text-3); }
.prose h2 { font-size: 1.2rem; color: var(--text); margin-top: 32px; }
.prose h3 { font-size: 1rem; color: var(--text); margin-top: 22px; }
.prose h2:first-child, .prose h3:first-child { margin-top: 0; }
.prose p { margin-top: 12px; }
.prose ul, .prose ol { margin-top: 12px; padding-inline-start: 22px; }
.prose li { margin-bottom: 8px; }
.prose strong { color: var(--text-2); }
.prose a { color: var(--gold); text-decoration: underline; text-underline-offset: 3px; }

/* The division that turns an ounce into a gram, set apart from the sentence
   explaining it. Centred rather than indented: it is one line and reads as a
   statement, not as a quoted block. */
.prose .formula {
  text-align: center;
  padding: 12px 16px;
  margin-top: 14px;
  background: var(--muted-surface);
  border: 1px dashed var(--card-border);
  border-radius: var(--r-sm);
  color: var(--text-2); font-weight: 700;
}
.prose .prose-closing {
  margin-top: 26px;
  text-align: center;
  font-size: 1.02rem; font-weight: 700; color: var(--gold);
}

.page-head { padding-block: 44px 12px; }
.page-head h1 { font-size: clamp(1.5rem, 3vw, 2.2rem); font-weight: 800; }
.page-head p { margin-top: 10px; color: var(--text-3); }
.crumbs { font-size: .76rem; color: var(--caption); margin-bottom: 10px; }
.crumbs a:hover { color: var(--gold); }

/* ── contact ─────────────────────────────────────────────────────────── */
.contact-card { display: flex; gap: 14px; align-items: flex-start; }
.contact-card .badge {
  width: 40px; height: 40px; border-radius: 12px; flex: none;
  display: grid; place-items: center;
  background: var(--glow); color: var(--gold);
}
.contact-card h3 { font-size: .92rem; font-weight: 700; }
.contact-card p { font-size: .85rem; color: var(--text-3); margin-top: 2px; }
.contact-card a { color: var(--gold); }

/* ── error / empty ───────────────────────────────────────────────────── */
.error-state {
  margin-block: 30px;
  text-align: center;
  color: var(--text-3);
  display: grid; gap: 12px; justify-items: center;
  border: 1px dashed var(--card-border);
  border-radius: var(--r);
  padding: 32px 20px;
}

/* ── footer ──────────────────────────────────────────────────────────── */
.foot {
  margin-top: 60px;
  background: var(--muted-surface);
  border-top: 1px solid var(--divider);
  padding-top: 44px;
}
.foot-grid {
  display: grid;
  grid-template-columns: 1.6fr 1fr 1fr 1.1fr;
  gap: 32px;
  padding-bottom: 32px;
}
.foot-col h3 { font-size: .88rem; font-weight: 700; margin-bottom: 12px; }
.foot-col ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 9px; }
.foot-col a { font-size: .84rem; color: var(--text-3); }
.foot-col a:hover { color: var(--gold); }
.foot-text { margin-top: 12px; font-size: .82rem; color: var(--text-3); max-width: 44ch; }
.foot-contact li { display: flex; align-items: center; gap: 8px; font-size: .84rem; color: var(--text-3); }
.foot-contact .ico { color: var(--gold); flex: none; }
.foot-social { display: flex; gap: 8px; margin-top: 14px; }
.foot-social a {
  width: 36px; height: 36px; border-radius: 10px;
  display: grid; place-items: center;
  border: 1px solid var(--card-border); color: var(--text-3);
}
.foot-social a:hover { color: var(--gold); border-color: var(--gold); }

.foot-bottom {
  border-top: 1px solid var(--divider);
  padding-block: 18px;
  padding-bottom: calc(18px + env(safe-area-inset-bottom));
  display: flex; flex-wrap: wrap; gap: 8px; justify-content: space-between;
  font-size: .76rem; color: var(--caption);
}

/* ── breakpoints ─────────────────────────────────────────────────────── */

@media (max-width: 1000px) {
  .nav { display: none; }
  .burger { display: grid; }
  .hero-grid, .app-grid { gap: 40px; }
  .foot-grid { grid-template-columns: 1fr 1fr; }
  .grid-4 { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 880px) {
  .hero { padding-block: 40px 36px; }
  .hero-grid { grid-template-columns: 1fr; }
  /* In one column the headline leads and the strip drops back between the copy
     and the card, where it was before. It only comes first in source so that it
     can take the whole first row of the two-column layout. */
  .hero-copy { order: -1; }
  .hero-card-wrap::before { inset: 14px -10px -10px 14px; }
  .app-grid { grid-template-columns: 1fr; }
  .grid-3 { grid-template-columns: repeat(2, 1fr); }
  .stats { grid-template-columns: repeat(2, 1fr); }
  .section { padding-block: 44px; }

  /* The phone gets one karat at a time, chosen with the chips. Same table,
     same cells — the columns for the other karats are simply not shown. */
  .karats { display: flex; }
  .matrix { table-layout: auto; }
  .matrix .k:not(.is-on) { display: none; }
  .matrix thead .k-note { display: none; }
  .matrix tbody td:last-of-type,
  .matrix tbody td.is-on {
    border-inline-end: 1px solid var(--card-border);
    border-start-end-radius: var(--r);
    border-end-end-radius: var(--r);
  }
  /* Two columns now — weight on the right, the chosen karat on the left — so
     the figures sit against the far edge, the way the app lists them. */
  .matrix .cell-price,
  .matrix .cell-chg,
  .matrix thead th.k { text-align: left; }
}

@media (max-width: 880px) {
  .calc-grid { grid-template-columns: 1fr; }
}

/* ── the making-charge calculator ────────────────────────────────────── */
/* One block of markup, three homes: the /calculator page, the sheet behind the
   floating button, and — with scripting off — a plain form that posts to the
   page. Nothing below is aware of which one it is in. */

.wc-page {
  display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
  gap: 16px; align-items: start;
}
.wc-aside { display: grid; gap: 16px; }
.wc-aside-head { display: flex; align-items: center; gap: 8px; font-size: .95rem; font-weight: 700; }
.wc-aside-head .ico { color: var(--gold); }
.wc-steps { margin-top: 12px; padding-inline-start: 18px; display: grid; gap: 9px; }
.wc-steps li { font-size: .84rem; color: var(--text-3); line-height: 1.75; }
.wc-steps b { color: var(--text); }
.wc-aside-app .app-cta { margin-top: 12px; display: flex; flex-wrap: wrap; gap: 10px; }
/* 40px, Apple's floor, with the 10px gap as its quarter-height clear space. */
.wc-aside-app .store-badge img { height: 40px; }

.wc { display: grid; gap: 14px; }
.wc-field-row { display: grid; grid-template-columns: 1fr auto; gap: 10px; align-items: end; }
.wc-unit { min-width: 132px; }
.wc select {
  width: 100%; height: 44px;
  background: var(--card); border: 1px solid var(--card-border);
  border-radius: var(--r-sm); color: var(--text);
  font: inherit; font-size: .92rem; font-weight: 700;
  padding: 0 10px;
}
.wc select:focus { border-color: var(--gold); outline: none; }

.wc-chips { border: 0; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: 6px; }
.wc-chips legend { float: inline-start; width: 100%; }

/* The radio is the control and the span is the chip. Styling the label with
   :has() would read better and would leave every browser without it unable to
   show which karat is selected — the input is off-screen, so an unstyled state
   is not "plain", it is blank. The sibling selector works everywhere. */
.wc-chip { display: inline-flex; cursor: pointer; }
.wc-chip input { position: absolute; width: 1px; height: 1px; opacity: 0; }
.wc-chip input:checked + .chip {
  background: var(--gold); border-color: var(--gold); color: var(--navy);
}
.wc-chip input:focus-visible + .chip { outline: 2px solid var(--gold); outline-offset: 2px; }

.wc-margin {
  border: 1px solid var(--card-border); border-radius: var(--r-sm);
  padding: 10px 12px; background: var(--muted-surface);
}
.wc-margin summary { cursor: pointer; font-size: .82rem; font-weight: 700; }
.wc-margin .wc-optional { color: var(--caption); font-weight: 400; }
.wc-margin .wc-field-row { margin-top: 12px; }

/* The submit button exists for the no-JavaScript path. With the script running
   the invoice follows the form, and a button that resubmits an unchanged form
   is a button that appears to do nothing. */
.wc-live .wc-submit { display: none; }
.wc-busy .wc-invoice { opacity: .55; transition: opacity .15s; }

/* ── the invoice ─────────────────────────────────────────────────────── */

.wc-invoice {
  margin-top: 4px; padding: 14px;
  background: var(--muted-surface);
  border: 1px solid var(--card-border);
  border-radius: var(--r);
}
.wc-invoice.wc-empty, .wc-invoice.wc-error { color: var(--caption); font-size: .82rem; }
.wc-invoice.wc-error { border-color: var(--error); color: var(--error); }

.wc-invoice-head { display: flex; align-items: center; gap: 8px; font-size: .9rem; font-weight: 700; }
.wc-invoice-head .ico { color: var(--gold); }

.wc-lines { margin-top: 12px; display: grid; gap: 2px; }
.wc-line {
  display: flex; align-items: baseline; justify-content: space-between; gap: 14px;
  padding: 9px 0; border-bottom: 1px dashed var(--divider);
}
.wc-line dt { font-size: .84rem; color: var(--text-3); display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px; }
.wc-line dt .ico { color: var(--gold); flex: none; }
.wc-line dd { font-size: .95rem; font-weight: 800; white-space: nowrap; text-align: left; }
.wc-sub { display: block; width: 100%; font-size: .7rem; color: var(--caption); font-weight: 400; }

.wc-line.wc-sub-total dt, .wc-line.wc-sub-total dd { color: var(--text-3); font-weight: 700; }

/* The line the whole page is for. Bigger, gold, and no dashed rule under it —
   there is nothing after it to separate from. */
.wc-total {
  margin-top: 4px; padding-top: 13px; border-bottom: 0;
  border-top: 2px solid var(--gold);
}
.wc-total dt { font-size: .92rem; font-weight: 800; color: var(--text); }
.wc-total dd { font-size: 1.5rem; color: var(--gold); }
.wc-total .wc-cur { font-size: .8rem; color: var(--text-3); font-weight: 700; }

.wc-basis { margin-top: 12px; font-size: .72rem; color: var(--caption); line-height: 1.9; }
.wc-basis b { color: var(--text-3); }
.wc-tag {
  display: inline-block; margin-inline-end: 6px; padding: 2px 8px;
  border-radius: 999px; background: var(--glow); color: var(--gold);
  font-size: .68rem; font-weight: 700;
}
.wc-legal { margin-top: 8px; font-size: .7rem; color: var(--caption); line-height: 1.85; }

.wc-actions {
  margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--divider);
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px;
}
.wc-ref { font-size: .68rem; color: var(--caption); }
.wc-ref b { color: var(--text-3); letter-spacing: .5px; }

/* ── the floating button ─────────────────────────────────────────────── */
/* Labelled, not a bare glyph. This is the feature the customer most wants
   found, and a floating circle with an icon in it is a guess the visitor has
   to make.

   **Physical `right`, deliberately, and not a logical property.** The mirroring
   rule — a floating button belongs at the inline *end*, which in RTL is the
   left — is what Material does and what `inset-inline-end` would give, and it
   is wrong for this audience: the customer asked for the bottom right and that
   is where an Arabic-speaking user reaches. This site is Arabic-only by a
   project decision that is not going to change, so the physical side is the
   honest way to say it. The app's Scaffold is pinned to the same corner with
   `FloatingActionButtonLocation.startFloat`. */

.wc-fab {
  position: fixed; z-index: 60;
  inset-block-end: max(18px, env(safe-area-inset-bottom));
  right: 18px;
  display: inline-flex; align-items: center; gap: 8px;
  padding: 13px 20px; border-radius: 999px;
  background: var(--gold); color: var(--navy);
  font-size: .86rem; font-weight: 800;
  box-shadow: var(--shadow-lg);
  transition: transform .15s, background .15s;
}
.wc-fab:hover { background: var(--gold-soft); transform: translateY(-2px); }
.wc-fab:active { transform: translateY(0); }
@media (prefers-reduced-motion: reduce) { .wc-fab:hover { transform: none; } }

/* ── the sheet ───────────────────────────────────────────────────────── */
/* A <dialog>, for the modal behaviour, the focus trap and Escape. Anchored to
   the bottom on a phone the way the app's bottom sheet is; centred once there
   is room for it to be a panel rather than a sheet. */

.wc-sheet {
  width: min(560px, 100%);
  max-height: 88dvh;
  margin: auto auto 0;
  padding: 0;
  border: 1px solid var(--card-border);
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  background: var(--card);
  color: var(--text);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}
.wc-sheet::backdrop { background: rgba(0, 0, 0, .55); }
.wc-sheet-head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 14px 16px; border-bottom: 1px solid var(--divider);
  position: sticky; top: 0; background: var(--card); z-index: 1;
}
.wc-sheet-head h2 { display: flex; align-items: center; gap: 8px; font-size: 1rem; font-weight: 800; }
.wc-sheet-head .ico { color: var(--gold); }
.wc-sheet-body { padding: 16px; overflow-y: auto; max-height: calc(88dvh - 58px); }
.wc-sheet-foot { text-align: center; margin-top: 14px; }
.wc-sheet-foot a { color: var(--gold); font-weight: 700; }

@media (min-width: 700px) {
  .wc-sheet { margin: auto; border-radius: var(--r-lg); }
}

/* ── toast ───────────────────────────────────────────────────────────── */
/* One element for the whole site — the share button, the copy button and the
   invoice's own copy all report through it. */

.toast {
  position: fixed; z-index: 90;
  inset-block-end: 88px;
  inset-inline: 0;
  margin-inline: auto;
  width: max-content; max-width: calc(100% - 32px);
  padding: 11px 20px; border-radius: 999px;
  background: var(--navy); color: var(--cream);
  border: 1px solid var(--gold);
  font-size: .82rem; font-weight: 700;
  box-shadow: var(--shadow-lg);
  opacity: 0; transform: translateY(8px);
  transition: opacity .2s, transform .2s;
  pointer-events: none;
}
.toast.on { opacity: 1; transform: translateY(0); }
@media (prefers-reduced-motion: reduce) { .toast { transition: none; } }


/* ── sign-in and the account pages ───────────────────────────────────────
   Added 2026-09-20 with the first state this site has ever had. Nothing here
   is new visual language: the cards, the gold button and the palette tokens
   are the ones already on the prices page, because a sign-in screen that
   looks like a different product is a sign-in screen people abandon.

   `.field` already existed for the converter, where the label is a separate
   `.field-label` span. These forms wrap the input in the label instead — one
   element, no `for`/`id` pair to keep in step — so the first child gets the
   same treatment the old class gave that span. */

.auth-shell { display: grid; grid-template-columns: 1.15fr 1fr; gap: 18px; align-items: start; }
.auth-card h2, .auth-aside h3 { font-size: 1rem; font-weight: 800; margin-bottom: 10px; }
.auth-aside h3 + ul { margin-bottom: 18px; }
.auth-card .btn-block { margin-top: 18px; }
.auth-fine { margin-top: 14px; font-size: .74rem; color: var(--caption); line-height: 1.9; }
.auth-fine a { color: var(--gold); }

/* The sign-in button carries Google's own four-colour mark, so it must not
   inherit the gold button's text colour into the SVG. */
#google-signin .ico { flex: none; }

/* Google's sign-in button, to Google's specification and not to ours.

   Every value below is published rather than chosen: the two permitted
   theme pairs, the 4px radius, the 20px mark, the 12px gap and Roboto Medium.
   None of it uses the site's palette tokens, deliberately — a later change to
   --gold or --card must not drift this button out of compliance, which is
   exactly what would happen if it inherited them.

   The Arabic renders in the page's own face because Roboto carries no Arabic
   glyphs and the fallback takes over; "Google" stays Latin, which is itself a
   requirement. */
/* Where Google renders its own button.
 *
 * The contents are Google's — an iframe-backed widget we may not restyle, and
 * the branding guidelines are the reason we would not want to. All this does
 * is centre it and reserve the height, so the card does not jump when the
 * widget arrives a moment after the rest of the page.
 *
 * `:empty` keeps the reservation only while it is empty: once the fallback
 * button is revealed instead, the slot collapses rather than leaving a gap
 * above it.
 */
/* The same 18px the hand-built button carries, so the gap above the button is
 * identical whichever of the two is on screen. It only became visible once the
 * rendered one appeared: an unstyled slot sat flush against the paragraph. */
.gsi-slot { display: flex; justify-content: center; margin-top: 18px; }
.gsi-slot:empty { min-height: 0; margin-top: 0; }

/*
 * Round Google's button ourselves.
 *
 * `shape: 'pill'` is passed to `renderButton` and the *standard* button honours
 * it. The **personalized** one does not — the variant carrying the visitor's
 * name and avatar, which Google renders inside an iframe it controls. That
 * variant also ignores `theme: 'filled_black'`, so on a dark card it arrives as
 * a white rectangle with square corners: the one shape nothing else on this
 * site has. Reported 2026-09-21.
 *
 * Nothing inside that frame can be styled — it is Google's document, and that
 * is the point of it. But the element holding it is ours, so clipping it is the
 * one lever left. A white pill on the dark card reads as a Google button; a
 * white rectangle reads as something that failed to load.
 *
 * Only the corners are touched. The colour, the wordmark, the typeface and the
 * minimum size all stay exactly as Google draws them, which is what the
 * branding guidelines actually require.
 */
.gsi-slot > * {
  border-radius: 999px;
  overflow: hidden;
  /* Safari ignores `overflow` on a transformed descendant unless the clip is
   * promoted; this is the usual coaxing. */
  isolation: isolate;
}

.gsi-button {
  display: flex; align-items: center; justify-content: center;
  gap: 12px;
  width: 100%;
  min-height: 44px;
  padding: 0 12px;
  margin-top: 18px;
  background: #FFFFFF;
  border: 1px solid #747775;
  border-radius: 4px;
  cursor: pointer;
  font: inherit;
  transition: background .15s ease, box-shadow .15s ease;
}
.gsi-button:hover { background: #F7F8F8; box-shadow: 0 1px 2px rgba(0,0,0,.2); }
.gsi-button:disabled { opacity: .5; cursor: default; }
.gsi-mark { display: flex; width: 20px; height: 20px; flex: none; }
.gsi-mark svg { width: 20px; height: 20px; }
.gsi-text {
  font-family: Roboto, 'Cairo', system-ui, sans-serif;
  font-size: .95rem;
  font-weight: 500;
  color: #1F1F1F;
}

/* Google's dark theme, for our dark theme. Two of the three permitted styles;
   the neutral grey one is not used here. */
:root:not([data-theme='light']) .gsi-button {
  background: #131314;
  border-color: #8E918F;
}
:root:not([data-theme='light']) .gsi-button:hover { background: #1E1F20; }
:root:not([data-theme='light']) .gsi-text { color: #E3E3E3; }

/*
 * Sign in with Apple, to Apple's Human Interface Guidelines.
 *
 * Only black, white, or white with a black outline; the mark in one colour;
 * 44px at least; a corner radius of up to half the height — which is exactly a
 * pill, so it takes the same shape as the Google button above it rather than
 * sitting under it as the odd one out. The same width as Google's (up to the
 * 400px `renderButton` accepts), because Apple asks for its button to be no
 * smaller than any other sign-in button beside it. Not our gold, ever.
 */
.apple-button {
  display: flex; align-items: center; justify-content: center;
  gap: 8px;
  width: 100%; max-width: 400px;
  min-height: 44px;
  padding: 0 16px;
  margin: 12px auto 0;
  background: #000000;
  color: #FFFFFF;
  border: 1px solid #000000;
  border-radius: 22px;
  cursor: pointer;
  font: inherit;
}
.apple-button:disabled { opacity: .5; cursor: default; }
.apple-button:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }
.apple-mark { display: flex; width: 18px; height: 18px; flex: none; }
.apple-mark svg { width: 18px; height: 18px; }
/* Apple's own text, in a Latin face for "Apple"; Cairo carries the Arabic. */
.apple-text { font-family: -apple-system, 'SF Pro Text', 'Cairo', system-ui, sans-serif; font-size: .95rem; font-weight: 500; }

/* White on our dark theme: a black button on navy is the case Apple's white
   style exists for. */
:root:not([data-theme='light']) .apple-button { background: #FFFFFF; color: #000000; border-color: #FFFFFF; }

.signin-status { margin-top: 12px; font-size: .82rem; color: var(--text-3); }
.signin-status.bad { color: var(--error); }

.tick-list { list-style: none; padding: 0; margin: 0; display: grid; gap: 8px; }
.tick-list li { display: flex; align-items: center; gap: 8px; font-size: .85rem; }
.tick-list .ico { flex: none; color: var(--gold); }
.tick-list.muted li { color: var(--text-3); }
.tick-list.muted .ico { color: var(--caption); }

/* ── the account page ────────────────────────────────────────────────── */
.account-grid { display: grid; grid-template-columns: 1.3fr 1fr; gap: 18px; align-items: start; }
.account-side { display: grid; gap: 18px; }
.account-grid h2 { display: flex; align-items: center; gap: 8px; font-size: 1rem; font-weight: 800; margin-bottom: 14px; }
.account-grid h2 .ico { color: var(--gold); }
.account-grid h3 { font-size: .9rem; font-weight: 700; margin-bottom: 6px; }

.field + .field, .field-row + .field, .field + .field-row { margin-top: 14px; }
.field > span { display: block; font-size: .72rem; color: var(--caption); margin-bottom: 5px; }
.field > span em { font-style: normal; }
.field small { display: block; margin-top: 6px; font-size: .7rem; color: var(--caption); line-height: 1.7; }
.field select {
  width: 100%; height: 44px;
  background: var(--card);
  border: 1px solid var(--card-border);
  border-radius: var(--r-sm);
  color: var(--text);
  font: inherit; font-size: .95rem; font-weight: 700;
  padding: 0 12px;
}
.field select:focus { border-color: var(--gold); outline: none; }
.field input:disabled, .field select:disabled { opacity: .55; }
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; align-items: start; }
/* `.field + .field` is for fields stacked in a column. Side by side, it pushed
   the second one 14px down and the two captions stopped lining up. */
.field-row > .field { margin-top: 0; }
.field[hidden] { display: none; }

/* The phone: a small dial-code button and the number, one bordered box.
   The <select> is invisible and laid over the code, so tapping «+964» opens
   the native list — names and all — while the box shows only the code. */
.phone-group {
  display: flex; align-items: stretch; height: 44px;
  background: var(--card);
  border: 1px solid var(--card-border);
  border-radius: var(--r-sm);
  overflow: hidden;
}
.phone-group:focus-within { border-color: var(--gold); }
.phone-group.is-bad { border-color: var(--error); }
.phone-group.is-ok { border-color: var(--success); }
.phone-cc {
  position: relative; flex: none;
  display: flex; align-items: center; gap: 6px;
  padding: 0 10px;
  border-inline-end: 1px solid var(--card-border);
  background: var(--muted-surface);
  font-weight: 800; font-size: .92rem; color: var(--text);
}
.phone-caret {
  width: 6px; height: 6px; margin-top: -3px;
  border: solid var(--caption); border-width: 0 1.5px 1.5px 0;
  transform: rotate(45deg);
}
.phone-cc select {
  position: absolute; inset: 0; width: 100%; height: 100%;
  opacity: 0; cursor: pointer;
  border: 0; padding: 0;
}
.phone-group input {
  flex: 1; min-width: 0; height: auto;
  border: 0; border-radius: 0; background: transparent;
  text-align: left;
}
.phone-group input:focus { border: 0; }
.phone-count {
  flex: none; align-self: center; padding: 0 10px;
  font-size: .72rem; font-weight: 700; color: var(--caption);
  font-variant-numeric: tabular-nums;
}
.phone-group.is-bad .phone-count { color: var(--error); }
.phone-group.is-ok .phone-count { color: var(--success); }

/* Day, month, year — first to last in reading order, so right to left here. */
.date-parts { display: grid; grid-template-columns: 1fr 1fr 1.3fr; gap: 6px; }
.date-parts select { min-width: 0; padding: 0 8px; }

form .btn { margin-top: 18px; }

/* A switch that is a checkbox, because that is what it is: it submits with the
   form, it is reachable by keyboard, and it works with scripting off. */
.switch { display: flex; align-items: center; gap: 10px; padding: 9px 0; font-size: .88rem; }
.switch + .switch { border-top: 1px solid var(--divider); }
.switch input { width: 18px; height: 18px; accent-color: var(--gold); flex: none; }

.rule { border: 0; border-top: 1px solid var(--divider); margin: 18px 0; }

.alert { border-radius: var(--r-sm); padding: 11px 14px; font-size: .85rem; margin-bottom: 16px; }
.alert-ok { background: rgba(102, 187, 106, .12); color: var(--success); border: 1px solid rgba(102, 187, 106, .35); }
.alert-bad { background: rgba(229, 115, 115, .12); color: var(--error); border: 1px solid rgba(229, 115, 115, .35); }

.pill { display: inline-block; padding: 3px 9px; border-radius: 999px; font-size: .7rem; font-weight: 700; background: var(--muted-surface); color: var(--text-3); }
.pill.ok { color: var(--success); }
.pill.warn { color: var(--gold); }

.danger { color: var(--error); }
.btn-ghost.danger:hover { border-color: var(--error); color: var(--error); }
.btn-gold.danger { background: var(--error); color: #fff; }
.btn-gold.danger:hover { background: #d05f5f; }
.danger-card { border-color: rgba(229, 115, 115, .4); }

.alert-form { display: grid; grid-template-columns: repeat(4, 1fr) auto; gap: 12px; align-items: end; margin-top: 18px; }
.alert-form .btn { margin-top: 0; }
form.inline { display: inline; }
form.inline .btn { margin-top: 0; }

.table-wrap { overflow-x: auto; margin-top: 14px; }
.table { width: 100%; border-collapse: collapse; }
.table th, .table td { text-align: start; padding: 10px 8px; font-size: .84rem; }
.table thead th { font-size: .68rem; font-weight: 600; color: var(--caption); border-bottom: 1px solid var(--divider); }
.table tbody tr + tr td { border-top: 1px solid var(--divider); }

.narrow { max-width: 780px; }
.muted { color: var(--text-3); }
@media (max-width: 1000px) {
  .wc-page { grid-template-columns: 1fr; }
  .auth-shell, .account-grid { grid-template-columns: 1fr; }
  .alert-form { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 640px) {
  :root { --gutter: 16px; }
  .hide-sm { display: none; }
  /* The floating button sits over the last line of the footer otherwise. */
  .foot-bottom { padding-bottom: 72px; }
  .wc-fab { padding: 12px 17px; font-size: .82rem; }
  .wc-field-row { grid-template-columns: 1fr; }
  .wc-unit { min-width: 0; }
  .wc-total dd { font-size: 1.28rem; }
  .grid-3, .grid-2 { grid-template-columns: 1fr; }
  .calc-inputs { grid-template-columns: 1fr; }
  .pl-out { grid-template-columns: 1fr; }
  .calc-table th, .calc-table td { padding: 8px 5px; font-size: .78rem; }
  .conv-fields { grid-template-columns: 1fr; }
  .field-row, .alert-form { grid-template-columns: 1fr; }
  .conv-swap { height: auto; transform: rotate(90deg); }
  .foot-grid { grid-template-columns: 1fr; gap: 26px; }
  .hero-mini { grid-template-columns: 1fr; }
  .section { padding-block: 36px; }
  .matrix tbody th, .matrix tbody td { padding: 11px 12px; }
}

/* ── the brand intro ──────────────────────────────────────────────────
   The mark assembling itself out of flying lines: one animated SVG, no
   player and no JavaScript beyond deciding when to insert it. It plays on
   the page's own background rather than a navy panel of its own — on the
   default theme that background is already the field it was designed for.

   `pointer-events: none` throughout: this is decoration over a page that is
   finished rendering and fully usable underneath it, never a curtain. */
.intro {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: grid;
  place-items: center;
  pointer-events: none;
  transition: opacity .55s ease;
}
.intro img { width: min(44vmin, 330px); height: auto; display: block; }

/* The hero waits behind its own intro, on the one visit that plays it.
   Added by intro.js and never by the stylesheet on its own: with JavaScript
   off, or on the second visit, this class never exists and the prices are
   simply there. Opacity rather than display, so nothing reflows when it
   lifts and the page is exactly as tall the whole time. */
.hero-grid { transition: opacity .6s ease; }
.hero.intro-hold .hero-grid { opacity: 0; pointer-events: none; }
.intro[data-done] { opacity: 0; }

/* The board is the one place this is a curtain rather than an overlay: a
   screen on a shop wall has nobody waiting on it, so the mark gets the whole
   panel to itself and the prices arrive when it lifts. Opaque in the board's
   own background colour, and still taking no clicks. */
.intro-board { position: fixed; background: var(--bg); }
.intro-board img { width: min(46vmin, 560px); }

/* On /about it is not an overlay at all: it is the page's own mark, in the
   flow above the title, and it stays on its last frame afterwards. */
.about-mark { display: flex; justify-content: center; margin-block: -22px -14px; }

/* /about leads with the mark, so the line under it is centred with it. Only
   there: every other page-head is a left edge the text below it lines up on. */
.page-head-brand p { text-align: center; }
.about-mark img { width: min(78vw, 380px); height: auto; display: block; }

@media (max-width: 720px) {
  .intro img { width: min(60vmin, 260px); }
}
