/* Het uiterlijk van de tool en de accountpagina.
   ---------------------------------------------------------------------------
   Stond eerst als <style> in index.html. Zodra er een tweede pagina bijkwam
   was dat kopieerwerk, en twee kopieen van driehonderd regels CSS lopen uit
   elkaar zonder dat iemand het merkt. Nu een bestand, door beide geladen en
   door de browser bewaard.

   Dit is dezelfde tokenlaag als website/app/globals.css. Daar staat waarom de
   keuzes zijn zoals ze zijn; hier staat alleen wat de tool er extra voor nodig
   heeft. */

/* De tool draagt dezelfde kleren als aimastersongs.com.
   ---------------------------------------------------------------------------
   Letterlijk dezelfde: dit blok is de tokenlaag van website/app/globals.css,
   met de vier woff2-bestanden erbij die daar ook gebruikt worden. Ze staan in
   web/static/fonts en worden door deze app zelf geserveerd, want een verzoek
   naar aimastersongs.com zou de belofte breken dat deze pagina niets van een
   ander domein haalt.

   Eén thema. De site heeft geen lichte variant meer, en een tool die in het
   licht wit wordt terwijl de site waar hij vandaan komt donker blijft voelt
   als een ander product. Kleur draagt hier bovendien altijd een oordeel, en
   die drie kleuren zijn op één grond afgestemd, niet op twee. */

@font-face{font-family:"Space Grotesk";src:url("/static/fonts/space-grotesk-500.woff2") format("woff2");
  font-weight:500;font-style:normal;font-display:swap}
@font-face{font-family:"Space Grotesk";src:url("/static/fonts/space-grotesk-700.woff2") format("woff2");
  font-weight:700;font-style:normal;font-display:swap}
@font-face{font-family:"JetBrains Mono";src:url("/static/fonts/jetbrains-mono-400.woff2") format("woff2");
  font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:"JetBrains Mono";src:url("/static/fonts/jetbrains-mono-600.woff2") format("woff2");
  font-weight:600;font-style:normal;font-display:swap}

:root{
  color-scheme: dark;

  --bg:#08090d; --bg-raised:#101219; --bg-sunken:#050609; --bg-glow:#141824;
  --line:#21242f; --line-soft:#171a23; --line-bright:#2f3444;
  --text:#f2f4f8; --text-dim:#a7adbd; --text-faint:#7b8398;

  /* Het signaal: merkkleur en "er staat spanning op" in één. */
  --signal:#7cf5d0; --signal-dim:#3fbf9d; --signal-ink:#04120e;
  --signal-glow:rgba(124,245,208,.14);

  --ok:#5ddb7d;    --ok-bg:rgba(93,219,125,.12);
  --tight:#f0b640; --tight-bg:rgba(240,182,64,.12);
  --clip:#ff6b6b;  --clip-bg:rgba(255,107,107,.14);

  --accent:var(--signal); --accent-ink:var(--signal-ink);

  --mono:"JetBrains Mono",ui-monospace,"SF Mono",SFMono-Regular,Menlo,Consolas,
    monospace;
  --sans:"Space Grotesk",system-ui,-apple-system,"Segoe UI",Roboto,
    "Helvetica Neue",Arial,sans-serif;

  --page:76rem;
  --radius:4px;
}

*,*::before,*::after{box-sizing:border-box}
html{scroll-behavior:smooth}
@media (prefers-reduced-motion: reduce){
  html{scroll-behavior:auto}
  *{animation-duration:.01ms !important;transition-duration:.01ms !important}
}

body{
  margin:0;background:var(--bg);color:var(--text);
  font-family:var(--sans);font-size:1rem;line-height:1.6;
  -webkit-text-size-adjust:100%;overflow-x:hidden;
}

h1,h2,h3{line-height:1.1;margin:0 0 .6em;letter-spacing:-.03em;font-weight:700}
h1,h2{text-wrap:balance}
h1{font-size:clamp(1.9rem,4.6vw,2.8rem);letter-spacing:-.04em}
h2{font-size:clamp(1.1rem,2.4vw,1.4rem)}
h3{font-size:.95rem;letter-spacing:-.01em}
p{margin:0 0 1rem;max-width:68ch}

a{color:var(--accent);text-underline-offset:.18em}
a:hover{text-decoration-thickness:2px}
:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:2px}

.mono,.num,code{font-family:var(--mono);font-variant-numeric:tabular-nums;
  font-feature-settings:"tnum" 1}
.num{white-space:nowrap}

.wrap{width:100%;max-width:var(--page);margin:0 auto;
  padding:0 clamp(1rem,4vw,2.5rem)}

.eyebrow{font-family:var(--mono);font-size:.72rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--text-faint);margin:0 0 .6rem}
.dim{color:var(--text-dim)}
.faint{color:var(--text-faint)}
.small{font-size:.82rem;line-height:1.5}

/* ---------- masthead ---------- */

.masthead{border-bottom:1px solid var(--line-soft);
  background:color-mix(in srgb, var(--bg) 92%, transparent);
  position:sticky;top:0;z-index:10;backdrop-filter:blur(8px)}
.masthead .wrap{display:flex;align-items:center;gap:1rem;
  min-height:3.5rem;flex-wrap:wrap}
.brand{display:flex;align-items:center;gap:.6rem;font-weight:650;
  letter-spacing:-.01em;text-decoration:none;color:var(--text)}
.brand svg{display:block}
.masthead .spacer{flex:1}

/* ---------- the account strip ---------- */

#account{display:none;align-items:center;gap:.65rem;flex-wrap:wrap;
  font-size:.86rem}
#account .said{color:var(--text-dim)}
#account b{color:var(--text);font-variant-numeric:tabular-nums}
.btn{font:inherit;font-size:.82rem;font-weight:600;font-family:var(--sans);
  border:1px solid var(--line);background:var(--bg-raised);color:var(--text);
  border-radius:var(--radius);padding:.4rem .75rem;cursor:pointer;
  text-decoration:none;display:inline-block;white-space:nowrap}
.btn:hover{border-color:var(--accent);color:var(--accent)}
.btn.primary{background:var(--accent);border-color:var(--accent);
  color:var(--accent-ink)}
.btn.primary:hover{color:var(--accent-ink);filter:brightness(1.08)}
.btn:disabled{opacity:.5;cursor:not-allowed}
.who{color:var(--text-faint);font-family:var(--mono);font-size:.76rem;
  max-width:22ch;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* ---------- page intro ---------- */

/* Dezelfde maatverdeling als op de onderpagina's van de site: de
   streepjesschaal van een meter, in de achtergrond, uitdovend naar onderen.
   Drie achtergrondlagen en verder niets: geen filter, geen masker, geen
   beweging. */
.intro{
  position:relative;isolation:isolate;overflow:hidden;
  padding:clamp(2.25rem,6vw,3.75rem) 0 clamp(1.5rem,3vw,2.25rem);
  border-bottom:1px solid var(--line-soft);
  background-color:var(--bg-sunken);
  background-image:
    radial-gradient(60% 100% at 92% 0%, var(--signal-glow) 0%, transparent 70%),
    linear-gradient(180deg, rgba(5,6,9,0) 0%, var(--bg-sunken) 82%),
    repeating-linear-gradient(90deg, var(--line) 0 1px, transparent 1px 120px),
    repeating-linear-gradient(90deg, var(--line-soft) 0 1px, transparent 1px 24px);
}
.intro > .wrap{position:relative;z-index:1}
.intro h1{margin-bottom:.5rem;max-width:18ch}
.intro p{color:var(--text-dim);max-width:62ch;margin:0;
  font-size:clamp(1rem,2.2vw,1.15rem)}

/* ---------- steps ---------- */

.step{border-top:1px solid var(--line-soft);padding:1.75rem 0}
.step-head{display:flex;align-items:baseline;gap:.8rem;margin-bottom:1.1rem}
.step-no{font-family:var(--mono);font-size:.72rem;letter-spacing:.14em;
  color:var(--text-faint);padding-top:.2rem}
.step-head h2{margin:0}
.step-head .note{color:var(--text-faint);font-size:.82rem;font-weight:400}

.grid{display:grid;gap:1.25rem}
.g2{grid-template-columns:repeat(auto-fit,minmax(17rem,1fr))}
.g3{grid-template-columns:repeat(auto-fit,minmax(12rem,1fr))}

label{display:block;font-size:.78rem;font-weight:600;color:var(--text-dim);
  margin-bottom:.35rem;letter-spacing:.01em}
select,input[type=text],input[type=file],textarea{
  width:100%;background:var(--bg-raised);color:var(--text);
  border:1px solid var(--line);border-radius:var(--radius);
  padding:.55rem .7rem;font:inherit;font-size:.92rem}
select:hover,input[type=text]:hover,textarea:hover{border-color:var(--line-bright)}
input[type=text]::placeholder,textarea::placeholder{color:var(--text-faint)}
/* De deelpagina heeft als eerste een tekstvak. Zonder deze regel is dat het
   enige onderdeel dat eruitziet alsof het uit een ander programma komt: wit
   vlak, systeemlettertype, en horizontaal te slepen tot buiten de kolom. */
textarea{resize:vertical;min-height:4.5rem;line-height:1.5;display:block}

/* Een keuzelijst met het pijltje van het besturingssysteem is het enige
   onderdeel op deze pagina dat eruitziet alsof het uit een ander programma
   komt: op Windows een grijs blokje, op macOS een blauw. Het pijltje hieronder
   is een SVG in de achtergrond, dus overal hetzelfde en in de signaalkleur. */
select{
  appearance:none;-webkit-appearance:none;
  padding-right:2.1rem;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' fill='none' stroke='%237cf5d0' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;
  background-position:right .75rem center;
  background-size:.7rem;
}
input[type=range]{width:100%;accent-color:var(--accent)}
.hint{font-size:.78rem;color:var(--text-faint);margin-top:.4rem;line-height:1.5}

/* The drop zone. One job, so it gets the room to say it. */
#drop{border:1px dashed var(--line);border-radius:var(--radius);
  background:var(--bg-sunken);padding:clamp(1.75rem,5vw,2.75rem) 1rem;
  text-align:center;cursor:pointer;transition:border-color .15s,background .15s}
#drop:hover,#drop.hot{border-color:var(--accent);
  background:color-mix(in srgb, var(--accent) 6%, var(--bg-sunken))}
#drop .big{font-weight:650;font-size:1rem}
#drop .formats{font-family:var(--mono);font-size:.72rem;letter-spacing:.06em;
  color:var(--text-faint);margin-top:.5rem;text-transform:uppercase}

#filelist{margin-top:.9rem;font-size:.85rem}
#filelist .file{display:flex;justify-content:space-between;gap:1rem;
  padding:.45rem 0;border-bottom:1px solid var(--line-soft)}
#filelist .file:last-child{border-bottom:0}

.checks{display:flex;flex-wrap:wrap;gap:.4rem}
/* `hidden` is een attribuut en geen klasse, en elke regel die `display` zet
   wint ervan. `.chk` doet dat, dus een verborgen vinkje stond gewoon op het
   scherm - hetzelfde soort fout als een <details> die zijn inhoud verbergt
   waar CSS niet bij kan. Eén regel bovenaan, voor alles wat hierna nog
   `display` gaat zetten. */
[hidden]{display:none !important}

.chk{display:inline-flex;align-items:center;gap:.45rem;cursor:pointer;
  border:1px solid var(--line);border-radius:var(--radius);
  padding:.35rem .6rem;font-size:.82rem;font-weight:500;color:var(--text-dim);
  user-select:none;background:var(--bg-raised)}
.chk:hover{border-color:var(--text-faint)}
.chk:has(input:checked){border-color:var(--accent);color:var(--text)}
.chk input{accent-color:var(--accent);margin:0;width:.95rem;height:.95rem}
/* Aangevinkt is een toestand met gevolgen: dit platform wordt straks echt
   gecodeerd en gemeten. Dat mag je zien zonder het vinkje te moeten zoeken. */
.chk:has(input:checked){background:color-mix(in srgb,var(--signal) 10%,var(--bg-raised))}

details{margin-top:1.1rem;border-top:1px solid var(--line-soft);padding-top:.9rem}
summary{cursor:pointer;font-size:.82rem;color:var(--text-dim);font-weight:600}
summary:hover{color:var(--accent)}

/* ---------- the run bar ---------- */

.runbar{display:flex;align-items:center;gap:1rem;flex-wrap:wrap;
  border-top:1px solid var(--line-soft);padding:1.5rem 0 2rem}
#go{font-size:.92rem;padding:.6rem 1.4rem}

#progress{display:none;flex:1;min-width:14rem}
#progress .line{display:flex;justify-content:space-between;
  font-family:var(--mono);font-size:.76rem;color:var(--text-dim);
  margin-bottom:.4rem}
.bar{height:2px;background:var(--line);overflow:hidden}
.bar>i{display:block;height:100%;width:35%;background:var(--accent);
  animation:slide 1.4s ease-in-out infinite}
@keyframes slide{0%{transform:translateX(-100%)}100%{transform:translateX(340%)}}

.err{border-left:2px solid var(--clip);background:var(--clip-bg);
  padding:.75rem .9rem;font-size:.88rem;margin-bottom:1.5rem}
.said-ok{border-left-color:var(--ok);background:var(--ok-bg)}

/* ---------- results ---------- */

.result{border-top:1px solid var(--line);padding:2rem 0}
.result > h2{display:flex;align-items:baseline;gap:.7rem;flex-wrap:wrap}
.result > h2 .meta{font-family:var(--mono);font-size:.76rem;font-weight:400;
  color:var(--text-faint);letter-spacing:.02em}

.readout{display:grid;gap:1px;background:var(--line-soft);
  border:1px solid var(--line-soft);
  grid-template-columns:repeat(auto-fit,minmax(9rem,1fr));margin-bottom:1.75rem}
.cell{background:var(--bg);padding:.85rem .9rem}
.cell .k{font-family:var(--mono);font-size:.66rem;letter-spacing:.12em;
  text-transform:uppercase;color:var(--text-faint)}
.cell .v{font-family:var(--mono);font-variant-numeric:tabular-nums;
  font-size:1.35rem;line-height:1.2;margin-top:.3rem;letter-spacing:-.02em}
.cell .v .unit{font-size:.72rem;color:var(--text-faint);margin-left:.15rem}
.cell .was{font-size:.72rem;color:var(--text-faint);margin-top:.15rem;
  font-family:var(--mono)}

h3.sub{margin:1.75rem 0 .75rem;font-family:var(--mono);font-size:.72rem;
  letter-spacing:.14em;text-transform:uppercase;color:var(--text-faint);
  font-weight:600}

.finding{border-left:2px solid var(--line);padding:.15rem 0 .15rem .85rem;
  margin-bottom:.9rem}
.finding.goed{border-color:var(--ok)}
.finding.info{border-color:var(--accent)}
.finding.waarschuwing{border-color:var(--tight)}
.finding b{display:block;font-size:.88rem;margin-bottom:.15rem}
.finding p{margin:0;font-size:.85rem;color:var(--text-dim)}

table{width:100%;border-collapse:collapse;font-size:.85rem}
th{text-align:left;font-family:var(--mono);font-size:.66rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--text-faint);font-weight:600;
  padding:.5rem .6rem;border-bottom:1px solid var(--line)}
td{padding:.6rem;border-bottom:1px solid var(--line-soft);vertical-align:top}
tr:last-child td{border-bottom:0}
.scroller{overflow-x:auto}

.tag{display:inline-block;font-family:var(--mono);font-size:.68rem;
  letter-spacing:.08em;text-transform:uppercase;font-weight:650;
  padding:.15rem .45rem;border-radius:var(--radius)}
.tag.goed{background:var(--ok-bg);color:var(--ok)}
.tag.krap{background:var(--tight-bg);color:var(--tight)}
.tag.clipt{background:var(--clip-bg);color:var(--clip)}

.timeline{position:relative;height:2.1rem;background:var(--bg-sunken);
  border:1px solid var(--line-soft);overflow:hidden;margin-bottom:1rem}
.timeline span{position:absolute;top:0;bottom:0}

audio{width:100%;max-width:26rem;height:2rem;margin-top:.5rem}
.legend{display:flex;gap:1.1rem;flex-wrap:wrap;font-size:.76rem;
  color:var(--text-faint);margin-top:.5rem}
.legend i{display:inline-block;width:.8rem;height:2px;margin-right:.35rem;
  vertical-align:middle}

.zipline{display:flex;align-items:center;gap:.9rem;flex-wrap:wrap;
  margin:.5rem 0 1.25rem}

footer{border-top:1px solid var(--line-soft);padding:1.75rem 0 3rem;
  font-size:.78rem;color:var(--text-faint)}
footer a{color:var(--text-faint)}

/* ---------- de accountpagina ----------

   Eén regel per master. Op een breed scherm staan de knoppen rechts naast de
   titel, op een telefoon eronder: drie knoppen naast een titel van vijftig
   tekens past daar niet, en dan wint de titel. */

.tag.neutraal{background:var(--bg-glow);color:var(--text-dim)}

.job{display:flex;gap:1rem;flex-wrap:wrap;align-items:flex-start;
  justify-content:space-between;
  border:1px solid var(--line-soft);border-radius:var(--radius);
  background:var(--bg-raised);padding:.9rem 1rem;margin-bottom:.75rem}
.job-main{flex:1 1 18rem;min-width:0}
.job h3{margin:0 0 .35rem;font-size:1rem;
  /* Een albumnaam van tien tracks is één regel van driehonderd tekens. */
  overflow-wrap:anywhere}
.job-meta{display:flex;flex-wrap:wrap;gap:.45rem .9rem;align-items:center;
  margin:0;font-size:.78rem}
.job-actions{display:flex;gap:.5rem;flex-wrap:wrap;align-items:center}

/* Verwijderen is onomkeerbaar en hoort er niet uit te zien als opslaan. Geen
   rood vlak dat om aandacht vraagt: een rode rand op het moment dat je hem
   aanwijst is genoeg om te weten wat er gaat gebeuren. */
.btn.danger:hover{border-color:var(--clip);color:var(--clip)}

/* ---------- de adminpagina ----------

   Veertien staafjes, één per dag. Geen bibliotheek voor een grafiek van
   veertien getallen: dat is honderd kilobyte JavaScript om iets te tekenen wat
   met veertien divs kan, op een pagina die alleen ik ooit zie. */

.daybars{display:flex;align-items:flex-end;gap:.35rem;height:9rem;
  padding:.5rem .5rem 0;border:1px solid var(--line-soft);
  border-radius:var(--radius);background:var(--bg-sunken)}
.daybar{flex:1;display:flex;flex-direction:column;justify-content:flex-end;
  align-items:center;height:100%;gap:.3rem}
.daybar-stack{width:100%;background:var(--signal-dim);border-radius:2px 2px 0 0;
  display:flex;flex-direction:column;justify-content:flex-end;min-height:2px}
/* Het mislukte deel onderaan, want dat is het deel dat er wel was en niets
   opleverde. Bovenop zou het lezen als iets dat er extra bij kwam. */
.daybar-bad{width:100%;background:var(--clip);border-radius:0 0 2px 2px}
.daybar-n{font-family:var(--mono);font-size:.62rem;color:var(--text-faint)}

/* Een oneven laatste cel over de volle breedte, maar alleen waar het raster
   zeker twee kolommen breed is. Drie meetwaarden in twee kolommen laat anders
   een leeg vak achter dat eruitziet als een ontbrekend getal, en op deze
   pagina's is een ontbrekend getal precies wat je niet wil suggereren. */
/* ---------- de menuknop in de kopbalk ----------

   Het accountstrookje is op een breed scherm een regel en op een telefoon een
   blok van drie: tegoed, twee koopknoppen, je adres en uitloggen. Dat duwde de
   tool zelf naar beneden, en juist op een telefoon wil je meteen bij het
   uploadvak kunnen.

   Een vinkje met een label, net als op de verkoopsite. Nul regels JavaScript,
   en het vinkje is onzichtbaar maar te focussen, dus het werkt met de
   spatiebalk. De streepjes bewegen met `transform` en `opacity`, want dat gaat
   naar de compositor; hoogte animeren zou layout kosten op het element dat op
   elke pagina bovenaan staat. */

.strip-toggle{position:absolute;opacity:0;width:1px;height:1px;margin:0}
.burger-btn{display:none}
.strip-toggle:focus-visible + .burger-btn{outline:2px solid var(--accent);
  outline-offset:2px;border-radius:3px}
.burger{display:grid;gap:3px;width:1.05rem}
.burger i{display:block;height:2px;background:currentColor;border-radius:1px;
  transition:transform .18s ease, opacity .18s ease}

@media (max-width: 700px) {
  .burger-btn{display:flex;align-items:center;cursor:pointer;
    color:var(--text-dim);padding:.45rem .2rem}
  .burger-btn:hover,.strip-toggle:checked + .burger-btn{color:var(--text)}
  .strip-toggle:checked + .burger-btn .burger i:nth-child(1){
    transform:translateY(5px) rotate(45deg)}
  .strip-toggle:checked + .burger-btn .burger i:nth-child(2){opacity:0}
  .strip-toggle:checked + .burger-btn .burger i:nth-child(3){
    transform:translateY(-5px) rotate(-45deg)}

  .masthead .wrap{position:relative;flex-wrap:nowrap}
  /* `display` met !important omdat de pagina dit element zelf op `flex` zet
     zodra er iets in staat: zonder dat zou het strookje op een telefoon weer
     openklappen op het moment dat het gevuld wordt. */
  #account{display:none !important}
  .strip-toggle:checked ~ #account{display:flex !important;
    position:absolute;left:0;right:0;top:100%;flex-direction:column;
    align-items:flex-start;gap:.55rem;padding:.85rem 0 1rem;
    background:var(--bg-raised);border-bottom:1px solid var(--line)}
}

@media (max-width: 460px) {
  .readout > .cell:last-child:nth-child(odd) { grid-column: 1 / -1 }
}


/* ---------- de toestemmingsbalk ----------
   Onderaan en niet als scherm ervoor: een banner die de pagina blokkeert is
   een manier om "accepteren" af te dwingen, en dat is precies de truc die deze
   dienst nergens anders uithaalt. De weigerknop is even groot als de andere. */
.consent{position:fixed;left:0;right:0;bottom:0;z-index:20;
  background:var(--bg-raised);border-top:1px solid var(--line);
  box-shadow:0 -8px 24px rgb(0 0 0 / 35%)}
.consent-inner{display:flex;align-items:center;gap:1.25rem;flex-wrap:wrap;
  padding-top:.9rem;padding-bottom:.9rem}
.consent p{margin:0;font-size:.86rem;color:var(--text-dim);max-width:62ch}
.consent-buttons{display:flex;gap:.6rem;margin-left:auto}
@media (max-width: 640px){
  .consent-buttons{margin-left:0;width:100%}
  .consent-buttons .btn{flex:1}
}
