/* ============================================================================
   AlAAnizA — design tokens, reset, typography, controls.

   Two paintings decide everything here.

   VAN GOGH, The Starry Night — the palette and the energy. Deep cobalt night,
   chrome-yellow stars, and movement that never quite settles. This is the dark
   surface: hero, footer, the player.

   LEONARDO, sfumato — the surface quality. "Softened like smoke": Leonardo's
   own method was to let no edge in a painting be hard. That is why NOTHING in
   this stylesheet has a square corner, why every shadow is a wide soft falloff,
   and why things fade in through a blur rather than snapping into place. It is
   the reason for the rule, not a decoration on top of it.

   Logical properties throughout, so Arabic mirrors with no second stylesheet.
   ============================================================================ */

:root {
  /* --- The night, from The Starry Night ---------------------------------- */
  --night: #0A1B34;        /* the darkest ground */
  --night-2: #12315C;      /* the sky's body */
  --night-3: #1B4B8F;      /* lit cobalt */
  --cobalt: #2A69B0;
  --cobalt-light: #3E88C9;
  --cobalt-pale: #8FB4D8;

  /* --- The stars --------------------------------------------------------- */
  --chrome: #F5C842;       /* chrome yellow: the star and the accent */
  --chrome-deep: #C99A1E;  /* dark enough to be text on cream */
  --chrome-soft: #FFE9A8;
  --chrome-glow: #FFF3CE;

  /* --- The lit canvas, from the Mona Lisa's varnish ----------------------- */
  --canvas: #F8F1E3;       /* the page: warm, never white */
  --canvas-2: #F0E5D0;     /* sunken panels */
  --canvas-3: #E5D7BC;     /* borders, softly */
  --umber: #3B2F1E;
  --umber-soft: #6B5836;
  --olive: #6B6440;

  /* --- Text -------------------------------------------------------------- */
  --ink: #241C12;          /* on canvas: 13.9:1 */
  --ink-soft: #574934;     /* 6.4:1 */
  --ink-faint: #7A6A52;    /* 4.6:1 */
  --on-night: #EFE5D0;     /* on night: 13.2:1 */
  --on-night-dim: #B5C8DE; /* 8.1:1 */

  --surface: #FFFDF8;

  /* --- Status, kept in the paintings' own colours -------------------------
     Each foreground is dark enough to clear WCAG AA against its own soft
     background. A badge nobody can read is not a badge. */
  --ok: #35633A;           /* 5.6:1 on --ok-soft */
  --ok-soft: #E4EFE2;
  --warn: #7A5A0F;         /* 5.9:1 on --warn-soft */
  --warn-soft: #FBF0D4;
  --danger: #8E3421;       /* 6.4:1 on --danger-soft */
  --danger-soft: #F8E5DE;

  /* --- Type --------------------------------------------------------------
     Cormorant Garamond is a Renaissance face: the letterforms Leonardo's own
     century used, and unusually soft-edged for a serif, with almost no sharp
     terminals. It carries the display.

     Alexandria runs the interface. It covers Arabic and Latin with the same
     rounded, low-contrast voice, so a heading reads the same in both languages
     and nothing in the UI has a hard corner either. */
  --font-display: 'Cormorant Garamond', 'Amiri', Georgia, serif;
  --font-body: 'Alexandria', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;

  /* The admin panel's font. A plain system stack: nothing to download, looks
     native, and reads at a glance — which is a dashboard's entire job.
     Cormorant Garamond uses OLD-STYLE figures, where 1 sits at x-height and is
     easily mistaken for a capital I, so it must never set a number in a table
     or a stat tile. The Renaissance serif stays on the public site. */
  --font-ui: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue',
             Arial, 'Noto Sans', sans-serif;

  --step--1: clamp(0.84rem, 0.81rem + 0.14vw, 0.92rem);
  --step-0: clamp(1rem, 0.96rem + 0.2vw, 1.09rem);
  --step-1: clamp(1.18rem, 1.11rem + 0.34vw, 1.38rem);
  --step-2: clamp(1.45rem, 1.3rem + 0.72vw, 1.95rem);
  --step-3: clamp(1.9rem, 1.6rem + 1.5vw, 2.9rem);
  --step-4: clamp(2.6rem, 1.9rem + 3.3vw, 5rem);

  /* --- Space -------------------------------------------------------------- */
  --gutter: clamp(1.35rem, 4vw, 3.25rem);
  --measure: 66ch;

  /* --- Shape --------------------------------------------------------------
     NOTHING here is square. The smallest radius in the system is 10px, and
     every control that can be a pill is one. */
  --r-sm: 10px;
  --r: 20px;
  --r-lg: 30px;
  --r-xl: 44px;
  --r-pill: 999px;

  /* Soft, wide and warm. A tight dark shadow would put a hard edge back in. */
  --shadow-sm: 0 2px 10px rgb(36 28 18 / 0.06);
  --shadow: 0 10px 34px -8px rgb(36 28 18 / 0.16);
  --shadow-lg: 0 26px 70px -18px rgb(10 27 52 / 0.35);
  --glow: 0 0 34px -4px rgb(245 200 66 / 0.5);

  --ease: cubic-bezier(0.22, 0.68, 0.32, 1);
}

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

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  min-height: 100vh;
  background: var(--canvas);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--step-0);
  font-weight: 400;
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

/* max-width is harmless to leave unconditional. display is NOT: video and
   canvas are both hidden/shown via the `hidden` attribute on the watch page,
   and `display` must live ONLY in the guarded rule below. A scoped rule like
   `.player-shell video:not([hidden])` only wins this fight while VISIBLE —
   the moment `hidden` is set that selector stops matching entirely, and the
   cascade falls through to whatever unconditional `display` rule remains. If
   one still set `display: block` here unconditionally, THAT would win instead
   of the browser's built-in `[hidden] { display: none }`, silently undoing
   the fix. Guarding here closes the gap for every element of these types, not
   just the ones already known to be toggled. */
img, svg, video, canvas { max-width: 100%; }
img:not([hidden]), svg:not([hidden]), video:not([hidden]), canvas:not([hidden]) {
  display: block;
}
img, video { height: auto; }
input, button, textarea, select { font: inherit; color: inherit; }
input[type='date'], input[type='time'], input[type='number'] { direction: ltr; }

/* --------------------------------------------------------------- motion --- */

/* ---- The flowing sky -------------------------------------------------------
   The whole point: the sky reads as one moving CURRENT, not a rotating picture.
   Three depth layers drift at different speeds and directions, the vortices
   counter-rotate while breathing, and the stars pulse out of phase with each
   other. Everything animates `transform` or `opacity` only, on a handful of
   GROUPS rather than per-path, or a sky of ~900 strokes would melt a phone. */

@keyframes vgDriftBack {
  0%   { transform: translate3d(0, 0, 0) scale(1.06); }
  50%  { transform: translate3d(-1.6%, 0.9%, 0) scale(1.06); }
  100% { transform: translate3d(0, 0, 0) scale(1.06); }
}
@keyframes vgDriftMid {
  0%   { transform: translate3d(0, 0, 0) scale(1.04); }
  50%  { transform: translate3d(2.2%, -1.2%, 0) scale(1.04); }
  100% { transform: translate3d(0, 0, 0) scale(1.04); }
}
@keyframes vgDriftFront {
  0%   { transform: translate3d(0, 0, 0) scale(1.02); }
  50%  { transform: translate3d(-3.2%, -0.6%, 0) scale(1.02); }
  100% { transform: translate3d(0, 0, 0) scale(1.02); }
}
@keyframes vgSpin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}
/* The breath: a vortex that only rotated would look mechanical. */
@keyframes vgBreathe {
  0%, 100% { scale: 1; }
  50%      { scale: 1.055; }
}
@keyframes vgStar {
  0%, 100% { opacity: 1; scale: 1; }
  50%      { opacity: 0.42; scale: 0.88; }
}
@keyframes vgMoon {
  0%, 100% { opacity: 0.92; }
  50%      { opacity: 1; }
}

.vg-layer { will-change: transform; transform-origin: 50% 50%; }
.vg-layer--back  { animation: vgDriftBack 74s ease-in-out infinite; }
.vg-layer--mid   { animation: vgDriftMid 58s ease-in-out infinite; }
.vg-layer--front { animation: vgDriftFront 44s ease-in-out infinite; }

/* Two animations on one element: the spin (duration set inline, per vortex) and
   the breath. Durations and directions come from the inline style in art.js so
   no two vortices are ever in phase. */
.vg-vortex {
  will-change: transform;
  animation-name: vgSpin, vgBreathe;
  animation-timing-function: linear, ease-in-out;
  animation-iteration-count: infinite, infinite;
}

.vg-star { animation: vgStar ease-in-out infinite; transform-box: fill-box; transform-origin: center; }
.vg-moon { animation: vgMoon 9s ease-in-out infinite; }

/* Paused by an IntersectionObserver in ui.js when the sky scrolls out of view.
   An animated sky nobody can see is pure battery cost. */
.vg-paused .vg-layer,
.vg-paused .vg-vortex,
.vg-paused .vg-star,
.vg-paused .vg-moon { animation-play-state: paused; }
/* The reveal is a sfumato: content resolves out of a blur instead of sliding
   into place, so even the transition has no hard edge. */
@keyframes sfumato {
  from { opacity: 0; filter: blur(14px); translate: 0 22px; }
  to { opacity: 1; filter: blur(0); translate: 0 0; }
}
@keyframes floatSlow {
  0%, 100% { translate: 0 0; }
  50% { translate: 0 -12px; }
}
@keyframes glowPulse {
  0%, 100% { opacity: 0.55; }
  50% { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  .vg-layer, .vg-vortex, .vg-star, .vg-moon { animation: none !important; }
}

/* --------------------------------------------------------------- type --- */

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.08;
  letter-spacing: -0.012em;
  text-wrap: balance;
}
:root[dir='rtl'] h1,
:root[dir='rtl'] h2,
:root[dir='rtl'] h3,
:root[dir='rtl'] h4 {
  font-family: var(--font-body);
  font-weight: 500;
  line-height: 1.35;
  letter-spacing: 0;
}

h1 { font-size: var(--step-4); }
h2 { font-size: var(--step-3); }
h3 { font-size: var(--step-2); }
h4 { font-size: var(--step-1); }

p { text-wrap: pretty; }

a { color: var(--night-3); text-underline-offset: 0.2em; text-decoration-thickness: 1px; }
a:hover { color: var(--chrome-deep); }

.eyebrow {
  font-size: var(--step--1);
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--chrome-deep);
}
:root[dir='rtl'] .eyebrow { letter-spacing: 0; }

.lede {
  font-size: var(--step-1);
  color: var(--ink-soft);
  max-width: var(--measure);
  font-weight: 400;
}
.muted { color: var(--ink-faint); }
.small { font-size: var(--step--1); }
.num { font-variant-numeric: tabular-nums; }

/* An italic display flourish, used once or twice per page and no more. */
.flourish {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 400;
  color: var(--chrome);
}

/* ------------------------------------------------------------------ focus --- */

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

.skip-link {
  position: absolute;
  inset-inline-start: 1rem;
  inset-block-start: -100%;
  z-index: 100;
  padding: 0.7rem 1.4rem;
  border-radius: var(--r-pill);
  background: var(--chrome);
  color: var(--night);
  font-weight: 500;
}
.skip-link:focus { inset-block-start: 1rem; }

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

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

.wrap {
  width: min(100% - (var(--gutter) * 2), 1200px);
  margin-inline: auto;
}
.wrap--narrow { width: min(100% - (var(--gutter) * 2), 780px); }

.section { padding-block: clamp(3.5rem, 8vw, 7rem); }

/* --------------------------------------------------------------- controls --- */

/* Every button is a pill. There is not a 90-degree corner anywhere in the
   control set. */
/* :not([hidden]): several .btn elements (e.g. watch.js's #nextLink) are shown
   and hidden via the `hidden` attribute. An unconditional `display` here would
   override the browser's built-in `[hidden] { display: none }` regardless of
   specificity, since normal author rules always beat the UA stylesheet — the
   same bug that hit .player-message. Gating the whole ruleset costs nothing:
   none of these properties matter once an element is display:none anyway. */
.btn:not([hidden]) {
  --btn-bg: var(--night-3);
  --btn-fg: var(--on-night);
  --btn-border: transparent;
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6em;
  padding: 0.82em 1.85em;
  border: 1.5px solid var(--btn-border);
  border-radius: var(--r-pill);
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-size: var(--step-0);
  font-weight: 500;
  line-height: 1.25;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 0.35s var(--ease), color 0.35s var(--ease),
              box-shadow 0.35s var(--ease), transform 0.35s var(--ease);
}
.btn:hover:not(:disabled) {
  transform: translateY(-2px);
  box-shadow: var(--shadow);
  color: var(--btn-fg);
}
.btn:active:not(:disabled) { transform: translateY(0); }
.btn:disabled { opacity: 0.45; cursor: not-allowed; }

.btn--gold {
  --btn-bg: var(--chrome);
  --btn-fg: #2E2205;
}
.btn--gold:hover:not(:disabled) {
  --btn-bg: var(--chrome-soft);
  box-shadow: var(--glow);
}

.btn--ghost {
  --btn-bg: transparent;
  --btn-fg: var(--night-3);
  --btn-border: var(--canvas-3);
}
.btn--ghost:hover:not(:disabled) {
  --btn-bg: var(--canvas-2);
  --btn-border: var(--chrome);
}

/* On the night ground, a ghost button borrows the sky rather than the page. */
.on-night .btn--ghost {
  --btn-fg: var(--on-night);
  --btn-border: rgb(255 255 255 / 0.28);
}
.on-night .btn--ghost:hover:not(:disabled) {
  --btn-bg: rgb(255 255 255 / 0.1);
  --btn-border: var(--chrome);
}

.btn--danger { --btn-bg: var(--danger); --btn-fg: #fff; }
.btn--sm { padding: 0.5em 1.15em; font-size: var(--step--1); }
.btn--full { width: 100%; }

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

.field { display: block; margin-block-end: 1.25rem; }

.field > label,
.field-label {
  display: block;
  margin-block-end: 0.45rem;
  font-size: var(--step--1);
  font-weight: 400;
  color: var(--ink-soft);
}

.field input[type='text'],
.field input[type='password'],
.field input[type='number'],
.field input[type='date'],
.field input[type='search'],
.field textarea,
.field select {
  width: 100%;
  padding: 0.8rem 1.15rem;
  border: 1.5px solid var(--canvas-3);
  border-radius: var(--r-pill);
  background: var(--surface);
  color: var(--ink);
  transition: border-color 0.3s var(--ease), box-shadow 0.3s var(--ease);
}
/* A textarea cannot be a pill and stay usable, so it takes the largest radius
   that still reads as soft. */
.field textarea {
  min-height: 7.5rem;
  border-radius: var(--r);
  resize: vertical;
  line-height: 1.65;
}
.field select { border-radius: var(--r-pill); }

.field input:focus-visible,
.field textarea:focus-visible,
.field select:focus-visible {
  border-color: var(--chrome);
  outline: none;
  box-shadow: 0 0 0 4px rgb(245 200 66 / 0.18);
}

.field-hint { margin-block-start: 0.4rem; font-size: var(--step--1); color: var(--ink-faint); }

.check { display: flex; align-items: flex-start; gap: 0.7rem; cursor: pointer; }
.check input {
  inline-size: 1.15rem;
  block-size: 1.15rem;
  margin-block-start: 0.35rem;
  accent-color: var(--night-3);
  border-radius: var(--r-sm);
}

.form-error {
  display: none;
  padding: 0.85rem 1.2rem;
  margin-block-end: 1.1rem;
  border-radius: var(--r);
  background: var(--danger-soft);
  color: var(--danger);
  font-size: var(--step--1);
}
.form-error.is-visible { display: block; }

/* ------------------------------------------------------------------ badge --- */

.badge {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  padding: 0.28em 0.85em;
  border-radius: var(--r-pill);
  font-size: var(--step--1);
  font-weight: 400;
  line-height: 1.5;
  white-space: nowrap;
}
.badge--ok { background: var(--ok-soft); color: var(--ok); }
.badge--warn { background: var(--warn-soft); color: var(--warn); }
.badge--danger { background: var(--danger-soft); color: var(--danger); }
.badge--quiet { background: var(--canvas-2); color: var(--ink-soft); }
.badge--gold { background: #FBEFCB; color: #6E5410; }

/* ------------------------------------------------------------------ toast --- */

.toast {
  position: fixed;
  inset-block-end: 1.5rem;
  inset-inline-start: 50%;
  translate: -50% 0;
  z-index: 60;
  max-width: min(92vw, 32rem);
  padding: 0.9rem 1.5rem;
  border-radius: var(--r-pill);
  background: var(--night);
  color: var(--on-night);
  box-shadow: var(--shadow-lg);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.35s var(--ease), translate 0.35s var(--ease);
}
.toast.is-visible { opacity: 1; translate: -50% -0.5rem; }

/* ------------------------------------------------------------------ brand --- */

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.8rem;
  color: inherit;
  text-decoration: none;
}
.brand svg { flex: none; border-radius: var(--r-sm); }
.brand__name {
  display: block;
  font-family: var(--font-display);
  font-size: 1.6rem;
  font-weight: 600;
  line-height: 1;
  letter-spacing: 0.01em;
}
:root[dir='rtl'] .brand__name { font-family: var(--font-body); font-size: 1.3rem; }
.brand__role {
  display: block;
  font-size: 0.68rem;
  font-weight: 400;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  opacity: 0.75;
  margin-block-start: 0.3rem;
}
:root[dir='rtl'] .brand__role { letter-spacing: 0; }

/* -------------------------------------------------------------- reveal --- */

/* Hiding is gated on a class JavaScript sets at startup: if the script never
   runs, nothing is ever hidden and the page simply renders. The visibility of
   the catalogue must never depend on an animation succeeding. */
:root.js-reveal .reveal { opacity: 0; }
:root.js-reveal .reveal.is-revealed {
  animation: sfumato 0.9s var(--ease) both;
}
:root.js-reveal .reveal.is-revealed:nth-child(2) { animation-delay: 0.08s; }
:root.js-reveal .reveal.is-revealed:nth-child(3) { animation-delay: 0.16s; }
:root.js-reveal .reveal.is-revealed:nth-child(4) { animation-delay: 0.24s; }
:root.js-reveal .reveal.is-revealed:nth-child(5) { animation-delay: 0.32s; }
:root.js-reveal .reveal.is-revealed:nth-child(6) { animation-delay: 0.4s; }

@media (prefers-reduced-motion: reduce) {
  :root.js-reveal .reveal { opacity: 1; }
  :root.js-reveal .reveal.is-revealed { animation: none; }
}
