/* Flaro — Weboberfläche. * * Der Aufbau folgt Plex: Kopfleiste oben, Seitenleiste links mit Icons, * waagerechte Reihen auf der Startseite, Plakate im Verhältnis 2:3 mit Haken * und Fortschrittsbalken, eine Detailseite mit unscharfem Hintergrund und * dem Schriftzug des Films. * * **Die Farbe nicht.** Plex ist bernsteingelb, Flaro ist Orchidee. Das * Vorbild ist die Anordnung, nicht das Aussehen. */ :root { --accent: #C04AC9; --accent-dim: #8E3595; --accent-soft: rgba(192, 74, 201, .16); --canvas: #0B0B0D; --surface: #141417; --elevated: #1D1D22; --raised: #26262C; --placeholder: #202026; --line: rgba(255, 255, 255, .08); --text: #F2F2F5; --text-dim: #B4B4BE; --text-muted: #8A8A95; --text-faint: #65656F; --destructive: #E5484D; --s-tight: 4px; --s-snug: 8px; --s-regular: 12px; --s-loose: 16px; --s-section: 24px; --s-page: 32px; --r-control: 8px; --r-card: 6px; --r-pill: 999px; --sidebar-w: 240px; --topbar-h: 56px; color-scheme: dark; } * { box-sizing: border-box; } html, body { height: 100%; } body { margin: 0; background: var(--canvas); color: var(--text); font: 400 14px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; -webkit-font-smoothing: antialiased; } button, input, select, textarea { font: inherit; color: inherit; } button { cursor: pointer; } .hidden { display: none !important; } /* **Jedes SVG bekommt eine Grösse, nicht nur die in `.icon`.** Ein rohes `` ohne Breite füllt sonst seinen Container — und die Lupe in der Suchleiste war dreihundert Bildpunkte gross und lag über der Seite. */ svg { width: 20px; height: 20px; display: block; flex: none; } .icon { width: 20px; height: 20px; display: block; flex: none; } /* ---------- Kopfleiste ---------- */ #topbar { position: fixed; inset: 0 0 auto 0; height: var(--topbar-h); z-index: 30; display: flex; align-items: center; gap: var(--s-loose); padding: 0 var(--s-loose); background: #0E0E11; border-bottom: 1px solid var(--line); } #topbar .marke { font-size: 20px; font-weight: 700; letter-spacing: -.02em; color: var(--accent); user-select: none; } #topbar .suchfeld { flex: 1; max-width: 420px; display: flex; align-items: center; gap: var(--s-snug); background: var(--elevated); border: 1px solid transparent; border-radius: var(--r-pill); padding: 0 var(--s-regular); height: 34px; color: var(--text-muted); } #topbar .suchfeld:focus-within { border-color: var(--accent); color: var(--text); } #topbar .suchfeld input { flex: 1; min-width: 0; background: none; border: 0; outline: none; color: var(--text); } #topbar .rechts { margin-left: auto; display: flex; align-items: center; gap: var(--s-regular); } #topbar .konto { display: flex; align-items: center; gap: var(--s-snug); background: none; border: 0; color: var(--text-dim); padding: 0; } #topbar .konto .kreis { width: 28px; height: 28px; border-radius: 50%; background: var(--accent); color: #fff; display: grid; place-items: center; font-size: 13px; font-weight: 600; } /* ---------- Grundgerüst ---------- */ #app { display: flex; min-height: 100%; padding-top: var(--topbar-h); } #chrome { position: fixed; top: var(--topbar-h); bottom: 0; left: 0; width: var(--sidebar-w); overflow-y: auto; background: #0E0E11; border-right: 1px solid var(--line); padding: var(--s-loose) 0; display: flex; flex-direction: column; gap: 2px; } .nav-gruppe { font-size: 11px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--text-faint); padding: var(--s-loose) var(--s-loose) var(--s-snug); } #chrome button { display: flex; align-items: center; gap: var(--s-regular); background: none; border: 0; text-align: left; padding: 9px var(--s-loose); color: var(--text-dim); border-left: 3px solid transparent; } #chrome button > span.name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } #chrome button .icon { flex: none; color: var(--text-muted); } #chrome button:hover { color: var(--text); background: rgba(255, 255, 255, .04); } #chrome button:hover .icon { color: var(--text-dim); } /* **Der Balken links, nicht ein gefüllter Knopf.** Bei Plex markiert ein schmaler farbiger Strich die aktive Zeile; das liest sich in einer langen Liste ruhiger als ein leuchtender Block. */ #chrome button.check { color: var(--accent); border-left-color: var(--accent); background: linear-gradient(90deg, var(--accent-soft), transparent 60%); } #chrome button.check .icon { color: var(--accent); } #chrome button .zahl { flex: none; font-size: 11px; font-variant-numeric: tabular-nums; color: var(--text-faint); } #chrome button.check .zahl { color: var(--accent); } .nav-fuss { margin-top: auto; padding-top: var(--s-loose); } #content { flex: 1; min-width: 0; margin-left: var(--sidebar-w); padding: var(--s-section) var(--s-page) var(--s-page); } /* ---------- Anmeldung ---------- */ #login { min-height: 100vh; display: grid; place-items: center; padding: var(--s-section); background: var(--canvas); } .login-card { width: 100%; max-width: 360px; display: flex; flex-direction: column; gap: var(--s-regular); background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-control); padding: var(--s-section); } .login-card h1 { margin: 0; font-size: 26px; letter-spacing: -.02em; color: var(--accent); } .bleiben { display: flex; align-items: center; gap: var(--s-snug); color: var(--text-dim); font-size: 13px; cursor: pointer; user-select: none; } .bleiben input { accent-color: var(--accent); width: 15px; height: 15px; margin: 0; } /* ---------- Kopf einer Mediathek ---------- */ .seitenkopf { display: flex; align-items: flex-start; gap: var(--s-section); margin-bottom: var(--s-section); } .seitenkopf .wer { min-width: 0; } .seitenkopf h1 { margin: 0; font-size: 22px; font-weight: 700; letter-spacing: -.02em; } .seitenkopf .quelle { font-size: 11px; letter-spacing: .06em; text-transform: uppercase; color: var(--text-faint); } /* Reiter in der Mitte, aktiver unterstrichen — wie bei Plex. */ .reiter { display: flex; gap: var(--s-section); margin: 0 auto; } .reiter button { background: none; border: 0; padding: 4px 0 8px; color: var(--text-muted); font-weight: 500; border-bottom: 2px solid transparent; } .reiter button:hover { color: var(--text); } .reiter button.check { color: var(--accent); border-bottom-color: var(--accent); } /* Filterzeile darunter — Pillen, keine Formularfelder. * * **Bei Plex sieht ein Filter nicht nach Eingabe aus.** Dort stehen Wörter * mit einem kleinen Pfeil daneben; ein umrandetes Auswahlfeld sagt „hier * fehlt noch etwas", und das stimmt nicht — es steht ja schon etwas drin. */ .filterzeile { display: flex; align-items: center; gap: var(--s-snug); margin-bottom: var(--s-section); flex-wrap: wrap; } .filterzeile .anzahl { background: var(--elevated); border-radius: var(--r-pill); padding: 3px 11px; font-size: 13px; color: var(--text-dim); font-variant-numeric: tabular-nums; } .pille { position: relative; display: inline-flex; align-items: center; } .pille select { appearance: none; -webkit-appearance: none; background: none; border: 0; outline: none; cursor: pointer; color: var(--text-dim); font-weight: 500; padding: 6px 26px 6px 11px; border-radius: var(--r-pill); } .pille select:hover { background: var(--elevated); color: var(--text); } .pille select:focus-visible { box-shadow: 0 0 0 2px var(--accent); } /* Gesetzt heisst farbig — so sieht man ohne Lesen, dass gefiltert wird. */ .pille.gesetzt select { color: var(--accent); } .pille::after { content: ''; position: absolute; right: 11px; top: 50%; width: 6px; height: 6px; margin-top: -4px; border-right: 1.6px solid currentColor; border-bottom: 1.6px solid currentColor; transform: rotate(45deg); color: var(--text-faint); pointer-events: none; } .pille.gesetzt::after { color: var(--accent); } .filterzeile .zuruecksetzen { background: none; border: 0; padding: 6px 4px; color: var(--text-muted); font-size: 13px; } .filterzeile .zuruecksetzen:hover { color: var(--text); text-decoration: underline; } .filterzeile .suchhuelle { margin-left: auto; display: flex; align-items: center; gap: var(--s-snug); background: var(--elevated); border: 1px solid transparent; border-radius: var(--r-pill); padding: 0 var(--s-regular); height: 32px; color: var(--text-muted); min-width: 220px; } .filterzeile .suchhuelle:focus-within { border-color: var(--accent); color: var(--text); } .filterzeile .suchhuelle input { flex: 1; min-width: 0; background: none; border: 0; outline: none; color: var(--text); } /* ---------- Kacheln ---------- */ .raster { display: grid; gap: var(--s-loose); grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); } .kachel { display: flex; flex-direction: column; gap: var(--s-snug); background: none; border: 0; padding: 0; text-align: left; min-width: 0; } .plakat { position: relative; width: 100%; aspect-ratio: 2 / 3; background: var(--placeholder); border-radius: var(--r-card); overflow: hidden; transition: transform .15s ease, box-shadow .15s ease; } .plakat img { width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity .2s; } .plakat.geladen img { opacity: 1; } .kachel:hover .plakat { transform: translateY(-2px); box-shadow: 0 8px 24px rgba(0, 0, 0, .55); } /* Der Abspielknopf erscheint beim Überfahren, mittig. */ .schweber { position: absolute; inset: 0; display: grid; place-items: center; background: rgba(0, 0, 0, .45); opacity: 0; transition: opacity .15s ease; } .schweber svg { width: 44px; height: 44px; color: #fff; filter: drop-shadow(0 2px 8px rgba(0,0,0,.6)); } .kachel:hover .schweber { opacity: 1; } /* **Haken und Zahl sitzen in derselben Ecke**, weil sie dieselbe Frage beantworten: ist hier noch etwas offen? */ .ecke { position: absolute; top: 0; right: 0; z-index: 2; min-width: 26px; height: 26px; padding: 0 6px; display: grid; place-items: center; font-size: 12px; font-weight: 600; font-variant-numeric: tabular-nums; border-bottom-left-radius: var(--r-card); } .ecke.haken { background: rgba(0, 0, 0, .72); color: #fff; } .ecke.haken svg { width: 15px; height: 15px; } .ecke.zahl { background: var(--accent); color: #fff; } /* Ab der ersten Sekunde sichtbar — darum die Mindestbreite. */ .fortschritt { position: absolute; left: 0; right: 0; bottom: 0; height: 3px; z-index: 2; background: rgba(255, 255, 255, .22); } .fortschritt > div { height: 100%; min-width: 4px; background: var(--accent); } .kacheltext { display: flex; flex-direction: column; gap: 1px; min-width: 0; } .kacheltext strong { font-weight: 500; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .kacheltext span { font-size: 12px; color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .kacheltext .dritte { color: var(--text-faint); } /* ---------- Waagerechte Reihen ---------- */ .reihe { margin-bottom: var(--s-page); } .reihe-kopf { display: flex; align-items: center; gap: var(--s-regular); margin-bottom: var(--s-regular); } .reihe-kopf h2 { margin: 0; font-size: 19px; font-weight: 700; letter-spacing: -.01em; } .reihe-kopf .mehr { background: none; border: 0; padding: 0; font-size: 13px; color: var(--accent); } .reihe-kopf .mehr:hover { text-decoration: underline; } .reihe-pfeile { margin-left: auto; display: flex; gap: var(--s-tight); } .pfeil { width: 28px; height: 28px; display: grid; place-items: center; background: var(--elevated); border: 0; border-radius: 50%; color: var(--text-dim); } .pfeil:hover { background: var(--raised); color: var(--text); } .pfeil svg { width: 16px; height: 16px; } .strip { display: grid; grid-auto-flow: column; grid-auto-columns: 150px; gap: var(--s-loose); overflow-x: auto; scroll-snap-type: x proximity; scrollbar-width: none; padding-bottom: var(--s-tight); } .strip::-webkit-scrollbar { display: none; } .strip > * { scroll-snap-align: start; } /* ---------- Detailseite ---------- */ .detail { position: relative; } /* **Der Hintergrund füllt die Seite, nicht nur einen Streifen.** Bei Plex liegt er unscharf und abgedunkelt hinter allem und gibt der Seite die Farbe des Films. */ .detail-hintergrund { position: fixed; top: var(--topbar-h); left: var(--sidebar-w); right: 0; bottom: 0; z-index: -1; background-size: cover; background-position: center top; opacity: .28; filter: blur(2px); mask-image: linear-gradient(180deg, #000 0%, rgba(0,0,0,.45) 55%, transparent 92%); } .detail-kopf { display: flex; gap: var(--s-page); align-items: flex-start; margin-bottom: var(--s-page); } .detail-kopf .plakat { flex: none; width: 240px; box-shadow: 0 12px 40px rgba(0, 0, 0, .6); } .detail-text { min-width: 0; flex: 1; padding-top: var(--s-snug); } /* Der Schriftzug des Films statt der Systemschrift — wenn es einen gibt. */ .detail-text .schriftzug { max-width: 420px; max-height: 110px; margin-bottom: var(--s-regular); object-fit: contain; object-position: left bottom; display: block; } .detail-text h1 { margin: 0 0 var(--s-snug); font-size: 34px; font-weight: 700; letter-spacing: -.03em; } .detail-text .unter { margin: 0 0 var(--s-regular); font-size: 17px; color: var(--text-dim); } .eckdaten { display: flex; align-items: center; gap: var(--s-regular); flex-wrap: wrap; color: var(--text-dim); font-size: 13px; margin-bottom: var(--s-loose); } .freigabe { border: 1px solid var(--text-faint); border-radius: 3px; padding: 0 6px; font-size: 11px; font-weight: 700; letter-spacing: .04em; color: var(--text-dim); } .bewertung { display: flex; align-items: center; gap: 5px; color: var(--text); font-weight: 600; } .bewertung svg { width: 15px; height: 15px; color: var(--accent); } .werbezeile { color: var(--text-muted); font-style: italic; margin: 0 0 var(--s-loose); } .beschreibung { max-width: 70ch; margin: 0 0 var(--s-section); color: var(--text-dim); } .aktionen { display: flex; align-items: center; gap: var(--s-regular); margin-bottom: var(--s-section); flex-wrap: wrap; } .btn { display: inline-flex; align-items: center; gap: var(--s-snug); background: var(--elevated); border: 0; border-radius: var(--r-pill); padding: 9px var(--s-loose); color: var(--text); } .btn:hover { background: var(--raised); } .btn:disabled { opacity: .5; cursor: default; } .btn svg { width: 18px; height: 18px; } .btn-primary { background: var(--accent); color: #fff; font-weight: 600; } .btn-primary:hover { background: var(--accent-dim); } /* Runde Knöpfe für alles ohne Beschriftung — wie Plex' Merkliste und Haken. */ .rund { width: 38px; height: 38px; padding: 0; border-radius: 50%; display: grid; place-items: center; background: none; border: 1px solid var(--line); color: var(--text-dim); } .rund:hover { border-color: var(--text-muted); color: var(--text); } .rund.an { background: var(--accent); border-color: var(--accent); color: #fff; } .rund svg { width: 19px; height: 19px; } /* Die Medienangaben als Tabelle — Plex' „Video / Ton / Untertitel". */ .medientabelle { display: grid; grid-template-columns: auto 1fr; gap: var(--s-snug) var(--s-section); margin-bottom: var(--s-section); } .medientabelle dt { color: var(--text-muted); font-size: 13px; } .medientabelle dd { margin: 0; font-size: 13px; } /* Besetzung: runde Porträts, wie bei Plex. */ .besetzung { display: grid; grid-auto-flow: column; grid-auto-columns: 110px; gap: var(--s-loose); overflow-x: auto; scrollbar-width: none; } .besetzung::-webkit-scrollbar { display: none; } .kopf-kachel { display: flex; flex-direction: column; align-items: center; gap: var(--s-snug); text-align: center; } .kopf-kachel .portrait { width: 92px; height: 92px; border-radius: 50%; overflow: hidden; background: var(--placeholder); display: grid; place-items: center; color: var(--text-faint); font-size: 26px; font-weight: 600; } .kopf-kachel .portrait img { width: 100%; height: 100%; object-fit: cover; } .kopf-kachel strong { font-size: 12px; font-weight: 500; } .kopf-kachel span { font-size: 11px; color: var(--text-muted); } /* Genre-Kacheln, Plex' „Kategorien". */ .kategorien { display: grid; gap: var(--s-loose); grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); } .kategorie { aspect-ratio: 16 / 9; border: 0; border-radius: var(--r-control); display: grid; place-items: center; color: #fff; font-size: 19px; font-weight: 700; letter-spacing: -.01em; position: relative; overflow: hidden; } .kategorie:hover { filter: brightness(1.15); } /* ---------- Kleinteile ---------- */ h2 { font-size: 19px; font-weight: 700; letter-spacing: -.01em; margin: 0 0 var(--s-regular); } .seitentitel { margin: 0; font-size: 22px; font-weight: 700; letter-spacing: -.02em; } .einstellungen { display: flex; flex-direction: column; gap: var(--s-regular); margin-bottom: var(--s-page); } .einstellung { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-control); padding: var(--s-loose); display: flex; flex-direction: column; gap: var(--s-regular); } .einstellung.waehlbar { text-align: left; width: 100%; } .einstellung.waehlbar:hover { border-color: var(--accent); } .zeile { display: flex; flex-direction: column; gap: 1px; min-width: 0; } .zeile strong { font-weight: 600; } .winzig { font-size: 12px; color: var(--text-muted); } .hinweis { color: var(--text-dim); font-size: 13px; } .feld { background: var(--elevated); border: 1px solid transparent; border-radius: var(--r-control); padding: 9px var(--s-regular); color: var(--text); outline: none; min-width: 0; } .feld:focus { border-color: var(--accent); } .knopfreihe { display: flex; gap: var(--s-snug); flex-wrap: wrap; align-items: center; } .fehler { background: rgba(229, 72, 77, .12); border: 1px solid rgba(229, 72, 77, .35); border-radius: var(--r-control); padding: var(--s-regular); color: #FF9A9D; font-size: 13px; } .leer { color: var(--text-muted); padding: var(--s-section) 0; } .spinner { width: 22px; height: 22px; margin: var(--s-section) auto; border: 2px solid var(--line); border-top-color: var(--accent); border-radius: 50%; animation: dreh .7s linear infinite; } @keyframes dreh { to { transform: rotate(360deg); } } .attribution { display: flex; align-items: center; gap: var(--s-snug); margin-top: var(--s-page); padding-top: var(--s-loose); border-top: 1px solid var(--line); color: var(--text-faint); font-size: 12px; } .attribution img { height: 14px; opacity: .7; } /* Eine laufende Wiedergabe im Dashboard. */ .einstellung.laeuft { gap: var(--s-snug); } .laeuft-bild { flex: none; width: 44px; aspect-ratio: 2 / 3; border-radius: 3px; overflow: hidden; background: var(--placeholder); } .laeuft-bild img { width: 100%; height: 100%; object-fit: cover; } .fortschritt.breit { position: static; height: 3px; border-radius: 2px; overflow: hidden; } /* ---------- Dialoge ---------- */ /* Das `` des Browsers: Escape schliesst, der Hintergrund ist unbedienbar, der Fokus bleibt gefangen. Hier bleibt nur das Aussehen. */ .dlg { width: min(520px, calc(100vw - 2 * var(--s-section))); padding: 0; border: 1px solid var(--line); border-radius: var(--r-control); background: var(--surface); color: var(--text); box-shadow: 0 24px 64px rgba(0, 0, 0, .7); } .dlg::backdrop { background: rgba(0, 0, 0, .62); backdrop-filter: blur(2px); } .dlg-kopf { display: flex; align-items: center; gap: var(--s-regular); padding: var(--s-loose) var(--s-section); border-bottom: 1px solid var(--line); } .dlg-kopf h2 { margin: 0; flex: 1; font-size: 17px; } .dlg-zu { width: 30px; height: 30px; display: grid; place-items: center; background: none; border: 0; border-radius: 50%; color: var(--text-muted); } .dlg-zu:hover { background: var(--elevated); color: var(--text); } .dlg-koerper { padding: var(--s-section); display: flex; flex-direction: column; gap: var(--s-loose); max-height: 60vh; overflow-y: auto; } .dlg-feld { display: flex; flex-direction: column; gap: var(--s-snug); } .dlg-feld.waagerecht { flex-direction: row; align-items: center; gap: var(--s-snug); cursor: pointer; } .dlg-feld.waagerecht input { accent-color: var(--accent); width: 15px; height: 15px; margin: 0; } .dlg-beschriftung { font-size: 13px; color: var(--text-dim); } .dlg-fuss { display: flex; justify-content: flex-end; gap: var(--s-snug); padding: var(--s-loose) var(--s-section); border-top: 1px solid var(--line); } .btn-gefahr { background: var(--destructive); color: #fff; font-weight: 600; } .btn-gefahr:hover { background: #C53338; } /* Der Spieler über allem. */ .pl-fill { position: fixed; inset: 0; z-index: 100; background: #000; } /* ---------- Schmale Bildschirme ---------- */ @media (max-width: 860px) { #app { flex-direction: column; } #chrome { position: static; width: auto; flex-direction: row; overflow-x: auto; border-right: 0; border-bottom: 1px solid var(--line); padding: var(--s-snug); } #chrome button { border-left: 0; border-bottom: 3px solid transparent; white-space: nowrap; } #chrome button.check { border-left-color: transparent; border-bottom-color: var(--accent); background: none; } .nav-gruppe { display: none; } .nav-fuss { margin: 0; padding: 0; display: flex; } #content { margin-left: 0; padding: var(--s-loose); } .detail-hintergrund { left: 0; } .detail-kopf { flex-direction: column; gap: var(--s-loose); } .detail-kopf .plakat { width: 160px; } .detail-text h1 { font-size: 26px; } #topbar .suchfeld { max-width: none; } }