/* ============================================================================
   Scoreflection — Base / UI Kit  (REUSABLE)
   ----------------------------------------------------------------------------
   Reset, typography utilities, layout primitives, buttons, cards, forms and
   motion. Reusable building blocks — the future web app can load this too.

   Requires: tokens.css (load it BEFORE this file).
   You normally don't edit this file — restyle via tokens.css.
============================================================================ */


/* ---------- Reset + base -------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; padding: 0; }

html { scroll-behavior: smooth; }
body {
  background: var(--sf-bg);
  color: var(--sf-on-surface);
  font-family: var(--sf-font-ui);
  font-size: var(--sf-body-l);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  font-feature-settings: "ss01", "cv11";
}

img, svg { display: block; max-width: 100%; }
a { color: var(--sf-primary); text-decoration: none; transition: color var(--sf-dur-1) var(--sf-ease-out); }
a:hover { color: var(--sf-primary-hover); }

::selection { background: var(--sf-primary-container); color: var(--sf-on-primary-container); }


/* ---------- Typography utilities ----------------------------------------- */

.sf-display-xl,
.sf-display-l,
.sf-display-m,
.sf-headline-l,
.sf-headline-m,
.sf-headline-s {
  font-family: var(--sf-font-display);
  font-weight: 400;
  letter-spacing: -0.02em;
  line-height: 1.04;
  text-wrap: balance;
  color: var(--sf-on-surface);
}
.sf-display-xl { font-size: var(--sf-display-xl); letter-spacing: -0.035em; }
.sf-display-l  { font-size: var(--sf-display-l);  letter-spacing: -0.03em; }
.sf-display-m  { font-size: var(--sf-display-m);  letter-spacing: -0.025em; line-height: 1.08; }
.sf-headline-l { font-size: var(--sf-headline-l); line-height: 1.15; }
.sf-headline-m { font-size: var(--sf-headline-m); line-height: 1.18; }
.sf-headline-s { font-size: var(--sf-headline-s); line-height: 1.25; }

.sf-display-xl em,
.sf-display-l  em,
.sf-display-m  em {
  font-style: italic;
  font-variation-settings: "SOFT" 100, "WONK" 1;
  color: var(--sf-primary);
}

.sf-title-l    { font: 500 var(--sf-title-l)/1.3 var(--sf-font-ui); letter-spacing: -0.005em; }
.sf-title-m    { font: 500 var(--sf-title-m)/1.4 var(--sf-font-ui); letter-spacing: 0.005em; }
.sf-title-s    { font: 500 var(--sf-title-s)/1.4 var(--sf-font-ui); letter-spacing: 0.01em; }

.sf-body-l     { font: 400 var(--sf-body-l)/1.55 var(--sf-font-ui); color: var(--sf-on-surface-variant); text-wrap: pretty; }
.sf-body-m     { font: 400 var(--sf-body-m)/1.55 var(--sf-font-ui); color: var(--sf-on-surface-variant); }
.sf-body-s     { font: 400 var(--sf-body-s)/1.5 var(--sf-font-ui); color: var(--sf-on-surface-variant); }

.sf-label-l    { font: 500 var(--sf-label-l)/1.4 var(--sf-font-ui); letter-spacing: 0.06em; text-transform: uppercase; }
.sf-label-m    { font: 600 var(--sf-label-m)/1.4 var(--sf-font-ui); letter-spacing: 0.10em; text-transform: uppercase; }
.sf-label-s    { font: 600 var(--sf-label-s)/1.4 var(--sf-font-ui); letter-spacing: 0.12em; text-transform: uppercase; }

.sf-mono       { font-family: var(--sf-font-mono); font-size: var(--sf-body-s); letter-spacing: 0; }

.sf-eyebrow {
  display: inline-flex; align-items: center; gap: var(--sf-s-2);
  font: 600 var(--sf-label-m)/1 var(--sf-font-ui);
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--sf-primary);
}
.sf-eyebrow::before {
  content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: currentColor; box-shadow: 0 0 0 3px color-mix(in oklch, var(--sf-primary) 22%, transparent);
}


/* ---------- Layout primitives -------------------------------------------- */

.sf-container       { width: 100%; max-width: var(--sf-container);        margin: 0 auto; padding-inline: clamp(20px, 4vw, 40px); }
.sf-container-wide  { width: 100%; max-width: var(--sf-container-wide);   margin: 0 auto; padding-inline: clamp(20px, 4vw, 40px); }
.sf-container-narrow{ width: 100%; max-width: var(--sf-container-narrow); margin: 0 auto; padding-inline: clamp(20px, 4vw, 40px); }

.sf-section {
  padding-block: clamp(64px, 9vw, 120px);
  position: relative;
}
.sf-section--tight  { padding-block: clamp(40px, 6vw, 72px); }
.sf-section--alt    { background: var(--sf-surface-variant); }
.sf-section--ink    { background: var(--sf-inverse-surface); color: var(--sf-inverse-on-surface); }
.sf-section--ink .sf-display-l,
.sf-section--ink .sf-display-m,
.sf-section--ink .sf-headline-l,
.sf-section--ink .sf-headline-m,
.sf-section--ink .sf-headline-s { color: var(--sf-inverse-on-surface); }
.sf-section--ink .sf-body-l,
.sf-section--ink .sf-body-m     { color: color-mix(in oklch, var(--sf-inverse-on-surface) 80%, transparent); }

.sf-section-head {
  display: flex; flex-direction: column; gap: var(--sf-s-3);
  margin-bottom: var(--sf-s-9);
  max-width: 720px;
}
.sf-section-head--center { text-align: center; margin-inline: auto; align-items: center; }

/* The -N in each name is the MAXIMUM number of columns, not just a hint.
   A bare minmax(260px, 1fr) lets auto-fit pack as many tracks as will fit — at
   1200px that's four, so six cards land 4+2 with an orphan row. Making the track
   minimum "one Nth of the row, but never below <floor>px" caps the count at N and
   still collapses to fewer columns on a narrow screen. */
.sf-grid { display: grid; gap: var(--sf-s-6); }
/* Two is explicit for the reason five is, plus one the others get away with: an
   auto-repeat track size has to be a <fixed-size>, so the percentage half of
   that max() is dropped and only the floor survives — auto-fit then packs as
   many floor-width tracks as fit, which is three of them at ~900px. -3 and -4
   are wrong in the same way and hide it, because their floors happen to divide
   the containers they are used in the way they were meant to. */
.sf-grid-2 { grid-template-columns: 1fr; }
@media (min-width: 700px) { .sf-grid-2 { grid-template-columns: repeat(2, 1fr); } }
.sf-grid-3 { grid-template-columns: repeat(auto-fit, minmax(max(260px, (100% - 2 * var(--sf-s-6)) / 3), 1fr)); }
.sf-grid-4 { grid-template-columns: repeat(auto-fit, minmax(max(220px, (100% - 3 * var(--sf-s-6)) / 4), 1fr)); }

/* Five is prime: auto-fit would drop to four columns around 1100px and leave a
   lone fifth card hanging. Step 1 → 2 → 3 → 5 explicitly and never land on 4. */
.sf-grid-5 { grid-template-columns: 1fr; }
@media (min-width: 440px)  { .sf-grid-5 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 700px)  { .sf-grid-5 { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1080px) { .sf-grid-5 { grid-template-columns: repeat(5, 1fr); } }

.sf-stack > * + * { margin-top: var(--sf-s-4); }
.sf-stack-lg > * + * { margin-top: var(--sf-s-7); }


/* ---------- Buttons + chips + badges ------------------------------------- */

.sf-btn {
  --_bg:    var(--sf-primary);
  --_fg:    var(--sf-on-primary);
  --_brd:   transparent;
  --_shadow: var(--sf-elev-glow);
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--sf-s-2);
  font: 600 15px/1 var(--sf-font-ui);
  letter-spacing: 0.005em;
  background: var(--_bg);
  color: var(--_fg);
  border: 1.5px solid var(--_brd);
  border-radius: var(--sf-r-full);
  padding: 14px 22px;
  cursor: pointer;
  box-shadow: var(--_shadow);
  transition: transform var(--sf-dur-1) var(--sf-ease-out),
              background var(--sf-dur-1) var(--sf-ease-out),
              box-shadow var(--sf-dur-2) var(--sf-ease-out),
              color var(--sf-dur-1) var(--sf-ease-out);
  user-select: none;
  white-space: nowrap;
}
.sf-btn:hover { background: var(--sf-primary-hover); transform: translateY(-1px); }
.sf-btn:active { transform: translateY(0) scale(0.98); background: var(--sf-primary-press); }
.sf-btn:focus-visible {
  outline: 3px solid color-mix(in oklch, var(--sf-primary) 40%, transparent);
  outline-offset: 2px;
}

.sf-btn--secondary {
  --_bg: var(--sf-surface);
  --_fg: var(--sf-on-surface);
  --_brd: var(--sf-outline-variant);
  --_shadow: var(--sf-elev-1);
}
.sf-btn--secondary:hover { --_bg: var(--sf-surface-variant); background: var(--sf-surface-variant); }
.sf-btn--secondary:active{ --_bg: var(--sf-surface-high); background: var(--sf-surface-high); }

.sf-btn--ghost {
  --_bg: transparent;
  --_fg: var(--sf-on-surface);
  --_brd: transparent;
  --_shadow: none;
}
.sf-btn--ghost:hover { --_bg: var(--sf-surface-variant); background: var(--sf-surface-variant); }

.sf-btn--inverse {
  --_bg: var(--sf-inverse-surface);
  --_fg: var(--sf-inverse-on-surface);
  --_brd: transparent;
  --_shadow: var(--sf-elev-2);
}
.sf-btn--inverse:hover { background: color-mix(in oklch, var(--sf-inverse-surface) 88%, white); }

.sf-btn--sm { padding: 10px 16px; font-size: 14px; }
.sf-btn--lg { padding: 18px 28px; font-size: 17px; }

.sf-btn__arrow { transition: transform var(--sf-dur-2) var(--sf-ease-spring); }
.sf-btn:hover .sf-btn__arrow { transform: translateX(3px); }

/* Chip */
.sf-chip {
  display: inline-flex; align-items: center; gap: var(--sf-s-2);
  height: 32px; padding: 0 14px;
  background: var(--sf-primary-container);
  color: var(--sf-on-primary-container);
  border-radius: var(--sf-r-full);
  font: 600 13px/1 var(--sf-font-ui);
  letter-spacing: 0.01em;
}
.sf-chip--outline {
  background: transparent;
  border: 1.5px solid var(--sf-outline-variant);
  color: var(--sf-on-surface);
}
.sf-chip--secondary { background: var(--sf-secondary-container); color: var(--sf-on-secondary-container); }
.sf-chip--tertiary  { background: var(--sf-tertiary-container);  color: var(--sf-on-tertiary-container); }

/* Badge — small status pill */
.sf-badge {
  display: inline-flex; align-items: center; gap: 6px;
  font: 600 11px/1 var(--sf-font-ui);
  letter-spacing: 0.1em; text-transform: uppercase;
  padding: 5px 10px; border-radius: var(--sf-r-full);
  background: color-mix(in oklch, var(--sf-correct) 18%, transparent);
  color: var(--sf-correct);
}
.sf-badge::before {
  content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: currentColor;
}


/* ---------- Cards + surfaces --------------------------------------------- */

.sf-card {
  background: var(--sf-surface);
  border: 1px solid var(--sf-outline-variant);
  border-radius: var(--sf-r-xl);
  padding: var(--sf-s-7);
  box-shadow: var(--sf-elev-1);
  transition: transform var(--sf-dur-2) var(--sf-ease-out),
              box-shadow var(--sf-dur-2) var(--sf-ease-out),
              border-color var(--sf-dur-2) var(--sf-ease-out);
}
.sf-card--interactive:hover {
  transform: translateY(-3px);
  box-shadow: var(--sf-elev-3);
  border-color: color-mix(in oklch, var(--sf-primary) 35%, var(--sf-outline-variant));
}
.sf-card--flat   { box-shadow: none; }
.sf-card--filled { background: var(--sf-primary-container); border-color: transparent; color: var(--sf-on-primary-container); }
.sf-card--ink    { background: var(--sf-inverse-surface); color: var(--sf-inverse-on-surface); border-color: transparent; }

.sf-card__icon {
  width: 56px; height: 56px;
  border-radius: var(--sf-r-lg);
  display: grid; place-items: center;
  background: var(--sf-primary-container);
  color: var(--sf-on-primary-container);
  margin-bottom: var(--sf-s-5);
  font-size: 26px;
}
/* Illustrated card icon — an SVG spot illustration (its own colored circle
   gives the badge look, so no background box is needed).

   The file itself is a GRAYSCALE MASTER: it is drawn on a neutral ramp and gets
   its colour here, from #sf-art, so the illustration follows the theme instead
   of carrying a baked light-mode palette into dark mode. An <img> cannot read
   var(--sf-*) — it is a separate document — but a filter applies to the <img>
   ELEMENT, in this document, which is what makes this work.

   The <defs> are generated into the page by assets/gen-art-filter.mjs. They
   have to be in the same document: `filter: url()` pointing at an external file
   is not supported in Chrome. If the <defs> are ever missing, the reference
   fails and the art renders gray rather than disappearing. */
.sf-card__art {
  display: block;
  width: 88px; height: 88px;
  margin-bottom: var(--sf-s-4);
  filter: url(#sf-art);
}
[data-theme="dark"] .sf-card__art { filter: url(#sf-art-dark); }
.sf-card__title {
  font-family: var(--sf-font-display);
  font-size: 22px; font-weight: 500; letter-spacing: -0.01em;
  margin-bottom: var(--sf-s-2);
  line-height: 1.2;
}
.sf-card__body {
  color: var(--sf-on-surface-variant);
  font-size: 15px; line-height: 1.55;
  text-wrap: pretty;
}


/* ---------- Forms -------------------------------------------------------- */

.sf-input {
  font: 500 15px/1 var(--sf-font-ui);
  background: var(--sf-surface);
  color: var(--sf-on-surface);
  border: 1.5px solid var(--sf-outline-variant);
  border-radius: var(--sf-r-full);
  padding: 14px 20px;
  width: 100%;
  transition: border-color var(--sf-dur-1) var(--sf-ease-out), box-shadow var(--sf-dur-1) var(--sf-ease-out);
}
.sf-input::placeholder { color: var(--sf-on-surface-variant); font-weight: 400; }
.sf-input:focus {
  outline: none;
  border-color: var(--sf-primary);
  box-shadow: 0 0 0 4px color-mix(in oklch, var(--sf-primary) 18%, transparent);
}
.sf-input-row {
  display: flex; gap: var(--sf-s-2); align-items: center;
  background: var(--sf-surface);
  border: 1.5px solid var(--sf-outline-variant);
  border-radius: var(--sf-r-full);
  padding: 4px 4px 4px 4px;
  transition: border-color var(--sf-dur-1) var(--sf-ease-out), box-shadow var(--sf-dur-1) var(--sf-ease-out);
}
.sf-input-row:focus-within {
  border-color: var(--sf-primary);
  box-shadow: 0 0 0 4px color-mix(in oklch, var(--sf-primary) 18%, transparent);
}
.sf-input-row input {
  flex: 1; min-width: 0; border: none; background: transparent;
  padding: 12px 18px; font: 500 15px/1 var(--sf-font-ui);
  color: var(--sf-on-surface);
}
.sf-input-row input:focus { outline: none; }

/* Shared by the two real forms on the site, the cancellation form (§ 312k BGB)
   and the music-school enquiry, so they live here rather than in a
   page-specific sheet. */
.sf-form fieldset.sf-fieldset {
  border: none;
  padding: 0;
  margin: 0 0 var(--sf-s-8) 0;
}
.sf-form legend {
  font-family: var(--sf-font-display);
  font-size: 20px; font-weight: 500; letter-spacing: -0.01em;
  color: var(--sf-on-surface);
  padding: 0; margin-bottom: var(--sf-s-4);
}
.sf-field { margin-bottom: var(--sf-s-5); }
.sf-field label {
  display: block;
  font: 600 14px/1.4 var(--sf-font-ui);
  color: var(--sf-on-surface);
  margin-bottom: var(--sf-s-2);
}
.sf-help {
  font: 400 13px/1.5 var(--sf-font-ui);
  color: var(--sf-on-surface-variant);
  margin-top: var(--sf-s-2);
}
/* A textarea cannot wear the pill radius the single-line inputs do — at four
   rows it reads as a speech bubble. */
.sf-textarea {
  border-radius: var(--sf-r-lg);
  line-height: 1.6;
  resize: vertical;
  font-family: var(--sf-font-ui);
}
.sf-choice { display: flex; flex-direction: column; gap: var(--sf-s-3); }
.sf-radio {
  display: grid; grid-template-columns: auto 1fr; gap: var(--sf-s-3);
  align-items: start;
  padding: 14px 18px;
  border: 1.5px solid var(--sf-outline-variant);
  border-radius: var(--sf-r-lg);
  cursor: pointer;
  font-weight: 400;
  transition: border-color var(--sf-dur-1) var(--sf-ease-out);
}
.sf-radio:hover { border-color: var(--sf-outline); }
.sf-radio:has(input:checked) {
  border-color: var(--sf-primary);
  background: color-mix(in oklch, var(--sf-primary) 6%, transparent);
}
.sf-radio input { margin-top: 3px; accent-color: var(--sf-primary); }
.sf-radio span { font: 400 15px/1.5 var(--sf-font-ui); color: var(--sf-on-surface-variant); }
.sf-radio strong { color: var(--sf-on-surface); font-weight: 600; }
/* A honeypot field: off-screen rather than display:none, because the bots it is
   for skip fields that are plainly hidden. aria-hidden and tabindex="-1" in the
   markup keep screen readers and keyboards out of it. */
.sf-hp {
  position: absolute; left: -10000px; top: auto;
  width: 1px; height: 1px; overflow: hidden;
}
.sf-form-error {
  padding: 14px 18px;
  border-radius: var(--sf-r-lg);
  border: 1.5px solid var(--sf-wrong);
  color: var(--sf-wrong);
  font: 500 15px/1.5 var(--sf-font-ui);
}


/* ---------- Motion + utilities ------------------------------------------- */

/* Bobbing antenna pulse, used to liven up hero illustrations */
@keyframes sf-bob       { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-4px); } }
@keyframes sf-pulse     { 0% { transform: scale(0.6); opacity: 0.5; } 100% { transform: scale(2.4); opacity: 0; } }
@keyframes sf-float     { 0%   { transform: translate(0,0) scale(0.7); opacity: 0; }
                          25%  { opacity: 0.9; }
                          75%  { opacity: 0.5; }
                          100% { transform: translate(8px,-40px) scale(1.1); opacity: 0; } }
@keyframes sf-fade-up   { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
@keyframes sf-fade-in   { from { opacity: 0; } to { opacity: 1; } }

.sf-anim-bob   { animation: sf-bob 2.4s ease-in-out infinite; }
.sf-anim-up    { animation: sf-fade-up var(--sf-dur-3) var(--sf-ease-out) both; }
.sf-anim-in    { animation: sf-fade-in var(--sf-dur-3) var(--sf-ease-out) both; }

/* Utilities */
.sf-center      { text-align: center; }
.sf-mt-1 { margin-top: var(--sf-s-1); }
.sf-mt-2 { margin-top: var(--sf-s-2); }
.sf-mt-3 { margin-top: var(--sf-s-3); }
.sf-mt-4 { margin-top: var(--sf-s-4); }
.sf-mt-5 { margin-top: var(--sf-s-5); }
.sf-mt-7 { margin-top: var(--sf-s-7); }
.sf-mt-9 { margin-top: var(--sf-s-9); }
.sf-mb-7 { margin-bottom: var(--sf-s-7); }
.sf-fg-muted   { color: var(--sf-on-surface-variant); }
.sf-fg-primary { color: var(--sf-primary); }
/* The zero-size <svg><defs> block holding the generated art filters. Takes no
   layout space and is never painted; it exists only so the illustrations can
   reference the filters by id. A class rather than a style attribute because
   the Content-Security-Policy in _headers is `style-src 'self'` — no inline
   styles — and a sprite that starts laying itself out is a visible bug. */
.sf-art-defs { position: absolute; width: 0; height: 0; overflow: hidden; }
/* Visually hidden, but still read by screen readers */
.sf-sr-only {
  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;
    transition-duration: 0.001ms !important;
  }
  html { scroll-behavior: auto; }
}
