/* ============================================================
   LINKPLAY — Base Styles v3
   Theme CSS vars override these. Load a theme AFTER this file.
   ============================================================ */

/* ── Safe defaults (overridden by theme files) ─────────────── */
:root {
  /* ================================================================
     BLUEPRINT — drafting paper.
     Light ground, measured grid, hard edges, signal orange on anything
     actionable. Replaces the inherited dark/neon palette entirely.
     ================================================================ */

  /* Ground */
  --gl-bg:           #EAEFF4;
  --gl-header:       rgba(234,239,244,0.88);
  --gl-header-solid: rgba(234,239,244,0.98);
  --gl-drawer:       #EAEFF4;
  --gl-bg2:          #E1E8EF;
  --gl-surface:      #EAEFF4;
  --gl-surface2:     #DDE6ED;
  --gl-card:         #EAEFF4;

  /* Ink */
  --gl-ink:          #0F2233;
  --gl-ink2:         #3D5666;
  --gl-muted:        #6C8398;

  /* Rules — hairline for texture, ink for structure */
  --gl-line:         #B9C9D6;
  --gl-lineA:        #0F2233;
  --gl-grid:         #D8E2EA;
  --gl-bw:           1.5px;

  /* Accent — signal orange, used only on what you can act on */
  --gl-accent:       #D4581F;
  --gl-accent2:      #A63F13;
  --gl-dim:          rgba(212,88,31,0.08);
  --gl-glow:         rgba(212,88,31,0.16);

  /* Semantic — kept distinct from the accent so status still reads as status */
  --gl-red:          #B5341F;
  --gl-yellow:       #A8730F;
  --gl-blue:         #1F6FA8;
  --gl-purple:       #6B4FA0;
  --gl-green:        #1E7A5A;

  /* Shape — square. Blueprint has no rounded corners. */
  --gl-r:            0px;
  --gl-rl:           0px;

  /* Type */
  --gl-fd:           'Bricolage Grotesque', 'Archivo', system-ui, sans-serif;
  --gl-fb:           'Public Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --gl-fm:           'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Depth — hard offset, never a blur halo */
  --gl-shadow:       3px 3px 0 rgba(15,34,51,0.09);
  --gl-shadowL:      6px 6px 0 rgba(15,34,51,0.11);
}

/* ── Reset ──────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; }

body {
  font-family: var(--gl-fb);
  background: var(--gl-bg);
  color: var(--gl-ink);
  -webkit-font-smoothing: antialiased;
  font-size: 16px;
  line-height: 1.65;
  overflow-x: hidden;
  transition: background .4s, color .4s;
}


/* ── Typography ─────────────────────────────────────────────── */
h1, h2, h3, h4 {
  font-family: var(--gl-fd);
  font-weight: 800;
  letter-spacing: -.035em;
  line-height: 1.0;
  text-wrap: balance;
  color: var(--gl-ink);
}
h1 { font-size: clamp(3.8rem, 9vw, 9rem); }
h2 { font-size: clamp(2.2rem, 5vw, 4rem); }
h3 { font-size: clamp(1.4rem, 3vw, 2rem); }
/* Was font-weight: 300 — index.html loads Public Sans 300..700
   only, so 300 was never available and rendered synthesised or snapped to
   400. (A later block in this file already re-set it; the line was dead as
   well as wrong.) */
p  { font-weight: 400; font-size: 1rem; }
a  { color: inherit; text-decoration: none; }
button { font-family: inherit; cursor: pointer; border: 0; background: none; color: inherit; padding: 0; }
input, select, textarea { font-family: inherit; font-size: inherit; }
img { display: block; }

/* ── Buttons ────────────────────────────────────────────────── */
.gl-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 13px 28px;
  font-family: var(--gl-fb); font-weight: 600; font-size: 13px;
  letter-spacing: .02em;
  border-radius: 0; border: var(--gl-bw) solid var(--gl-lineA);
  background: var(--gl-surface); color: var(--gl-ink);
  transition: all .18s; white-space: nowrap; user-select: none;
}
.gl-btn:hover  { background: var(--gl-surface2); border-color: rgba(15,34,51,.13); transform: translateY(-1px); }
.gl-btn:active { transform: translateY(0); opacity: .9; }
.gl-btn-primary {
  background: var(--gl-accent); color: var(--gl-btn-ink, #000); border-color: transparent;
  box-shadow: none;
}
.gl-btn-primary:hover { filter: brightness(1.12); box-shadow: 3px 3px 0 rgba(15,34,51,.16); }
.gl-btn-outline { border-color: var(--gl-lineA); background: var(--gl-dim); color: var(--gl-accent); }
.gl-btn-outline:hover { background: rgba(var(--gl-accent), .18); border-color: var(--gl-lineA); filter: brightness(1.08); }
.gl-btn-ghost { border-color: transparent; background: transparent; }
.gl-btn-ghost:hover { background: var(--gl-dim); border-color: var(--gl-lineA); }
.gl-btn-sm { padding: 7px 16px; font-size: 11px; }
.gl-btn-block { width: 100%; }
.gl-btn:disabled { opacity: .4; cursor: not-allowed; transform: none !important; }

/* ── Inputs ─────────────────────────────────────────────────── */
.gl-input {
  width: 100%; padding: 13px 17px;
  border: 1px solid var(--gl-line); border-radius: var(--gl-r);
  background: var(--gl-surface); color: var(--gl-ink); font-size: 15px;
  outline: none; transition: border-color .15s, box-shadow .15s;
}
.gl-input:focus { border-color: var(--gl-accent); box-shadow: 0 0 0 3px var(--gl-dim); }
.gl-input::placeholder { color: var(--gl-muted); }
.gl-label { font-size: 10px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--gl-ink2); display: block; margin-bottom: 6px; }

/* ── Cards ──────────────────────────────────────────────────── */
.gl-card {
  background: var(--gl-card);
  border: 1px solid var(--gl-line);
  border-radius: var(--gl-rl);
  box-shadow: var(--gl-shadow);
  transition: background .2s, box-shadow .22s, transform .22s, border-color .22s;
  position: relative;
  overflow: hidden;
}
.gl-card:hover { box-shadow: var(--gl-shadowL); transform: translateY(-4px); border-color: var(--gl-lineA); }

/* Glass shimmer on hover */
.gl-card::before {
  content: '';
  position: absolute; inset: 0; opacity: 0; transition: opacity .3s; pointer-events: none;
  background: linear-gradient(135deg, rgba(15,34,51,0.06) 0%, transparent 60%);
  border-radius: inherit;
}
.gl-card:hover::before { opacity: 1; }

/* ── Empty state ────────────────────────────────────────────────
   The site had no empty state as a first-class concept: data-driven sections
   rendered their heading unconditionally and their content conditionally, so
   an empty database degraded into a promise with nothing under it. A visitor
   could not tell "no games yet" from "this page is broken".

   This is that missing state. It borrows .gl-card's surface and radius so it
   reads as part of the system, but takes a DASHED border — the whole visual
   argument is "something belongs here and it isn't here yet", which a solid
   card edge (used for real content everywhere else) would contradict. Every
   instance carries at least one real next action; none may terminate in dead
   space, which is what the four bare headings previously did.
   ─────────────────────────────────────────────────────────────── */
.gl-empty {
  display: flex; flex-direction: column; align-items: center;
  text-align: center; gap: 14px;
  padding: clamp(38px, 6vw, 62px) clamp(22px, 5vw, 44px);
  background: var(--gl-card);
  border: 1px dashed rgba(15,34,51,0.16);
  border-radius: var(--gl-rl);
}
.gl-empty-mark {
  width: 46px; height: 46px; border-radius: 0;
  display: grid; place-items: center;
  background: var(--gl-dim); border: 1px solid var(--gl-lineA);
  color: var(--gl-accent); flex-shrink: 0;
}
.gl-empty-title { font-size: 20px; font-weight: 700; letter-spacing: -.02em; line-height: 1.25; color: var(--gl-ink); }
.gl-empty-body  { font-size: 15px; color: var(--gl-ink2); line-height: 1.7; max-width: 48ch; }
.gl-empty-acts  { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; margin-top: 8px; }
/* Inline variant — for a filter that matched nothing, where the section around
   it is otherwise populated and a full card would over-weight the message. */
.gl-empty-sm { padding: 30px 24px; gap: 10px; }
.gl-empty-sm .gl-empty-title { font-size: 16px; }
.gl-empty-sm .gl-empty-body  { font-size: 14px; }

/* ── Badges ─────────────────────────────────────────────────── */
.gl-badge {
  display: inline-flex; align-items: center;
  padding: 3px 11px; font-size: 10px; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase;
  border-radius: 0; border: 1px solid transparent;
}
.gl-badge-live  { background: rgba(212,88,31,.1);  color: var(--gl-accent); border-color: rgba(212,88,31,.25); }
.gl-badge-hot   { background: rgba(255,209,102,.1); color: var(--gl-yellow); border-color: rgba(255,209,102,.25); }
.gl-badge-new   { background: rgba(99,179,237,.1);  color: var(--gl-blue);   border-color: rgba(99,179,237,.25); }
.gl-badge-feat  { background: var(--gl-accent); color: #000; }

/* ── Eyebrow ────────────────────────────────────────────────── */
.gl-eye {
  font-size: 10px; font-weight: 700; letter-spacing: .22em; text-transform: uppercase;
  color: var(--gl-accent); display: flex; align-items: center; gap: 10px; margin-bottom: 16px;
}
.gl-eye::before { content: ''; width: 28px; height: 2px; background: var(--gl-accent); border-radius: 0; flex-shrink: 0; }

/* ── Divider ────────────────────────────────────────────────── */
.gl-hr { width: 100%; height: 1px; background: var(--gl-line); }

/* ── Marquee ────────────────────────────────────────────────── */
@keyframes glMq { from { transform: translateX(0); } to { transform: translateX(-50%); } }
.gl-mq { overflow: hidden; background: var(--gl-surface); border-top: 1px solid var(--gl-line); border-bottom: 1px solid var(--gl-line); }
.gl-mq-track { display: flex; gap: 56px; padding: 14px 0; white-space: nowrap; animation: glMq 38s linear infinite; width: max-content; }
.gl-mq-item { font-weight: 600; letter-spacing: .12em; font-size: 11px; text-transform: uppercase; color: var(--gl-muted); display: inline-flex; align-items: center; gap: 14px; }
.gl-mq-dot { color: var(--gl-accent); font-size: 14px; }

/* ── Header nav links ───────────────────────────────────────── */
/* Sizing lives here rather than as inline style on the element, so the touch
   target can be widened on small screens — an inline style would win over any
   media query. Only the active/dynamic colours stay inline in the component. */
.gl-navlink {
  padding: 7px 12px;
  font-family: inherit;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: .03em;
  border-radius: 0;
  color: var(--gl-ink2);
  background: transparent;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: none;
  cursor: pointer;
  transition: color .15s, background .15s;
}
.gl-navlink:hover { color: var(--gl-accent); background: var(--gl-dim); }
.gl-navlink.is-active { color: var(--gl-accent); background: var(--gl-dim); }

/* Keyboard focus was invisible before — nothing indicated where you were. */
.gl-navlink:focus-visible,
.gl-iconbtn:focus-visible {
  outline: 2px solid var(--gl-accent);
  outline-offset: 2px;
  color: var(--gl-accent);
}

/* ── Focus visibility, everything else ──────────────────────────
   The nav had a designed focus ring; nothing else did. Buttons and links fell
   back to the UA ring (foreign to the design, easy to lose on near-black), and
   two inputs actively suppressed it with `outline: none` and compensated with a
   border-colour change that measured 1.79:1 — under the 3:1 that WCAG 1.4.11
   requires for a non-text indicator. One rule, matching the nav treatment.
   On Blueprint's paper ground the accent measures only 3.48:1, so the ring is
   drawn in ink (#0F2233 on #EAEFF4 = 14.1:1) — unambiguous wherever it lands,
   and consistent with a drafting palette where ink is the drawing colour.     */
a:focus-visible,
button:focus-visible,
.gl-btn:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--gl-ink);
  outline-offset: 2px;
  border-radius: 0;
}
/* Inputs already carry their own radius; don't square their ring off. */
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
.gl-input:focus-visible { border-radius: inherit; }

/* Icon-only controls (hamburger) need an accessible hit area too. */
.gl-iconbtn {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 44px; min-height: 44px;
  border: none; background: transparent; cursor: pointer;
  border-radius: 0; color: inherit;
}

/* Touch targets: WCAG 2.5.5 / Apple HIG want ~44px. The drawer links were 31px
   tall, and the hamburger 42x38. Below the drawer breakpoint the links stack,
   so they can take the full width. */
@media (max-width: 900px) {
  .gl-navlink {
    min-height: 44px;
    padding: 11px 14px;
    width: 100%;
    justify-content: flex-start;
  }
}
/* Coarse pointer on a wider screen (tablet): keep the horizontal layout but
   still give it a real touch height. */
@media (pointer: coarse) and (min-width: 901px) {
  .gl-navlink { min-height: 44px; }
}

/* ── Footer links ───────────────────────────────────────────────
   Were 19px tall with an 11px gap. On desktop that is a fine dense list; on a
   touch screen it is a column of 19px targets, which is the one place the
   site's otherwise careful 44px discipline had a hole in it. Desktop keeps the
   density; below the drawer breakpoint each link takes a real touch height and
   the gap collapses into it so the footer doesn't balloon.
   ─────────────────────────────────────────────────────────────── */
/* The wordmark is a link home in both the header and the footer, and measured
   170×26 / 195×30. Wide enough, short enough to miss. */
.gl-logobtn { display: flex; align-items: center; min-height: 44px; }

.gl-flinks { gap: 11px; }
.gl-flink {
  display: inline-flex; align-items: center;
  font-size: 15px; color: inherit; opacity: .7;
  background: none; border: none; padding: 0; cursor: pointer;
  text-align: left; transition: opacity .15s;
}
.gl-flink:hover { opacity: 1; }
@media (max-width: 900px) {
  .gl-flinks { gap: 0; }
  /* Full-width so the target is 44px in BOTH axes — "Blog" is 31px of text,
     and a 31x44 target still fails WCAG 2.5.5. */
  .gl-flink { min-height: 44px; display: flex; width: 100%; }
}
@media (pointer: coarse) and (min-width: 901px) {
  .gl-flinks { gap: 0; }
  .gl-flink { min-height: 44px; display: flex; width: 100%; }
}

/* ── Mobile drawer ──────────────────────────────────────────────
   The drawer was a partial-height panel with no backdrop: page content stayed
   fully visible beside and behind it, its bottom edge cut arbitrarily across
   the hero, and the page scrolled freely underneath. All three read as an
   unfinished overlay rather than a mode you are in.
   ─────────────────────────────────────────────────────────────── */
.gl-scrim {
  position: fixed; inset: 0;
  background: rgba(0,0,0,.62);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  /* Under the header (z 500) so the panel stays lit, over everything else. */
  z-index: 480;
  border: 0; padding: 0; width: 100%;
  cursor: pointer;
  animation: glScrimIn .18s ease;
}
@keyframes glScrimIn { from { opacity: 0 } to { opacity: 1 } }

.gl-drawer-panel {
  /* Full height under the 66px bar — dvh so mobile browser chrome collapsing
     doesn't leave a strip of page showing through at the bottom. */
  height: calc(100dvh - 66px);
  overflow-y: auto;
  overscroll-behavior: contain;
  /* .gl-show-mob sets `display:block !important`, which silently beat the
     element's inline display:flex — so the drawer's gap never applied and its
     links sat flush. Reassert flex at the same weight. */
  display: flex !important;
  flex-direction: column;
  gap: 4px;
}
/* dvh is well supported now, but keep a floor for anything that lacks it. */
@supports not (height: 100dvh) {
  .gl-drawer-panel { height: calc(100vh - 66px); }
}
/* Set on <body> while the drawer is open. */
.gl-noscroll { overflow: hidden !important; }

/* ── Page progress bar ──────────────────────────────────────── */
#gl-bar { position: fixed; top: 0; left: 0; height: 2px; z-index: 9997; background: linear-gradient(90deg, var(--gl-accent), var(--gl-accent2)); transition: width .4s; box-shadow: 0 0 10px var(--gl-glow); pointer-events: none; }

/* ── Toast ──────────────────────────────────────────────────── */
@keyframes glToast { from { opacity: 0; transform: translateY(10px) translateX(-50%); } to { opacity: 1; transform: translateY(0) translateX(-50%); } }
.gl-toast-wrap { animation: glToast .22s cubic-bezier(.34,1.56,.64,1); }

/* ── Grid bg / orbs ─────────────────────────────────────────── */
.gl-gridbg {
  position: absolute; inset: 0; pointer-events: none;
  background-image: linear-gradient(rgba(212,88,31,.032) 1px, transparent 1px), linear-gradient(90deg, rgba(212,88,31,.032) 1px, transparent 1px);
  background-size: 48px 48px;
}
/* Blueprint has no ambient glow — the orbs were Gamingo atmosphere. */
.gl-orb { display: none !important; }

/* ── Animations ─────────────────────────────────────────────── */
@keyframes glFloat { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-22px); } }
@keyframes glGlow  { 0%,100% { opacity: 1; } 50% { opacity: 1; } }
@keyframes glFade  { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: translateY(0); } }
.gl-float { animation: glFloat 7s ease-in-out infinite; }
.gl-glow-text { animation: glGlow 3s ease-in-out infinite; }

/* ── Scrollbar ──────────────────────────────────────────────── */
::-webkit-scrollbar { width: 5px; }
::-webkit-scrollbar-track { background: var(--gl-bg2); }
::-webkit-scrollbar-thumb { background: var(--gl-muted); border-radius: 0; }

/* ── Utility ────────────────────────────────────────────────── */
.gl-hide { display: none !important; }

/* ── Layout ─────────────────────────────────────────────────── */
.gl-wrap { max-width: 1380px; margin: 0 auto; padding: 0 5%; }
.gl-2col  { display: grid; grid-template-columns: 1fr 1fr;    gap: 64px; align-items: start; }
.gl-25col { display: grid; grid-template-columns: 1.4fr 2fr;  gap: 64px; align-items: start; }
.gl-footer{ display: grid; grid-template-columns: 2fr 1fr 1fr 1fr; gap: 40px; }
/* The "Games" column is dropped rather than rendered empty when the catalogue
   has nothing in it — a heading over 246px of nothing. The remaining columns
   re-flow instead of leaving a hole in the grid. */
.gl-footer-3 { grid-template-columns: 2fr 1fr 1fr; }
.gl-auto  { display: grid; grid-template-columns: repeat(auto-fill, minmax(270px, 1fr)); gap: 24px; }
.gl-auto3 { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 24px; }

/* ── Section ────────────────────────────────────────────────── */
.gl-section { padding: 88px 5% 100px; max-width: 1380px; margin: 0 auto; }
.gl-section-sm { padding: 60px 5%; max-width: 1380px; margin: 0 auto; }

/* ── Responsive ─────────────────────────────────────────────── */
@media (max-width: 1060px) {
  .gl-footer { grid-template-columns: 2fr 1fr 1fr !important; }
}
@media (max-width: 860px) {
  .gl-hide-mob { display: none !important; }
  .gl-show-mob { display: block !important; }
  .gl-2col  { grid-template-columns: 1fr !important; gap: 40px !important; }
  .gl-25col { grid-template-columns: 1fr !important; gap: 40px !important; }
  .gl-footer { grid-template-columns: 1fr 1fr !important; }
  .gl-auto  { grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 18px; }
}
@media (min-width: 861px) {
  .gl-show-mob { display: none !important; }
}
@media (max-width: 560px) {
  .gl-footer { grid-template-columns: 1fr !important; }
  h1 { font-size: 3rem; }
  h2 { font-size: 2.2rem; }
  /* Stacked hero CTAs were 213px and 232px wide — two ragged left-aligned
     pills. At this width they get the full column instead. */
  .gl-hero-cta { flex-direction: column; align-items: stretch; }
  .gl-hero-cta > .gl-btn { width: 100%; }
}

/* ── Iridescent Card Effect ──────────────────────────────────
   Applied to .gl-iri-wrap. JS drives CSS vars via RAF.
   ───────────────────────────────────────────────────────────── */
.gl-iri-stage {
  position: relative;
  perspective: 900px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.gl-iri-card {
  --rx: 0deg;
  --ry: 0deg;
  --mx: 50%;
  --my: 50%;
  --glow: 0;
  --iri-angle: 180deg;
  position: relative;
  transform-style: preserve-3d;
  transform: rotateX(var(--rx)) rotateY(var(--ry)) translateZ(0);
  transition: transform 0.5s cubic-bezier(.2,.7,.2,1), box-shadow 0.4s ease;
  will-change: transform;
  border-radius: 0;
  overflow: hidden;
  cursor: pointer;
}

/* Iridescent rainbow — color-dodge lifts bright areas */
.gl-iri-card::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: conic-gradient(
    from calc(var(--iri-angle)) at var(--mx) var(--my),
    #ff5ad6 0deg,
    #ffd86b 60deg,
    #6bffd1 120deg,
    #6ba3ff 200deg,
    #c46bff 270deg,
    #ff5ad6 360deg
  );
  mix-blend-mode: color-dodge;
  opacity: calc(0.12 + 0.55 * var(--glow));
  filter: saturate(1.5) blur(2px);
  transition: opacity 0.3s ease;
  pointer-events: none;
  z-index: 2;
}

/* Specular — white radial following cursor */
.gl-iri-card::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(
    circle at var(--mx) var(--my),
    rgba(15,34,51,0.7) 0%,
    rgba(15,34,51,0.15) 15%,
    rgba(15,34,51,0) 40%
  );
  mix-blend-mode: soft-light;
  opacity: calc(0.3 + 0.7 * var(--glow));
  transition: opacity 0.3s ease;
  pointer-events: none;
  z-index: 3;
}

/* Outer aura */
.gl-iri-aura {
  position: absolute;
  inset: -20px;
  border-radius: 0;
  background: radial-gradient(
    closest-side,
    rgba(107,163,255,0.2) 0%,
    rgba(255,90,214,0.12) 50%,
    transparent 100%
  );
  filter: blur(16px);
  opacity: calc(0.1 + 0.9 * var(--glow, 0));
  transition: opacity 0.45s ease;
  pointer-events: none;
  z-index: 0;
}


/* ================================================================
   The site shipped four swappable themes behind a palette button.
   That is now one theme. Everything below was the appended override
   file, kept in place so the cascade order — and therefore the
   rendering — is unchanged; only its values are Blueprint's now.
   index.html loads the fonts with a preconnect, not an @import, so
   they are not render-blocking.
================================================================ */
/* ================================================================
   LINKPLAY — Blueprint (replaced the inherited dark + neon palette)
   Drafting paper · ink rules · signal orange · measured grid, no glow
   Fonts: Bricolage Grotesque (display) + Public Sans (body) + JetBrains Mono
================================================================ */

/* Base */
body {
  background-color: var(--gl-bg);
  background-image:
    linear-gradient(var(--gl-grid) 1px, transparent 1px),
    linear-gradient(90deg, var(--gl-grid) 1px, transparent 1px);
  background-size: 30px 30px;
  color: var(--gl-ink);
  font-family: var(--gl-fb);
  font-size: 16px;
  line-height: 1.65;
}



/* Typography */
h1, h2, h3, h4 {
  font-family: var(--gl-fd);
  font-weight: 800;
  letter-spacing: -.035em;
  line-height: 1.02;
  color: var(--gl-ink);
}
h1 { font-size: clamp(3.4rem, 8vw, 8.5rem); font-weight: 800; letter-spacing: -.04em; }
h2 { font-size: clamp(2rem, 5vw, 3.8rem); font-weight: 800; }
h3 { font-size: clamp(1.3rem, 3vw, 2rem); font-weight: 800; }
p  { font-weight: 400; }

/* ── Page title role ────────────────────────────────────────────
   Eight of ten pages had no <h1> at all and led with an <h2> — an SEO defect
   and the reason there were three unrelated "page title" sizes on the site
   (102.4px on home, 60.8px on the eight h2-led pages, 44.8px on /profile).
   Those leads are now <h1 class="gl-ptitle">, which pins one size for the
   role. The bare h1 rule above stays for the home hero, which is a different
   role — a wordmark-scale statement, not a page label. */
.gl-ptitle {
  font-size: clamp(2rem, 5vw, 3.8rem);
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 1.08;
}

/* Glass card override */
.gl-card {
  background: var(--gl-card);
  backdrop-filter: blur(24px) saturate(160%);
  -webkit-backdrop-filter: blur(24px) saturate(160%);
  border: 1px solid rgba(15,34,51,0.09);
  box-shadow: var(--gl-shadow);
}
.gl-card:hover {
  background: var(--gl-surface2);
  border-color: rgba(15,34,51,0.14);
  box-shadow: var(--gl-shadowL);
  transform: translateY(-4px);
}

/* Glow text for hero */
.gl-glow-text {
}

/* Grid background — very subtle */
.gl-gridbg {
  background-image:
    linear-gradient(rgba(15,34,51,.025) 1px, transparent 1px),
    linear-gradient(90deg, rgba(15,34,51,.025) 1px, transparent 1px);
  background-size: 48px 48px;
}

/* Eyebrow line */
.gl-eye::before { background: var(--gl-accent); }

/* Marquee */
.gl-mq { background: rgba(15,34,51,0.03); backdrop-filter: blur(8px); }

/* Input glass */
.gl-input {
  background: rgba(15,34,51,0.05);
  backdrop-filter: blur(12px);
  border: 1px solid rgba(15,34,51,0.1);
  color: var(--gl-ink);
}
.gl-input:focus {
  background: rgba(15,34,51,0.07);
  border-color: var(--gl-accent);
  box-shadow: 0 0 0 3px rgba(212,88,31,0.08);
}

:root { --gl-btn-ink: #FFFFFF; }

/* ================================================================
   REDUCED MOTION
   Nothing on the public site honoured prefers-reduced-motion. Seven
   animations ran infinitely and unconditionally — two floating orbs, a 3s
   text-shadow pulse behind the largest text on the page, a 38s marquee, and
   the arcade's skeleton shimmer — plus smooth scrolling on every navigation.
   An infinitely pulsing glow behind the hero is the exact pattern this
   preference exists to suppress.

   This block is last in the file on purpose: !important declarations of equal
   specificity resolve by source order, so nothing added later can quietly
   outrank it. Kept as near-zero durations rather than `animation: none` so
   that any animationend/transitionend handler still fires.
   ================================================================ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    animation-delay: 0s !important;
    transition-duration: .01ms !important;
    transition-delay: 0s !important;
    scroll-behavior: auto !important;
  }
  html { scroll-behavior: auto !important; }

  /* The marquee's end state is translateX(-50%). Collapsing the animation
     would snap it there and hide the first half of the list, so stop it at
     the start instead and let it sit still. */
  .gl-mq-track { animation: none !important; transform: none !important; }

  /* The float/glow decorations have no informational content — park them at
     their resting state rather than at whatever keyframe 100% happens to be. */
  .gl-float { transform: none !important; }
  .gl-glow-text { text-shadow: none !important; }
}
