/* ==========================================================================
   Daleel, design tokens & primitives (dipakai landing page + aplikasi)
   ========================================================================== */

:root {
  /* ---------- Type ---------- */
  /* UI stays sans: SF on Apple devices, Inter everywhere else (loaded from Google Fonts). */
  --font: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Inter", "Segoe UI Variable Text", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-display: -apple-system, BlinkMacSystemFont, "SF Pro Display", "Inter", "Segoe UI Variable Display", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  /* Brand serif: the wordmark and the landing's display headlines only (owner decision, 6 November 2026: serif on
     the landing only; every title inside the app, big page titles included, is Inter, and app.html does not load it).
     Never forms, tables, steps, buttons or body text, and never the default font of a student's paper, poster or slides. */
  --font-serif: "Newsreader", "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif;
  /* Code-like UI (kbd, table cells, data entry cells): unchanged from base.css. Numbers in data use var(--font) with tabular-nums. */
  --mono: "SF Mono", ui-monospace, "JetBrains Mono", "Cascadia Code", Menlo, Consolas, monospace;
  /* References a student pastes into a database: search strings (.sbox-code), DOI, PMID. */
  --mono-ref: "JetBrains Mono", ui-monospace, Consolas, monospace;

  /* ---------- Neutrals: ink on paper ---------- */
  --bg: #FAFAF8;            /* Kertas: page background, a barely warm near-white. Optional for app surfaces (#FFFFFF is fine). */
  --surface: #FFFFFF;       /* cards, sheets, inputs */
  --surface-2: #F3F3F0;     /* secondary surfaces (same value as --soft) */
  --soft: #F3F3F0;          /* chips, table stripes, footer */
  --soft-2: #EAEAE6;        /* pressed chips, progress tracks, skeletons */
  --ink: #16181F;           /* Tinta: 17.73:1 on --surface, 16.96 on --bg, 15.95 on --soft, 14.70 on --soft-2, 15.60 on brand wash */
  --ink-2: #3D404A;         /* labels, secondary text: 10.34 / 9.90 / 9.30 / 8.57, 9.10 on brand wash */
  --muted: #5E616B;         /* supporting copy, Research in the wordmark: 6.18 / 5.91 / 5.56 / 5.12, 5.44 on brand wash */
  --faint: #666973;         /* captions, metadata, placeholders (the lightest text): 5.48 / 5.24 / 4.93 / 4.54, 4.82 on brand wash */
  --text-1: var(--ink);
  --text-2: var(--ink-2);
  --text-3: var(--muted);
  --line: rgba(22, 24, 31, .08);   /* hairlines and card borders, decorative only */
  --line-2: rgba(22, 24, 31, .14); /* stronger dividers, chip borders, decorative only */
  --line-control: #878A93;         /* borders of inputs, checkboxes, radios, upcoming-step rings (WCAG 1.4.11): 3.45 on --surface, 3.30 on --bg, 3.10 on --soft */

  /* ---------- Brand: Tinta Biru (royal ink, hue 228) ---------- */
  --brand: #2847C3;         /* symbol, primary buttons, current step. Text on --surface 7.56, --bg 7.23, --soft 6.80, --soft-2 6.26, brand wash 6.65. White label on it 7.56 */
  --brand-rgb: 40, 71, 195; /* for rgba(var(--brand-rgb), a) where base.css had rgba(0, 113, 227, a) */
  --brand-hover: #2F50CF;   /* hover of filled brand controls: white label 6.63; as text 6.63 / 6.34 */
  --brand-press: #213BA6;   /* pressed state: white label 9.37 */
  --brand-ink: #2341B4;     /* links and brand-coloured text: 8.45 on --surface, 8.08 on --bg, 7.60 on --soft, 7.43 on brand wash */
  --brand-wash: rgba(40, 71, 195, .08);  /* selected rows, current step, info banners, the paraf chip (= #EEF0FA over white, #E9ECF4 over --bg) */
  --brand-wash-solid: #EEF0FA;           /* the same wash as a solid colour (replaces #f7faff / #f6f9fd): brand-ink 7.43, brand 6.65 */
  --brand-deep: #15204F;    /* Tinta Pekat: dark brand panels, the ink app-icon tile, the dark social card. Paper text 14.87, white 15.54, Tinta Terang 7.58 */
  --brand-on-dark: #9DB2FF; /* Tinta Terang: brand colour on dark surfaces. 9.27 on #0E1017, 8.56 on #161922, 7.58 on --brand-deep */
  --favicon: #5977EA;       /* Tinta Sinyal: favicon only. 4.00 on a white tab, 3.05 on the inactive Chrome strip #DEE1E6, 3.02 on a dark tab #35363A, 4.03 on #202124 */
  --favicon-dark: #6D88F3;  /* favicon.svg under a dark colour scheme: 3.72 on #35363A, 4.96 on #202124, 3.09 on the Firefox dark tab #42414D, 3.25 on white */
  --mark: var(--brand);     /* colour of the symbol in the UI (header, empty states); switches to Tinta Terang in dark */

  /* Semantic accent (the interactive colour). */
  --accent: var(--brand);
  --accent-hover: var(--brand-hover);
  --accent-press: var(--brand-press);
  --accent-ink: var(--brand-ink);
  /* Meaningful graphics in the accent colour (WCAG 1.4.11, 3:1): the paraf glyph, step-rail dots and thread, the garis
     tulis loader, progress fills, the active-step dot. Same as --brand here; Tinta Terang in the dark block, where the
     filled-button blue is too dark to read as a graphic. 7.56 on --surface, 6.65 on brand wash, 6.26 on --soft-2. */
  --accent-stroke: var(--brand);
  --on-accent: #FFFFFF;
  --accent-on-dark: var(--brand-on-dark);
  --focus-ring: rgba(40, 71, 195, .72);  /* 3px outline, 2px offset: 3.94 on --surface, 3.87 on --bg, 3.73 on --soft */
  --selection: rgba(40, 71, 195, .16);   /* ::selection (= #DDE2F5 over white, --ink on it 13.74) */

  /* Dark surfaces that exist in the light theme too (landing dark panel, toast, rehearsal screen). */
  --dark-bg: #0E1017;       /* Malam */
  --dark-surface: #161922;
  --dark-ink: #ECEDF2;      /* 16.25 on --dark-bg, 15.02 on --dark-surface, 13.29 on --brand-deep */
  --dark-muted: #A1A5B2;    /* 7.73 on --dark-bg, 7.14 on --dark-surface, 6.32 on --brand-deep */

  /* ---------- Sorot: the highlighter, for evidence only ---------- */
  --sorot: #FFE35A;         /* always a fill behind --ink text (13.83); never text, decoration or a status colour; one phrase per screen */
  --sorot-soft: #FFF1A8;    /* long highlighted passages: --ink 15.53, --brand-ink 7.40, --muted 5.41 */
  --sorot-ink: #16181F;

  /* ---------- Document previews (student work): pure white, neutral frame ---------- */
  --doc-bg: #FFFFFF;
  --doc-frame: rgba(22, 24, 31, .12);

  /* ---------- Legacy names, mapped onto the brand ---------- */
  --blue: var(--brand);            /* was #0071e3 */
  --blue-hi: var(--brand-hover);   /* was #0077ed */
  --blue-ink: var(--brand-ink);    /* was #0066cc */
  --blue-wash: var(--brand-wash);  /* was rgba(0, 113, 227, .08) */
  --green: #34c759;                /* fills and dots only, not text */
  --green-ink: #1E7A44;            /* success text: 5.35 on --surface, 5.12 on --bg, 4.83 on its wash #E5F8E9 (the old #248a3d was 4.40, below AA) */
  --green-wash: rgba(52, 199, 89, .13);
  --orange: #ff9500;               /* fills and dots only */
  --orange-ink: #9A5300;           /* warning text: 5.82 on --surface, 5.56 on --bg, 5.23 on its wash #FFF1DE */
  --orange-wash: rgba(255, 149, 0, .13);
  --red: #ff3b30;                  /* fills and dots only */
  --red-ink: #C4170F;              /* error text and destructive buttons: 6.04 on --surface, 5.78 on --bg, 5.27 on its wash #FFEBEA */
  --red-wash: rgba(255, 59, 48, .1);
  --purple: #af52de;               /* legacy, not used by the app; never for brand or text */
  --indigo: #5856d6;               /* legacy, not used by the app; never for brand or text */
  --teal: #30b0c7;                 /* legacy, not used by the app */

  /* ---------- Shape ---------- */
  --r-xs: 8px;
  --r-s: 10px;
  --r: 14px;
  --r-l: 20px;
  --r-xl: 28px;
  --pill: 980px;

  --shadow-s: 0 1px 2px rgba(22, 24, 31, .05), 0 1px 1px rgba(22, 24, 31, .02);
  --shadow: 0 2px 8px rgba(22, 24, 31, .04), 0 12px 32px rgba(22, 24, 31, .06);
  --shadow-l: 0 10px 30px rgba(22, 24, 31, .07), 0 40px 90px rgba(22, 24, 31, .10);

  /* ---------- Motion: gerak pena (a steady stroke, then a short decisive flick; nothing bounces) ---------- */
  --ease: cubic-bezier(.28, .11, .32, 1);      /* kept: general UI transitions */
  --ease-out: cubic-bezier(.22, 1, .36, 1);    /* entrances and reveals */
  --ease-in-out: cubic-bezier(.65, 0, .35, 1); /* anything drawn or filled: strokes, progress, the Sorot sweep, moving between two states */
  --ease-in: cubic-bezier(.4, 0, 1, 1);        /* exits */
  --ease-flick: cubic-bezier(.3, 0, 0, 1);     /* only the final flick of the paraf draw */
  --spring: cubic-bezier(.3, 1.2, .5, 1);      /* was an 8% overshoot; now about 1%. Toggles and toasts only, never numbers */
  --dur-1: 120ms;   /* press, hover, focus */
  --dur-2: 200ms;   /* chips, toggles, tooltips, every exit */
  --dur-3: 320ms;   /* cards, toasts, drawers, the Sorot sweep, the rail thread */
  --dur-4: 480ms;   /* section reveals and step transitions (travel 12px) */
  --dur-5: 900ms;   /* chart draws and counters */
  --dur-sig: 1100ms; /* the Paraf signature draw, once per session */
  --travel: 12px;   /* reveal distance (was 30px) */
}

/* --------------------------------------------------------------------------
   Dark theme, opt-in. The app has no dark mode yet, so this block only applies
   when <html data-theme="auto"> is set AND the OS asks for dark. Adopt it once
   every component has been checked (hard-coded #fff and rgba(0,0,0,..) first),
   and add the dark theme-color meta tag in the same change.
   Surfaces: --bg #0E1017, --surface #161922, --soft #1D202A, --soft-2 #252935.
   -------------------------------------------------------------------------- */
@media (prefers-color-scheme: dark) {
  :root[data-theme="auto"] {
    color-scheme: dark;
    --bg: #0E1017;
    --surface: #161922;
    --surface-2: #1D202A;
    --soft: #1D202A;
    --soft-2: #252935;
    --ink: #ECEDF2;           /* 16.25 on --bg, 15.02 on --surface, 13.90 on --soft, 12.41 on --soft-2 */
    --ink-2: #C5C8D2;         /* 11.37 / 10.50 / 9.72 / 8.68 */
    --muted: #A1A5B2;         /* 7.73 / 7.14 / 6.61 / 5.90 */
    --faint: #8B909D;         /* 5.95 / 5.50 / 5.09 / 4.54 */
    --line: rgba(236, 237, 242, .10);
    --line-2: rgba(236, 237, 242, .16);
    --line-control: #737A8C;  /* 4.43 on --bg, 4.09 on --surface, 3.79 on --soft */
    --brand: #3A57D8;         /* filled buttons only: white label 5.94. As a graphic it is only 2.95 on --surface and 3.20 on --bg, so graphics use --accent-stroke */
    --brand-rgb: 58, 87, 216;
    --brand-hover: #4361DB;   /* white label 5.29 */
    --brand-press: #2F4CCB;   /* white label 6.96 */
    --brand-ink: #9DB2FF;     /* links and brand text = Tinta Terang: 9.27 / 8.56 / 7.93 / 7.08 */
    --accent-stroke: #9DB2FF; /* paraf glyph, rail, garis tulis, progress fills, active-step dot: 8.56 on --surface, 9.27 on --bg, 7.93 on --soft, 6.85 on brand wash */
    --mark: #9DB2FF;          /* the symbol on dark is always Tinta Terang, never the filled-button blue */
    --brand-wash: rgba(157, 178, 255, .12);  /* = #262B3D over --surface: --ink 12.01, --brand-ink 6.85 */
    --brand-wash-solid: #252B40;             /* --ink 11.99, --brand-ink 6.84 */
    --focus-ring: rgba(157, 178, 255, .75);  /* 5.66 on --bg */
    --selection: rgba(157, 178, 255, .28);   /* = #3C4460 over --surface, --ink on it 8.21 */
    --sorot: #F0D44A;         /* short highlights stay a yellow fill with --sorot-ink text (12.01) */
    --sorot-soft: rgba(240, 212, 74, .18);   /* long passages: a dim band with the normal --ink text (= #3D3B29 over --surface, 9.68) */
    --sorot-ink: #16181F;
    --green-ink: #4CC38A;     /* 8.58 / 7.92 / 7.34 */
    --orange-ink: #F7A35C;    /* 9.36 / 8.65 / 8.01 */
    --red-ink: #FF8B80;       /* 8.38 / 7.74 / 7.16 */
    --shadow-s: 0 1px 2px rgba(0, 0, 0, .4);
    --shadow: 0 2px 8px rgba(0, 0, 0, .3), 0 12px 32px rgba(0, 0, 0, .35);
    --shadow-l: 0 10px 30px rgba(0, 0, 0, .4), 0 40px 90px rgba(0, 0, 0, .5);
    /* --doc-bg stays #FFFFFF: a student's paper is always previewed on white. */
  }
}

/* App aliases (UI spec names), all mapped onto the brand values above. */
:root {
  --surface-1: var(--surface);
  --bg-app: #F6F6F3;               /* the app canvas, one step below Kertas so white cards stand apart */
  --bg-rail: #EFEFEB;
  --line-1: var(--line);
  --fill-1: rgba(22, 24, 31, .05);
  --fill-2: rgba(22, 24, 31, .09);
  --text-4: var(--faint);
  --success: var(--green); --success-ink: var(--green-ink); --success-wash: var(--green-wash); --success-line: rgba(52, 199, 89, .38);
  --warning: var(--orange); --warning-ink: var(--orange-ink); --warning-wash: var(--orange-wash); --warning-text: #6B3A00;
  --danger: var(--red); --danger-ink: var(--red-ink); --danger-wash: var(--red-wash);
  --surface-inverse: rgba(22, 24, 31, .94);
  --text-inv-1: var(--dark-ink);
  --text-inv-2: var(--dark-muted);
  --accent-wash: var(--brand-wash);
  --accent-wash-2: rgba(var(--brand-rgb), .14);
  --accent-ring: rgba(var(--brand-rgb), .32);
  --scroll-thumb: rgba(22, 24, 31, .22);
  --radius-xs: 6px; --radius-s: var(--r-s); --radius-m: var(--r); --radius-l: 18px; --radius-xl: 24px; --radius-pill: var(--pill);
  --elev-1: 0 1px 2px rgba(22, 24, 31, .05);
  --elev-2: 0 6px 20px rgba(22, 24, 31, .07), 0 1px 3px rgba(22, 24, 31, .04);
  --elev-3: 0 24px 64px rgba(22, 24, 31, .18), 0 2px 8px rgba(22, 24, 31, .06);
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: var(--font);
  font-size: 17px;
  line-height: 1.47;
  letter-spacing: -.012em;
  color: var(--ink);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

img, svg { display: block; max-width: 100%; }
/* html2canvas finds each font's baseline with a 1×1 image it appends to <body> next to a line of text. That image must
   stay inline: as a block (the rule above) every exported line of a poster or slide lands about 0.4 em too low. */
body > div > img[width="1"][height="1"] { display: inline !important; }
button { font: inherit; color: inherit; }
a { color: var(--blue-ink); text-decoration: none; }
a:hover { text-decoration: underline; }
::selection { background: var(--selection); }

/* ---------- Typography ---------- */
.display, .h1, .h2, .h3, .h4 { font-family: var(--font-display); margin: 0; color: var(--ink); }
.display { font-size: clamp(44px, 7.2vw, 88px); line-height: 1.04; font-weight: 700; letter-spacing: -.035em; }
.h1 { font-size: clamp(36px, 5vw, 64px); line-height: 1.06; font-weight: 700; letter-spacing: -.032em; }
.h2 { font-size: clamp(30px, 3.6vw, 48px); line-height: 1.08; font-weight: 700; letter-spacing: -.028em; }
.h3 { font-size: clamp(22px, 2.2vw, 28px); line-height: 1.16; font-weight: 600; letter-spacing: -.02em; }
.h4 { font-size: 21px; line-height: 1.24; font-weight: 600; letter-spacing: -.016em; }
.lead { font-size: clamp(19px, 1.7vw, 24px); line-height: 1.38; color: var(--muted); letter-spacing: -.016em; font-weight: 400; }
.eyebrow { font-size: 14px; font-weight: 600; letter-spacing: -.005em; color: var(--blue-ink); margin: 0 0 10px; }
.muted { color: var(--muted); }
.faint { color: var(--faint); }
.small { font-size: 14px; line-height: 1.43; }
.tiny { font-size: 12px; line-height: 1.34; letter-spacing: -.003em; }
.mono { font-family: var(--mono); letter-spacing: 0; }
.grad-text { color: var(--ink); }   /* retired: the brand has no gradient text */

/* ---------- Buttons ---------- */
.btn {
  --h: 44px;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  height: var(--h); padding: 0 22px;
  border: 0; border-radius: var(--pill);
  font: 500 15px/1 var(--font); letter-spacing: -.01em;
  cursor: pointer; user-select: none; white-space: nowrap; text-decoration: none !important;
  transition: transform var(--dur-1) var(--ease), background-color var(--dur-1) var(--ease), box-shadow var(--dur-2) var(--ease), color var(--dur-1) var(--ease);
}
.btn:active { transform: scale(.97); }
.btn svg { width: 17px; height: 17px; flex: none; }
.btn-primary { background: var(--accent); color: var(--on-accent); font-weight: 600; }
.btn-primary:hover { background: var(--accent-hover); }
.btn-primary:active { background: var(--accent-press); }
.btn-dark { background: var(--ink); color: var(--surface); }
.btn-dark:hover { background: #000; }
.btn-gray { background: var(--fill-1); color: var(--ink); }
.btn-gray:hover { background: var(--fill-2); }
.btn-tinted { background: var(--accent-wash); color: var(--accent-ink); }
.btn-tinted:hover { background: var(--accent-wash-2); }
.btn-ghost { background: transparent; color: var(--accent-ink); padding: 0 12px; }
.btn-ghost:hover { background: var(--accent-wash); }
.btn-white { background: var(--surface); color: var(--ink); box-shadow: var(--shadow-s); }
.btn-danger { background: var(--red-wash); color: var(--red-ink); }
.btn-lg { --h: 54px; padding: 0 30px; font-size: 17px; }
.btn-sm { --h: 36px; padding: 0 14px; font-size: 13px; gap: 6px; }
/* Keyboard focus is always visible (mouse clicks keep the clean look). */
.btn:focus-visible, .icon-btn:focus-visible, a:focus-visible, summary:focus-visible, [tabindex]:focus-visible, .seg-b:focus-visible, .choice:focus-visible, .type:focus-visible, .goal:focus-visible {
  outline: 3px solid var(--focus-ring); outline-offset: 2px;
}
.btn-sm svg { width: 15px; height: 15px; }
.btn-icon { width: var(--h); padding: 0; }
/* Disabled stays readable (the label often says why the step cannot go on): muted on soft-2 is 5.12:1. */
.btn[disabled], .btn.is-disabled { opacity: 1; background: var(--soft-2); color: var(--muted); box-shadow: none; pointer-events: none; }
.btn-ghost[disabled], .btn-ghost.is-disabled { background: transparent; color: var(--faint); }
/* Not available yet, but still readable and still clickable, so the click can say what is missing (ui.js foot). */
.btn[aria-disabled="true"] { color: var(--faint); box-shadow: none; cursor: not-allowed; }
.btn[aria-disabled="true"]:active { transform: none; }
.btn-primary[aria-disabled="true"], .btn-primary[aria-disabled="true"]:hover { background: var(--soft-2); box-shadow: none; }
.btn.is-loading { pointer-events: none; }
.btn .spin { width: 16px; height: 16px; }

.link-chev { display: inline-flex; align-items: center; gap: 2px; font-weight: 400; color: var(--blue-ink); }
.link-chev::after { content: ""; width: 7px; height: 7px; border-right: 1.6px solid currentColor; border-top: 1.6px solid currentColor; transform: rotate(45deg); margin-left: 6px; transition: transform .25s var(--ease); }
.link-chev:hover { text-decoration: none; }
.link-chev:hover::after { transform: translateX(3px) rotate(45deg); }

/* ---------- Form controls ---------- */
.field {
  width: 100%; height: 48px; padding: 0 16px;
  border-radius: 12px; border: 1px solid var(--line-control);
  background: var(--surface); color: var(--ink);
  font: inherit; font-size: 16px; letter-spacing: -.01em;
  transition: border-color .2s ease, box-shadow .2s ease, background-color .2s ease;
}
.field::placeholder { color: var(--faint); }
.field:hover { border-color: var(--ink-2); }
.field:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 4px rgba(var(--brand-rgb), .16); }
textarea.field { height: auto; min-height: 112px; padding: 13px 16px; resize: vertical; line-height: 1.5; }
select.field { appearance: none; padding-right: 40px; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5l5 5 5-5' fill='none' stroke='%236e6e73' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 16px center; }
.label { display: block; font-size: 13px; font-weight: 600; color: var(--ink-2); margin: 0 0 7px; letter-spacing: -.005em; }
.hint { font-size: 13px; color: var(--muted); margin-top: 6px; }

/* ---------- Pills & badges ---------- */
.pill {
  display: inline-flex; align-items: center; gap: 6px;
  height: 26px; padding: 0 11px; border-radius: var(--pill);
  font-size: 12.5px; font-weight: 600; letter-spacing: -.003em; white-space: nowrap;
  background: var(--soft); color: var(--ink-2);
}
.pill svg { width: 13px; height: 13px; }
.pill-blue { background: var(--blue-wash); color: var(--blue-ink); }
.pill-green { background: var(--green-wash); color: var(--green-ink); }
.pill-orange { background: var(--orange-wash); color: var(--orange-ink); }
.pill-red { background: var(--red-wash); color: var(--red-ink); }
.pill-dark { background: var(--ink); color: var(--surface); }

/* ---------- Motion ---------- */
.reveal { opacity: 0; transform: translateY(var(--travel)); transition: opacity var(--dur-4) var(--ease-out), transform var(--dur-4) var(--ease-out); }
.reveal.in { opacity: 1; transform: none; }
.reveal.d1 { transition-delay: .08s; } .reveal.d2 { transition-delay: .16s; } .reveal.d3 { transition-delay: .24s; } .reveal.d4 { transition-delay: .32s; }

@keyframes spin { to { transform: rotate(360deg); } }
@keyframes pop { from { transform: scale(.6); opacity: 0; } to { transform: scale(1); opacity: 1; } }
@keyframes rise { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes shimmer { 0% { background-position: -400px 0; } 100% { background-position: 400px 0; } }
@keyframes draw { to { stroke-dashoffset: 0; } }

.spin { animation: spin .9s linear infinite; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal { opacity: 1; transform: none; transition: none; }
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; }
}

/* ---------- Utilities ---------- */
.sr-only { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
.row { display: flex; align-items: center; gap: 12px; }
.row-wrap { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.spacer { flex: 1; }
.center { text-align: center; }
.mt-0 { margin-top: 0; } .mt-1 { margin-top: 8px; } .mt-2 { margin-top: 16px; } .mt-3 { margin-top: 24px; } .mt-4 { margin-top: 36px; } .mt-5 { margin-top: 56px; }
.mb-0 { margin-bottom: 0; } .mb-1 { margin-bottom: 8px; } .mb-2 { margin-bottom: 16px; } .mb-3 { margin-bottom: 24px; }
.hidden { display: none !important; }
