/* ==========================================================================
   Fantasi design system
   One stylesheet shared by every page: the public site, sign-in and sign-up,
   the member app and the admin dashboard. It is linked LAST in each <head>.

   1. Tokens       colour, type, space, radius, elevation, motion, layers
   2. Defaults     states every page gets for free. Written inside :where(),
                   so they carry no specificity and a page's own rules win.
   3. Cohesion     a short list of deliberate overrides (dialogs, toasts,
                   field errors, loading) so these feel the same everywhere.
   4. Components   ds- prefixed pieces for new work: chips, skeletons,
                   spinners, the loading bar, photo fade-in.
   5. Motion       page transitions and the reduced-motion rule.

   The living reference is /design-system.
   ========================================================================== */

/* ---------- 1. tokens ---------- */
:root {
  /* palette */
  --c-noir: #0B0A0C;
  --c-noir-soft: #100E11;
  --c-noir-raised: #17141A;
  --c-cream: #F2ECDF;
  --c-sand: #B0A797;
  --c-sand-dim: #968D7F;
  --c-gold: #C7A65C;
  --c-gold-bright: #E4C687;
  --c-gold-deep: #A8884A;
  --c-wine: #6B1A30;
  --c-wine-bright: #B0445F;
  --c-rose: #E7A1B4;
  --c-forest: #1E4A38;
  --c-forest-bright: #4E9C79;
  --c-plum: #4A2C52;
  --c-silver: #E2E6EB;

  /* roles */
  --surface-0: var(--c-noir);
  --surface-1: #121013;
  --surface-2: #19161B;
  --surface-glass: rgba(18, 16, 19, 0.72);
  --text-1: var(--c-cream);
  --text-2: var(--c-sand);
  --text-3: var(--c-sand-dim);
  --border-1: rgba(199, 166, 92, 0.14);
  --border-2: rgba(199, 166, 92, 0.30);
  --border-3: rgba(228, 198, 135, 0.55);
  --accent: var(--c-gold-bright);
  --accent-fill: linear-gradient(117.7deg, var(--c-gold) 0%, var(--c-gold-bright) 100%);
  --accent-text: linear-gradient(100deg, #f3e2b0, var(--c-gold-bright) 35%, var(--c-gold) 70%, var(--c-gold-deep));
  --danger: #D9637F;
  --danger-bg: rgba(176, 68, 95, 0.16);
  --success: #6FBF94;
  --success-bg: rgba(78, 156, 121, 0.16);
  --warning: #E0B45E;
  --tier-silver: var(--c-silver);
  --tier-gold: var(--c-gold-bright);
  --tier-black: var(--c-rose);

  /* type: Garamond does the work; the two display faces are accents only */
  --type-serif: garamond-premier-pro-display, Garamond, "Times New Roman", serif; /* headings, reading, labels */
  --type-ui: var(--type-serif);                                        /* buttons, fields, messages, toasts */
  --type-display: the-seasons, "Cormorant Garamond", Georgia, serif;   /* the italic gold word in a heading */
  --type-script: elina, "Cormorant Garamond", serif;                   /* decorative script, used sparingly */
  --fs-label: 11px;    /* uppercase labels, tracked */
  --fs-xs: 12.5px;
  --fs-sm: 14.5px;
  --fs-md: 16.5px;     /* body */
  --fs-lg: 19px;       /* lede */
  --fs-h4: 21px;
  --fs-h3: clamp(26px, 2.4vw, 34px);
  --fs-h2: clamp(36px, 4.2vw, 60px);
  --fs-h1: clamp(46px, 6.4vw, 92px);
  --lh-tight: 1.04;
  --lh-snug: 1.25;
  --lh-body: 1.65;
  --tracking-label: 0.14em;

  /* space: a 4px grid */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --space-8: 64px;
  --space-9: 96px;
  --space-10: 140px;
  --section-y: clamp(84px, 11vw, 150px);
  --gutter: clamp(16px, 4vw, 40px);

  /* radius */
  --radius-xs: 6px;
  --radius-sm: 10px;
  --radius-md: 16px;
  --radius-lg: 22px;
  --radius-xl: 30px;
  --radius-pill: 999px;

  /* elevation */
  --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.4), 0 4px 12px rgba(0, 0, 0, 0.25);
  --shadow-2: 0 12px 32px rgba(0, 0, 0, 0.42);
  --shadow-3: 0 30px 70px rgba(0, 0, 0, 0.5);
  --shadow-4: 0 50px 110px rgba(0, 0, 0, 0.6);
  --shadow-glow: 0 0 0 1px rgba(228, 198, 135, 0.35), 0 14px 40px rgba(199, 166, 92, 0.18);
  --ring-1: inset 0 0 0 1px var(--border-1);
  --ring-2: inset 0 0 0 1px var(--border-2);
  --focus-ring: 0 0 0 3px rgba(228, 198, 135, 0.22);

  /* motion: short for feedback, long for scenes */
  --dur-1: 120ms;
  --dur-2: 220ms;
  --dur-3: 400ms;
  --dur-4: 700ms;
  --ease-out: cubic-bezier(0.2, 0.7, 0.2, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --ease-spring: cubic-bezier(0.3, 1.35, 0.5, 1);

  /* layers */
  --z-raised: 10;
  --z-sticky: 100;
  --z-nav: 1000;
  --z-overlay: 9000;
  --z-toast: 99999;
}

/* ---------- 2. defaults (no specificity; pages override freely) ---------- */
::selection { background: rgba(199, 166, 92, 0.35); color: var(--text-1); }
/* hidden means hidden, even on elements that set their own display (buttons, flex rows) */
[hidden] { display: none !important; }

:where(a, button, [role="button"], [role="tab"], [role="switch"], summary, input, select, textarea):focus-visible {
  outline: 2px solid var(--c-gold-bright);
  outline-offset: 3px;
}
:where(input:not([type="checkbox"], [type="radio"], [type="range"], [type="file"]), select, textarea) {
  transition: border-color var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out), background-color var(--dur-2) var(--ease-out);
}
:where(input:not([type="checkbox"], [type="radio"], [type="range"], [type="file"]), select, textarea):focus-visible {
  outline-offset: 1px;
  box-shadow: var(--focus-ring);
}
:where(input, select, textarea, button):disabled { cursor: not-allowed; }
:where(input, select, textarea):disabled { opacity: 0.55; }
:where(button, [role="button"], .btn) { -webkit-tap-highlight-color: transparent; }
:where(.btn) { transition: transform var(--dur-2) var(--ease-out), background var(--dur-3) var(--ease-out), color var(--dur-2) var(--ease-out), border-color var(--dur-2) var(--ease-out), box-shadow var(--dur-3) var(--ease-out), opacity var(--dur-2) ease; }
:where(.btn):disabled, :where(.btn)[aria-disabled="true"] { opacity: 0.5; pointer-events: none; }
:where(a.card, button.card, .card[tabindex]) { transition: transform var(--dur-3) var(--ease-out), box-shadow var(--dur-3) var(--ease-out), border-color var(--dur-3) var(--ease-out); }
:where(img) { max-width: 100%; }

/* ---------- 3. cohesion (deliberate; these win over page styles) ---------- */

/* buttons press in, and show a spinner while they wait */
.btn:active:not(:disabled) { transform: translateY(0) scale(0.98); transition-duration: var(--dur-1); }
.btn[aria-busy="true"] { position: relative; color: transparent !important; pointer-events: none; }
.btn[aria-busy="true"]::after {
  content: ""; position: absolute; left: 50%; top: 50%; width: 16px; height: 16px; margin: -8px 0 0 -8px;
  border-radius: 50%; border: 2px solid currentColor; border-color: rgba(242, 236, 223, 0.35); border-top-color: var(--c-cream);
  animation: dsSpin 0.7s linear infinite;
}
.btn-gold[aria-busy="true"]::after { border-color: rgba(11, 10, 12, 0.25); border-top-color: var(--c-noir); }

/* fields that failed validation */
input[aria-invalid="true"], select[aria-invalid="true"], textarea[aria-invalid="true"] { border-color: var(--danger) !important; }
input[aria-invalid="true"]:focus-visible, select[aria-invalid="true"]:focus-visible, textarea[aria-invalid="true"]:focus-visible { box-shadow: 0 0 0 3px var(--danger-bg); }
.api-field-error, .ds-field-error {
  display: flex; align-items: center; gap: 6px; margin-top: 6px;
  font-family: var(--type-ui); font-size: var(--fs-xs); line-height: 1.4; color: var(--danger);
  animation: dsRise var(--dur-2) var(--ease-out);
}
.api-field-error::before, .ds-field-error::before { content: "!"; display: inline-grid; place-items: center; flex: 0 0 15px; height: 15px; border-radius: 50%; font-size: 10px; font-weight: 700; color: var(--c-noir); background: var(--danger); }

/* dialogs: the same backdrop, surface and entrance on every page */
.confirm-overlay, .modal-backdrop, .ds-dialog::backdrop { -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px); }
.confirm-overlay, .modal-backdrop { transition: opacity var(--dur-3) var(--ease-out); }
.confirm-modal, .modal, .ds-dialog {
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-3), inset 0 0 0 1px var(--border-2);
  transition: opacity var(--dur-3) var(--ease-out), transform var(--dur-3) var(--ease-spring);
}
@starting-style {
  .confirm-overlay.show, .modal-backdrop:not([hidden]) { opacity: 0; }
  .confirm-overlay.show .confirm-modal, .modal-backdrop:not([hidden]) .modal, .ds-dialog[open] { opacity: 0; transform: translateY(16px) scale(0.98); }
}

/* toasts (showToast in fantasi-api.js) */
.ds-toast {
  position: fixed; left: 50%; bottom: max(24px, env(safe-area-inset-bottom)); z-index: var(--z-toast);
  display: flex; align-items: center; gap: 10px; max-width: min(92vw, 460px);
  padding: 13px 20px 13px 16px; border-radius: var(--radius-md);
  font-family: var(--type-ui); font-size: var(--fs-sm); line-height: 1.45; color: var(--text-1);
  background: var(--surface-glass); -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px);
  box-shadow: var(--shadow-2), inset 0 0 0 1px var(--border-2);
  transform: translate(-50%, 12px); opacity: 0; pointer-events: none;
  transition: opacity var(--dur-3) var(--ease-out), transform var(--dur-3) var(--ease-spring);
}
.ds-toast.in { opacity: 1; transform: translate(-50%, 0); }
.ds-toast::before { content: ""; flex: 0 0 8px; height: 8px; border-radius: 50%; background: var(--success); box-shadow: 0 0 10px var(--success); }
.ds-toast--error::before { background: var(--danger); box-shadow: 0 0 10px var(--danger); }
.ds-toast--warning::before { background: var(--warning); box-shadow: 0 0 10px var(--warning); }

/* ---------- 4. components ---------- */

/* a thin gold bar along the top while the page talks to the server */
.ds-loadbar { position: fixed; inset: 0 0 auto; z-index: var(--z-toast); height: 2px; pointer-events: none; opacity: 0; transition: opacity var(--dur-3) ease; overflow: hidden; }
.ds-loadbar::before { content: ""; position: absolute; inset: 0; width: 40%; background: var(--accent-fill); box-shadow: 0 0 12px var(--c-gold); animation: dsLoad 1.1s var(--ease-in-out) infinite; }
html[data-busy] .ds-loadbar { opacity: 1; }

.ds-spinner { display: inline-block; width: 20px; height: 20px; border-radius: 50%; border: 2px solid var(--border-2); border-top-color: var(--c-gold-bright); animation: dsSpin 0.7s linear infinite; }

/* placeholder while content loads */
.ds-skeleton { position: relative; overflow: hidden; border-radius: var(--radius-sm); background: rgba(242, 236, 223, 0.06); }
.ds-skeleton::after { content: ""; position: absolute; inset: 0; transform: translateX(-100%); background: linear-gradient(90deg, transparent, rgba(242, 236, 223, 0.07), transparent); animation: dsShimmer 1.4s ease-in-out infinite; }

/* chips and tier tags */
.ds-chip { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; border-radius: var(--radius-pill); font-family: var(--type-serif); font-size: var(--fs-label); letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-1); box-shadow: inset 0 0 0 1px rgba(242, 236, 223, 0.25); transition: box-shadow var(--dur-2) ease, color var(--dur-2) ease, background var(--dur-2) ease; }
.ds-chip--gold { color: var(--c-gold-bright); box-shadow: inset 0 0 0 1px rgba(199, 166, 92, 0.5); }
.ds-chip--black { color: var(--tier-black); box-shadow: inset 0 0 0 1px rgba(176, 68, 95, 0.55); }
.ds-chip--forest { color: #cfe9dc; background: rgba(30, 74, 56, 0.7); box-shadow: none; }
button.ds-chip { cursor: pointer; background: none; border: 0; }
button.ds-chip:hover { box-shadow: inset 0 0 0 1px var(--border-3); }
button.ds-chip[aria-pressed="true"] { color: var(--c-noir); background: var(--accent-fill); box-shadow: none; }

/* photographs fade in as they arrive (system.js adds .is-loaded) */
.ds-photo { opacity: 0; transition: opacity var(--dur-4) var(--ease-out), transform 1.4s var(--ease-out); }
.ds-photo.is-loaded { opacity: 1; }

/* the membership action that follows you down a long page (system.js shows it
   once [data-float-after] has scrolled away, and hides it over [data-float-hide]
   and the footer). --mobile shows it on phones only. */
.ds-float-cta { position: fixed; right: max(20px, env(safe-area-inset-right)); bottom: max(20px, env(safe-area-inset-bottom)); z-index: var(--z-sticky); box-shadow: var(--shadow-2), 0 0 0 1px rgba(228, 198, 135, 0.3); opacity: 0; transform: translateY(18px); pointer-events: none; transition: opacity var(--dur-3) var(--ease-out), transform var(--dur-3) var(--ease-spring), background var(--dur-3) ease, color var(--dur-2) ease; }
.ds-float-cta.in { opacity: 1; transform: none; pointer-events: auto; }
.ds-float-cta--mobile { display: none !important; }
@media (max-width: 700px) {
  .ds-float-cta { left: 64px; right: 16px; justify-content: center; }
  .ds-float-cta--mobile { display: inline-flex !important; }
}

/* legs reaching into a section from the edge of the screen (videos/story/legs-*.webp,
   a cutout whose skirt runs off its right edge). Put the <img class="ds-legs"> inside a
   section with position: relative and overflow: clip. .ds-legs--left mirrors it so it
   reaches in from the left. It slides in as the section scrolls into view. */
.ds-legs { --dir: 1; position: absolute; z-index: 2; right: 0; bottom: 0; height: 100%; width: auto; max-width: none; pointer-events: none; user-select: none;
  filter: drop-shadow(-24px 34px 40px rgba(0, 0, 0, 0.6));
  translate: calc(42% * var(--dir)) 0; rotate: calc(7deg * var(--dir)); opacity: 0; transform-origin: 100% 20%;
  transition: translate 1.3s var(--ease-out), rotate 1.3s var(--ease-out), opacity 0.8s ease; }
.ds-legs--left { --dir: -1; right: auto; left: 0; transform: scaleX(-1); transform-origin: 0% 20%; filter: drop-shadow(24px 34px 40px rgba(0, 0, 0, 0.6)); }
.ds-legs.in { translate: 0 0; rotate: 0deg; opacity: 1; }
@supports (animation-timeline: view()) {
  .ds-legs { transition: none; animation: dsLegsIn linear both; animation-timeline: view(); animation-range: entry 10% cover 50%; }
}
@keyframes dsLegsIn { from { translate: calc(42% * var(--dir)) 0; rotate: calc(7deg * var(--dir)); opacity: 0; } 60% { opacity: 1; } to { translate: 0 0; rotate: 0deg; opacity: 1; } }

/* Gradient text (background-clip: text) only paints inside its own box, and
   the display faces' tails (g, y, p, j) hang well below it. Give every gold
   word room above and below, on every line it wraps to; the negative margins
   keep block-level ones from moving their neighbours. */
:is(h1, h2, h3, h4, h5, figcaption, blockquote, .display-xl, .cm-title, .dc-title, .fx-num) em,
.fx-pick, .dc-file-foot, .fx-ledger .gold, .hw-masks .gold b, .cm-club b, .cmx-circles .cm-circle h3, .ab-mission-marks, .fl-more em {
  padding-top: 0.1em; padding-bottom: 0.32em; margin-top: -0.1em; margin-bottom: -0.32em;
  -webkit-box-decoration-break: clone; box-decoration-break: clone;
}

/* sections far below the fold skip layout until they are near */
.ds-defer { content-visibility: auto; contain-intrinsic-size: auto 900px; }

@keyframes dsSpin { to { transform: rotate(360deg); } }
@keyframes dsRise { from { opacity: 0; transform: translateY(-3px); } to { opacity: 1; transform: none; } }
@keyframes dsShimmer { to { transform: translateX(100%); } }
@keyframes dsLoad { 0% { transform: translateX(-100%); } 100% { transform: translateX(260%); } }

/* ---------- 5. motion ---------- */

/* pages dissolve into each other like a curtain, so moving around feels like one app */
@view-transition { navigation: auto; }
::view-transition-old(root) { animation: dsPageOut var(--dur-3) ease both; }
::view-transition-new(root) { animation: dsPageIn 0.55s var(--ease-out) both; }
@keyframes dsPageOut { to { opacity: 0; filter: blur(6px); } }
@keyframes dsPageIn { from { opacity: 0; transform: scale(1.012); } }

@media (prefers-reduced-motion: reduce) {
  @view-transition { navigation: none; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .ds-photo { opacity: 1; }
  .ds-legs { animation: none; translate: 0 0; rotate: 0deg; opacity: 1; }
}
