/* ============================================================
   WeArrange — foundation
   Tokens, reset, typography scale, day→night theming engine.
   ============================================================ */

:root {
  /* --- brand, straight from the identity deck --- */
  --ice:        #f1f5ff;   /* R241 G245 B255 */
  --peri:       #b3c7ff;   /* R179 G199 B255 */
  --gold:       #daac00;   /* R218 G172 B0   */
  --grey:       #dadbdc;   /* R218 G219 B220 */
  --blue:       #1e3e95;   /* taken from the logo artwork itself */
  --blue-deck:  #263d91;   /* the deck's stated value, kept for reference */
  --black:      #000000;

  /* --- derived depths --- */
  --blue-deep:  #16306f;
  --blue-abyss: #0c1c42;
  --night:      #050609;
  --peri-dim:   #8ea6e0;

  /* --- the live surface: driven by JS as the page descends --- */
  --surface:    var(--ice);
  --ink:        var(--blue);
  /* Height of the fixed header. Interior pages offset their content by it.
     JS refines this on resize; the fallback keeps the layout right without it. */
  --hdr-h:      78px;
  --ink-soft:   #5f719f;
  --rule:       rgba(30, 62, 149, 0.16);
  --rule-soft:  rgba(30, 62, 149, 0.08);

  /* --- type ---
     No monospace anywhere. Wide-tracked uppercase mono micro-labels are the
     single most recognisable tell of a generated website; the label voice here
     is a serif italic in sentence case instead, which reads as an editorial
     aside rather than a system readout. */
  --display: 'Clash Display', 'Helvetica Neue', sans-serif;
  --text:    'Switzer', 'Helvetica Neue', sans-serif;
  --serif:   'Sentient', Iowan Old Style, Georgia, serif;
  --arabic:  'Plex Arabic', 'Switzer', sans-serif;

  /* --- measure --- */
  --gutter: clamp(1.25rem, 4vw, 4.5rem);
  --rail:   clamp(2.75rem, 5vw, 5.5rem);   /* left index rail width */
  --maxw:   96rem;

  /* --- motion --- */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in-out: cubic-bezier(0.76, 0, 0.24, 1);
  --dur: 0.9s;
}

/* ---------- reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body, h1, h2, h3, h4, p, figure, blockquote, dl, dd, ul, ol { margin: 0; padding: 0; }
ul, ol { list-style: none; }
img, svg, video { display: block; max-width: 100%; }
button, input, textarea, select { font: inherit; color: inherit; background: none; border: 0; }
button { cursor: pointer; }
a { color: inherit; text-decoration: none; }

html {
  /* Native scrolling is deliberate: sticky pins, keyboard paging, mobile
     momentum and find-in-page all keep working. The "smooth" feel comes from
     js/scroller.js, which drives every animation off a lerped scroll value
     rather than hijacking the scroll itself. */
  scroll-behavior: auto;
}

body {
  font-family: var(--text);
  font-weight: 400;
  font-size: clamp(0.98rem, 0.55vw + 0.85rem, 1.125rem);
  line-height: 1.55;
  color: var(--ink);
  background: var(--surface);
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  transition: background-color 0.6s linear, color 0.6s linear;
}

::selection { background: var(--gold); color: var(--black); }

/* ---------- night mode: set on <body> by the horizon scene ---------- */
body[data-phase="dusk"] {
  --surface: var(--blue-deep);
  --ink: var(--ice);
  --ink-soft: rgba(241, 245, 255, 0.6);
  --rule: rgba(241, 245, 255, 0.18);
  --rule-soft: rgba(241, 245, 255, 0.08);
}
body[data-phase="night"] {
  --surface: var(--night);
  --ink: var(--ice);
  --ink-soft: rgba(241, 245, 255, 0.55);
  --rule: rgba(241, 245, 255, 0.16);
  --rule-soft: rgba(241, 245, 255, 0.07);
}

/* ============================================================
   TYPOGRAPHY
   ============================================================ */

.display {
  font-family: var(--display);
  font-weight: 500;
  line-height: 0.86;
  letter-spacing: -0.035em;
  text-wrap: balance;
}

.d-xl { font-size: clamp(2.9rem, 9.2vw, 9.5rem); }
.d-lg { font-size: clamp(2.3rem, 6vw, 5.8rem); }
.d-md { font-size: clamp(2rem, 4.6vw, 4.4rem); line-height: 0.94; }
.d-sm { font-size: clamp(1.5rem, 2.6vw, 2.4rem); line-height: 1.02; letter-spacing: -0.025em; }

.thin { font-weight: 200; }
.mid  { font-weight: 400; }
.bold { font-weight: 600; }

/* The caret-A — lifted from the wordmark, where the A is a rising chevron.
   Used sparingly, only where the brand voice literally says "arrange". */
.caret {
  display: inline-block;
  position: relative;
  width: 0.60em;
  height: 0.70em;
  vertical-align: baseline;
  margin: 0 0.02em;
}
.caret::before {
  content: '';
  position: absolute;
  inset: 0;
  background: currentColor;
  -webkit-mask: var(--caret-mask) center/contain no-repeat;
          mask: var(--caret-mask) center/contain no-repeat;
}
:root {
  --caret-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 62 72'%3E%3Cpath d='M31 4 L58 68 L47 68 L31 30 L15 68 L4 68 Z' stroke-linejoin='round' stroke-width='7' stroke='black' fill='black'/%3E%3C/svg%3E");
}

/* Eyebrow / label. Sentence case, serif italic, ordinary tracking — an aside
   in the margin of a document, not a readout on a dashboard. */
.label {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(0.86rem, 0.3vw + 0.78rem, 1.02rem);
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink-soft);
}
.label--gold { color: var(--gold); }

/* Long-form reading. Used on the interior pages, where there is real text to
   get through and a serif simply carries further than a grotesque. */
.prose {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(1.02rem, 0.42vw + 0.93rem, 1.22rem);
  line-height: 1.62;
  letter-spacing: 0.002em;
}
.prose p + p { margin-top: 1.15em; }
.prose p { max-width: 68ch; text-wrap: pretty; }
.prose strong { font-weight: 600; }
.prose em { font-style: italic; }
.prose a { text-decoration: underline; text-underline-offset: 0.18em; text-decoration-thickness: 1px; }
.prose a:hover { color: var(--gold); }

.ar {
  font-family: var(--arabic);
  font-weight: 300;
  direction: rtl;
  unicode-bidi: isolate;
  letter-spacing: 0;
}

.lede {
  font-size: clamp(1.05rem, 0.9vw + 0.85rem, 1.5rem);
  line-height: 1.45;
  font-weight: 300;
  letter-spacing: -0.012em;
  max-width: 34ch;
  color: var(--ink-soft);
  text-wrap: pretty;
}

.num {
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
}

/* ============================================================
   LAYOUT PRIMITIVES
   ============================================================ */

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

/* Every section carries an index number in the left rail — the site reads
   like a filing system, which is what the company actually sells. */
.chapter {
  position: relative;
  padding-block: clamp(5rem, 12vh, 10rem);
}
.chapter__rail {
  position: absolute;
  top: clamp(5rem, 12vh, 10rem);
  left: var(--gutter);
  writing-mode: vertical-rl;
  font-family: var(--serif);
  font-style: italic;
  font-size: 0.92rem;
  letter-spacing: 0;
  color: var(--ink-soft);
  display: flex;
  align-items: center;
  gap: 1.2rem;
}
.chapter__rail::after {
  content: '';
  width: 1px;
  height: clamp(3rem, 10vh, 7rem);
  background: linear-gradient(to bottom, var(--rule), transparent);
}
@media (max-width: 900px) { .chapter__rail { display: none; } }

.inset { padding-left: var(--gutter); }
@media (min-width: 901px) {
  /* the vertical section-index rails were removed; content now aligns to the
     same gutter as everything else */
  .inset { padding-left: var(--gutter); }
}

.hr {
  height: 1px;
  background: var(--rule);
  border: 0;
  transform-origin: left center;
}

/* ============================================================
   THE CAPSULE — the identity's atomic unit.
   Every rounded bar on this site is one of these.
   ============================================================ */
.cap {
  border-radius: 999px;
  background: currentColor;
  display: block;
}

/* ============================================================
   BUTTONS
   ============================================================ */
.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.85em;
  padding: 0.95em 1.5em 0.95em 1.6em;
  border-radius: 999px;
  font-family: var(--text);
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--surface);
  isolation: isolate;
  overflow: hidden;
  transition: color 0.5s var(--ease-out);
}
.btn::before {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--ink);
  border-radius: inherit;
  z-index: -2;
}
.btn::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--gold);
  border-radius: inherit;
  z-index: -1;
  transform: translateY(101%);
  transition: transform 0.62s var(--ease-out);
}
.btn:hover::after, .btn:focus-visible::after { transform: translateY(0); }
.btn:hover, .btn:focus-visible { color: var(--black); }
.btn__dot {
  width: 0.45em; height: 0.45em; border-radius: 999px;
  background: currentColor; flex: none;
}

.btn--ghost {
  color: var(--ink);
  border: 1px solid var(--rule);
  padding: 0.9em 1.5em;
}
.btn--ghost::before { background: transparent; }
.btn--ghost:hover { color: var(--black); border-color: var(--gold); }

/* link with a rule that wipes on hover */
.ulink {
  position: relative;
  display: inline-block;
  padding-bottom: 0.15em;
}
.ulink::after {
  content: '';
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: right center;
  transition: transform 0.5s var(--ease-out);
}
.ulink:hover::after, .ulink:focus-visible::after {
  transform: scaleX(1);
  transform-origin: left center;
}

/* ============================================================
   SCROLL-LINKED REVEAL PRIMITIVES
   (driven by js/engine.js — .is-in is added when a node enters)
   ============================================================ */

/* per-line mask reveal: each .line gets an inner <i> that slides up */
.reveal .line {
  display: block;
  overflow: hidden;
  /* line-height is 0.86, so the line box sits inside the glyphs. Extend the
     clip box below the baseline to clear descenders, then pull the extra
     height back out so the vertical rhythm is unchanged. */
  padding-bottom: 0.16em;
  margin-bottom: -0.16em;
}
.reveal .line > i {
  display: block;
  font-style: inherit;
  transform: translateY(105%) rotate(2deg);
  opacity: 0;
  transition:
    transform 1.05s var(--ease-out),
    opacity 0.7s linear;
  transition-delay: calc(var(--i, 0) * 78ms);
}
.reveal.is-in .line > i { transform: none; opacity: 1; }

.fade { opacity: 0; transform: translateY(1.6rem); transition: opacity 0.9s var(--ease-out), transform 1.1s var(--ease-out); transition-delay: calc(var(--i, 0) * 65ms); }
.fade.is-in { opacity: 1; transform: none; }

.wipe { clip-path: inset(0 100% 0 0); transition: clip-path 1.2s var(--ease-in-out); transition-delay: calc(var(--i, 0) * 80ms); }
.wipe.is-in { clip-path: inset(0 0 0 0); }

.grow { transform: scaleX(0); transform-origin: left center; transition: transform 1.1s var(--ease-in-out); transition-delay: calc(var(--i, 0) * 60ms); }
.grow.is-in { transform: scaleX(1); }

/* ============================================================
   GRAIN + VIGNETTE — kills the flat vector-render look
   ============================================================ */
.grain {
  position: fixed;
  inset: -50%;
  z-index: 9998;
  pointer-events: none;
  opacity: 0.2;
  mix-blend-mode: overlay;
  background-image: var(--grain-src);
  background-size: 180px 180px;
  animation: grainshift 7s steps(6) infinite;
}
@keyframes grainshift {
  0%   { transform: translate(0, 0); }
  16%  { transform: translate(-3%, 2%); }
  33%  { transform: translate(2%, -4%); }
  50%  { transform: translate(-4%, -2%); }
  66%  { transform: translate(3%, 3%); }
  83%  { transform: translate(-2%, 4%); }
  100% { transform: translate(0, 0); }
}

/* ============================================================
   CUSTOM CURSOR — a capsule, because the logo is capsules
   ============================================================ */
.cursor {
  position: fixed;
  top: 0; left: 0;
  z-index: 9999;
  pointer-events: none;
  width: 12px; height: 12px;
  border-radius: 999px;
  background: var(--gold);
  mix-blend-mode: difference;
  will-change: transform;
  transition: width 0.45s var(--ease-out), height 0.45s var(--ease-out), background-color 0.4s;
}
.cursor--wide { width: 46px; height: 12px; }
.cursor--ring { width: 54px; height: 54px; background: transparent; box-shadow: inset 0 0 0 1px var(--gold); }
.cursor__txt {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  font-family: var(--text); font-size: 0.72rem; letter-spacing: 0.06em; color: var(--gold);
  opacity: 0; transition: opacity 0.3s;
}
.cursor--ring .cursor__txt { opacity: 1; }
@media (hover: none), (pointer: coarse) { .cursor { display: none; } }

/* ============================================================
   SCROLL SPINE — five capsules, one per bar of the W.
   Fills as the document is consumed.
   ============================================================ */
.spine {
  position: fixed;
  left: calc(var(--gutter) * 0.45);
  top: 50%;
  transform: translateY(-50%);
  z-index: 60;
  display: flex;
  flex-direction: column;
  gap: 7px;
  /* No blend mode: difference over the mid-blue of the jurisdictions and
     horizon sections turns the bars a muddy ochre. The phase tokens already
     flip ink from blue to ice, so plain currentColour tracks the page. */
  color: var(--ink);
  opacity: 0;
  transition: opacity 0.7s var(--ease-out);
}
.spine.is-on { opacity: 1; }
.spine__bar {
  width: 3px;
  height: 34px;
  border-radius: 999px;
  /* opacity on the bar itself would form a group and dim the gold fill with
     it, so the track is tinted through the background instead */
  background: rgba(128, 140, 175, 0.3);
  background: color-mix(in srgb, currentColor 22%, transparent);
  overflow: hidden;
  position: relative;
}
.spine__bar::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--gold);
  border-radius: inherit;
  transform: scaleY(var(--fill, 0));
  transform-origin: top center;
}
@media (max-width: 900px) { .spine { display: none; } }

/* ============================================================
   ACCESSIBILITY
   ============================================================ */
/* Hidden by clipping rather than by left:-9999px. The old technique pushed the
   link 9999px off the inline-start edge, which in RTL lands off the *other*
   side and adds 9999px of horizontal scroll to every Arabic page. Clipping has
   no such directionality. */
.skip {
  position: absolute; inset-inline-start: 0; top: 0; z-index: 10000;
  background: var(--blue); color: var(--ice);
  padding: 1rem 1.4rem; font-family: var(--text); font-size: 0.75rem;
  clip-path: inset(50%); width: 1px; height: 1px; overflow: hidden;
  white-space: nowrap;
}
.skip:focus {
  clip-path: none; width: auto; height: auto; overflow: visible;
}

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

.vh {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .reveal .line > i { transform: none; opacity: 1; }
  .fade { opacity: 1; transform: none; }
  .wipe { clip-path: none; }
  .grow { transform: none; }
  .grain { animation: none; }
}
