Benutzer-Werkzeuge

Webseiten-Werkzeuge


tools:ur-timer

Dies ist eine alte Version des Dokuments!


<!DOCTYPE html>

<html lang=„de“> <head> <meta charset=„UTF-8“> <meta name=„viewport“ content=„width=device-width, initial-scale=1.0“> <title>Unterrichts-Timer</title> <link href=„https://fonts.googleapis.com/css2?family=DM+Mono:wght@300;400;500&family=Bebas+Neue&family=DM+Sans:wght@300;400;500;600&family=Roboto+Mono:wght@400;500;600&display=swap“ rel=„stylesheet“> <style> /* ══════════════════════════════════════════════════

 ALL STYLES SCOPED TO #ut-app — zero global leakage

═══════════════════════════════════════════════════ */ #ut-app {

  1. -ut-green: #16a34a;
  2. -ut-green-mid: #22c55e;
  3. -ut-green-light: #dcfce7;
  4. -ut-green-glow: rgba(22,163,74,0.22);
  5. -ut-green-dim: rgba(22,163,74,0.10);
  6. -ut-red: #dc2626;
  7. -ut-red-mid: #ef4444;
  8. -ut-red-light: #fee2e2;
  9. -ut-red-glow: rgba(220,38,38,0.18);
  10. -ut-red-dim: rgba(220,38,38,0.09);
  11. -ut-surface: rgba(255,255,255,0.85);
  12. -ut-surface2: rgba(248,249,252,0.98);
  13. -ut-border: rgba(0,0,0,0.09);
  14. -ut-shadow: 0 2px 14px rgba(0,0,0,0.07);
  15. -ut-text: #1a1a2e;
  16. -ut-muted: #6b7280;
  17. -ut-dim: #9ca3af;
  18. -ut-purple: #7c3aed;

font-family: ‘DM Sans’, system-ui, sans-serif; font-size: 16px; line-height: 1.5; color: #1a1a2e; background: transparent; box-sizing: border-box; /* Kein festes height/overflow — passt sich dem Container an */ position: relative; width: 100%; min-width: 0; }

/* Hard reset only inside the app — no bleed outward */ #ut-app *:not(select):not(input):not(button):not(option), #ut-app *::before, #ut-app *::after { box-sizing: border-box; margin: 0; font-family: inherit; } #ut-app * { box-sizing: border-box; font-family: inherit; }

/* ── Screens ── */ #ut-setup, #ut-timer, #ut-result { position: relative; width: 100%; display: none; flex-direction: column; align-items: center; justify-content: flex-start; } #ut-setup { display: flex; } #ut-timer { align-items: stretch; min-height: 500px; } #ut-result { position: fixed; inset: 0; z-index: 10; background: rgba(255,255,255,0.97); backdrop-filter: blur(10px); align-items: center; justify-content: center; }

/* ══════════════════════════════════════════════════ SETUP SCREEN ═══════════════════════════════════════════════════ */ #ut-setup { padding: 20px 40px; gap: 0; }

.ut-hdr { text-align: center; margin-bottom: 20px; } .ut-hdr h1 { font-family: ‘Bebas Neue’, sans-serif; font-size: clamp(24px, 3.8vw, 46px); letter-spacing: 4px; background: linear-gradient(135deg, #16a34a 15%, #4ade80 52%, #dc2626 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; } .ut-hdr p { color: #6b7280; font-size: 11px; letter-spacing: 2.5px; text-transform: uppercase; margin-top: 2px; }

.ut-grid { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 12px; width: min(800px, 86vw); margin-bottom: 12px; }

.ut-card { background: rgba(255,255,255,0.94); border: 1px solid rgba(0,0,0,0.07); border-radius: 16px; padding: 22px 22px 20px 22px; display: flex; flex-direction: column; gap: 12px; box-shadow: 0 1px 0 rgba(0,0,0,0.05), 0 4px 18px rgba(0,0,0,0.08); backdrop-filter: blur(12px); } .ut-card label, .ut-card-label { font-size: 10px; letter-spacing: 2.5px; text-transform: uppercase; color: #6b7280; font-weight: 600; display: block; margin: 0; padding: 0; line-height: 1.4; }

.ut-card select { background: rgba(248,249,252,0.98); border: 1.5px solid rgba(0,0,0,0.10); border-radius: 9px; color: #1a1a2e; font-family: ‘DM Mono’, monospace; font-size: 14px; padding: 12px 36px 12px 14px; width: 100%; outline: none; cursor: pointer; appearance: none; -webkit-appearance: none; 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 1l5 5 5-5’ stroke=’%236b7280’ stroke-width=‘1.5’ fill=‘none’ stroke-linecap=‘round’/%3E%3C/svg%3E”); background-repeat: no-repeat; background-position: right 14px center; box-shadow: 0 1px 3px rgba(0,0,0,0.06) inset; margin: 0; } .ut-card select:focus { border-color: #16a34a; box-shadow: 0 0 0 3px rgba(22,163,74,0.10); }

/* Timer choice */ .ut-tchoice { display: flex; gap: 8px; } .ut-tbtn { flex: 1; padding: 11px 16px; border-radius: 10px; border: 1.5px solid rgba(0,0,0,0.10); background: rgba(248,249,252,0.98); color: #6b7280; font-family: ‘DM Sans’, sans-serif; font-size: 12px; font-weight: 700; cursor: pointer; transition: all 0.16s; letter-spacing: 1px; text-transform: uppercase; box-shadow: 0 1px 0 rgba(0,0,0,0.08), 0 2px 6px rgba(0,0,0,0.04); } .ut-tbtn.green.active { background: linear-gradient(160deg, #f0fdf4 0%, #dcfce7 100%); border-color: #16a34a; color: #15803d; box-shadow: 0 1px 0 rgba(21,128,61,0.15), 0 3px 12px rgba(22,163,74,0.22); } .ut-tbtn.red.active { background: linear-gradient(160deg, #fff5f5 0%, #fee2e2 100%); border-color: #dc2626; color: #b91c1c; box-shadow: 0 1px 0 rgba(185,28,28,0.15), 0 3px 12px rgba(220,38,38,0.20); } .ut-tbtn:hover:not(.active) { border-color: #9ca3af; color: #1a1a2e; background: #fff; }

/* Goal */ .ut-goal-val { font-family: ‘Bebas Neue’, sans-serif; font-size: 34px; text-align: center; color: #16a34a; letter-spacing: 2px; line-height: 1; } .ut-goal-sub { font-size: 9px; text-align: center; color: #6b7280; letter-spacing: 1.5px; text-transform: uppercase; }

#ut-app input[type=range] { -webkit-appearance: none; appearance: none; height: 5px; border-radius: 3px; background: linear-gradient(90deg, #22c55e, #dcfce7); width: 100%; cursor: pointer; border: none; outline: none; display: block; } #ut-app input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; width: 20px; height: 20px; border-radius: 50%; background: #16a34a; border: 3px solid #fff; box-shadow: 0 1px 6px rgba(22,163,74,0.25); cursor: pointer; } #ut-app input[type=range]::-moz-range-thumb { width: 20px; height: 20px; border-radius: 50%; background: #16a34a; border: 3px solid #fff; box-shadow: 0 1px 6px rgba(22,163,74,0.25); cursor: pointer; } .ut-rlabels { display: flex; justify-content: space-between; font-size: 10px; color: #9ca3af; font-family: ‘DM Mono’, monospace; }

/* Button row */ .ut-btnrow { display: flex; gap: 10px; width: min(800px, 86vw); align-items: stretch; } .ut-start-btn { flex: 1; padding: 15px 40px; border-radius: 12px; border: none; background: linear-gradient(160deg, #22c55e 0%, #16a34a 100%); color: #fff; font-family: ‘Bebas Neue’, sans-serif; font-size: 18px; letter-spacing: 3.5px; cursor: pointer; transition: all 0.16s; box-shadow: 0 2px 0 #166534, 0 5px 18px rgba(22,163,74,0.30); text-shadow: 0 1px 2px rgba(0,0,0,0.15); } .ut-start-btn:hover:not(:disabled) { transform: translateY(-1px); box-shadow: 0 3px 0 #166534, 0 8px 26px rgba(22,163,74,0.35); } .ut-start-btn:active:not(:disabled) { transform: translateY(1px); box-shadow: 0 1px 0 #166534, 0 2px 10px rgba(22,163,74,0.22); } .ut-start-btn:disabled { opacity: 0.38; cursor: not-allowed; transform: none; box-shadow: none; }

.ut-now-btn { padding: 15px 28px; border-radius: 12px; border: 1.5px solid #16a34a; background: linear-gradient(160deg, #f0fdf4 0%, #dcfce7 100%); color: #15803d; font-family: ‘DM Sans’, sans-serif; font-size: 12px; font-weight: 700; letter-spacing: 1px; text-transform: uppercase; cursor: pointer; transition: all 0.16s; white-space: nowrap; display: flex; align-items: center; gap: 6px; box-shadow: 0 2px 0 rgba(21,128,61,0.18), 0 3px 10px rgba(22,163,74,0.14); } .ut-now-btn:hover:not(:disabled) { background: linear-gradient(160deg, #22c55e 0%, #16a34a 100%); color: #fff; border-color: #15803d; box-shadow: 0 2px 0 #166534, 0 6px 18px rgba(22,163,74,0.30); transform: translateY(-1px); } .ut-now-btn:active:not(:disabled) { transform: translateY(1px); box-shadow: 0 1px 0 rgba(21,128,61,0.18); } .ut-now-btn:disabled { opacity: 0.35; cursor: not-allowed; }

.ut-wait-note { margin-top: 9px; font-size: 11px; color: #6b7280; letter-spacing: 1.5px; text-transform: uppercase; display: none; text-align: center; width: min(800px, 86vw); } .ut-wait-note.show { display: block; } .ut-wait-note span { font-family: ‘DM Mono’, monospace; color: #1a1a2e; font-weight: 600; } .ut-wait-note button { background: none; border: none; color: #16a34a; font-size: 11px; letter-spacing: 1px; text-transform: uppercase; font-weight: 700; cursor: pointer; text-decoration: underline; font-family: ‘DM Sans’, sans-serif; }

/* ══════════════════════════════════════════════════ TIMER SCREEN ═══════════════════════════════════════════════════ */ #ut-timer { display: none; position: relative; width: 100%; height: 100vh; min-height: 500px; }

.ut-topbar { height: auto; min-height: 50px; display: flex; align-items: center; justify-content: space-between; padding: 8px 16px; border-bottom: 1.5px solid rgba(0,0,0,0.08); background: rgba(255,255,255,0.90); flex-shrink: 0; gap: 10px; backdrop-filter: blur(12px); box-shadow: 0 1px 8px rgba(0,0,0,0.06); /* Keine flex-wrap: Leiste bleibt immer einzeilig und stabil */ flex-wrap: nowrap; overflow: hidden; } .ut-clock { font-family: ‘Roboto Mono’, monospace; font-size: 19px; font-weight: 500; letter-spacing: 0; color: #1a1a2e; font-variant-numeric: tabular-nums; width: 7ch; flex-shrink: 0; } .ut-topinfo { display: flex; align-items: center; gap: 12px; flex-wrap: nowrap; flex-shrink: 0; } .ut-chip { display: flex; align-items: center; gap: 5px; font-size: 10px; letter-spacing: 1.5px; text-transform: uppercase; color: #6b7280; white-space: nowrap; flex-shrink: 0; } /* Label-Teil des Chips: feste Breite je nach Inhalt */ .ut-chip span:first-child { flex-shrink: 0; } .ut-chip .utv { font-family: ‘Roboto Mono’, monospace; font-size: 13px; color: #1a1a2e; font-weight: 500; letter-spacing: 0; font-variant-numeric: tabular-nums; display: inline-block; text-align: left; flex-shrink: 0; } /* Zeitwerte MM:SS — genau 5 Zeichen */ .ut-chip .utv.utv-time { width: auto; display: inline-flex; align-items: center; } /* Prozentwerte — genau 4 Zeichen für “100%” */ .ut-chip .utv.utv-pct { width: auto; display: inline-flex; align-items: center; }

/* Jede Ziffer in einer eigenen Box — absolute Pixelbreite */ .utd { display: inline-block; width: 0.62em; text-align: center; font-family: ‘Roboto Mono’, monospace; font-variant-numeric: tabular-nums; } /* Ziffern für Prozentwert */ .utdd { display: inline-block; width: 0.62em; text-align: center; font-family: ‘Roboto Mono’, monospace; font-variant-numeric: tabular-nums; } /* Prozentzeichen — feste Breite */ .utdpc { display: inline-block; width: 0.7em; text-align: center; font-family: ‘Roboto Mono’, monospace; } /* Doppelpunkt-Trennzeichen etwas enger */ .utdc { width: 0.38em; } /* Zeitwerte: max. “99:99” = 5 Zeichen */ .ut-chip .utv.utv-time { width: 5ch; } /* Prozentwerte: max. “100%” = 4 Zeichen */ .ut-chip .utv.utv-pct { width: 4ch; }

.ut-chip.gc .utv { color: #16a34a; }

.ut-otbadge { padding: 3px 11px; border-radius: 20px; font-size: 10px; font-weight: 700; letter-spacing: 2px; text-transform: uppercase; background: #fee2e2; color: #dc2626; border: 1.5px solid rgba(220,38,38,0.30); animation: ut-pred 1.2s ease-in-out infinite; } @keyframes ut-pred { 0%,100% { box-shadow: 0 0 0 0 rgba(220,38,38,0.18); } 50% { box-shadow: 0 0 10px 3px rgba(220,38,38,0.18); } }

/* Timers area */ .ut-area { flex: 1; display: flex; align-items: center; justify-content: center; padding: 10px 14px; min-height: 0; } .ut-panel { flex: 1; display: flex; align-items: center; justify-content: center; height: 100%; } .ut-divider { width: 1.5px; height: 52%; background: rgba(0,0,0,0.08); flex-shrink: 0; }

.ut-rwrap { position: relative; cursor: pointer; transition: transform 0.13s ease; border-radius: 50%; } .ut-rwrap:active { transform: scale(0.966); } .ut-rwrap svg { display: block; }

.ut-rinner { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; pointer-events: none; gap: 3px; } .ut-rlbl { font-size: 11px; letter-spacing: 3px; text-transform: uppercase; font-weight: 700; } .ut-rtime { font-family: ‘Bebas Neue’, sans-serif; line-height: 1; letter-spacing: 2px; } .ut-rstat { font-size: 10px; letter-spacing: 2px; text-transform: uppercase; font-weight: 600; opacity: 0.55; }

.ut-panel.ag .ut-rwrap { filter: drop-shadow(0 0 16px rgba(22,163,74,0.22)) drop-shadow(0 4px 10px rgba(22,163,74,0.10)); animation: ut-ps 2.2s ease-in-out infinite; } .ut-panel.ar .ut-rwrap { filter: drop-shadow(0 0 16px rgba(220,38,38,0.18)) drop-shadow(0 4px 10px rgba(220,38,38,0.10)); animation: ut-ps 2.2s ease-in-out infinite; } @keyframes ut-ps { 0%,100% { transform:scale(1); } 50% { transform:scale(1.012); } }

/* ══════════════════════════════════════════════════ RESULT SCREEN ═══════════════════════════════════════════════════ */ #ut-result { display: none; position: absolute; inset: 0; align-items: center; justify-content: center; } .ut-rcard { width: min(640px, 92vw); background: #fff; border: 1.5px solid rgba(0,0,0,0.08); border-radius: 22px; padding: 30px 34px; text-align: center; box-shadow: 0 8px 40px rgba(0,0,0,0.10); } .ut-rtitle { font-family: ‘Bebas Neue’, sans-serif; font-size: clamp(26px, 3.8vw, 42px); letter-spacing: 4px; margin-bottom: 4px; } .ut-rtitle.ok { color: #16a34a; } .ut-rtitle.no { color: #dc2626; } .ut-rsub { font-size: 11px; letter-spacing: 2px; color: #6b7280; text-transform: uppercase; margin-bottom: 24px; } .ut-rbars { display: flex; gap: 12px; margin-bottom: 18px; } .ut-rbi { flex: 1; background: rgba(248,249,252,0.98); border-radius: 12px; padding: 14px 12px; border: 1px solid rgba(0,0,0,0.08); } .ut-rbil { font-size: 10px; letter-spacing: 2px; text-transform: uppercase; font-weight: 700; margin-bottom: 9px; } .ut-rbil.g { color: #16a34a; } .ut-rbil.r { color: #dc2626; } .ut-rbt { height: 8px; background: #e5e7eb; border-radius: 4px; overflow: hidden; margin-bottom: 8px; } .ut-rbf { height: 100%; border-radius: 4px; width: 0; transition: width 1s ease; } .ut-rbf.g { background: linear-gradient(90deg, #16a34a, #22c55e); } .ut-rbf.r { background: linear-gradient(90deg, #dc2626, #ef4444); } .ut-rbp { font-family: ‘Bebas Neue’, sans-serif; font-size: 30px; letter-spacing: 1px; line-height: 1; } .ut-rbp.g { color: #16a34a; } .ut-rbp.r { color: #dc2626; } .ut-rbt2 { font-family: ‘DM Mono’, monospace; font-size: 11px; color: #6b7280; } .ut-rgoal { font-size: 13px; color: #6b7280; margin-bottom: 18px; line-height: 1.7; } .ut-rgoal strong { color: #1a1a2e; } .ut-racts { display: flex; gap: 10px; justify-content: center; } .ut-rbtn { padding: 11px 24px; border-radius: 9px; border: 1.5px solid rgba(0,0,0,0.09); background: rgba(248,249,252,0.98); color: #1a1a2e; font-family: ‘DM Sans’, sans-serif; font-size: 12px; font-weight: 700; letter-spacing: 1.5px; text-transform: uppercase; cursor: pointer; transition: all 0.16s; } .ut-rbtn:hover { border-color: #9ca3af; } .ut-rbtn.p { background: #dcfce7; border-color: #16a34a; color: #16a34a; } /* ══════════════════════════════════════════════════ RESPONSIVE — Tablet & Mobile ═══════════════════════════════════════════════════ */

/* Tablet: schmaler als 700px */ @media (max-width: 700px) { #ut-setup { padding: 14px 16px; overflow-y: auto; justify-content: flex-start; padding-top: 20px; }

.ut-hdr { margin-bottom: 14px; } .ut-hdr h1 { font-size: clamp(22px, 6vw, 36px); letter-spacing: 2px; } .ut-hdr p { font-size: 10px; letter-spacing: 1.5px; }

.ut-grid { grid-template-columns: 1fr 1fr; width: 100%; gap: 10px; margin-bottom: 10px; }

/* Ziel-Karte nimmt alle Spalten ein */ .ut-grid .ut-card:last-child { grid-column: 1 / -1; }

.ut-btnrow { width: 100%; flex-direction: column; gap: 8px; } .ut-start-btn { font-size: 16px; padding: 14px 24px; } .ut-now-btn { justify-content: center; padding: 13px 24px; }

.ut-wait-note { width: 100%; font-size: 10px; }

/* Timer-Leiste: zweizeilig auf Hochkant */ .ut-topbar { flex-wrap: wrap; padding: 8px 12px; gap: 6px; } .ut-topinfo { gap: 8px; width: 100%; justify-content: flex-start; } .ut-clock { font-size: 15px; width: 7.5ch; } .ut-chip { font-size: 9px; gap: 3px; } .ut-chip .utv { font-size: 11px; } .ut-chip .utv.utv-time { width: 5ch; } .ut-chip .utv.utv-pct { width: 4ch; }

/* Timer-Ringe kleiner */ .ut-area { padding: 6px 10px; } }

/* Smartphone Hochkant: schmaler als 480px */ @media (max-width: 480px) { #ut-setup { padding: 12px 12px; }

.ut-grid { grid-template-columns: 1fr; gap: 8px; } .ut-grid .ut-card:last-child { grid-column: 1; }

/* Ziel-Karte: vertikal stapeln */ .ut-grid .ut-card[style*=“flex-direction:row”], .ut-grid .ut-card[style*=“flex-direction: row”] { flex-direction: column !important; align-items: flex-start !important; }

.ut-card { padding: 16px 16px; } .ut-card select { font-size: 15px; padding: 13px 36px 13px 14px; } .ut-tbtn { font-size: 13px; padding: 12px 12px; }

.ut-start-btn { font-size: 15px; letter-spacing: 2px; } .ut-now-btn { font-size: 13px; }

/* Topbar: alles kompakter */ .ut-clock { font-size: 15px; } .ut-chip { font-size: 8.5px; } .ut-chip .utv { font-size: 11px; } .ut-otbadge { font-size: 9px; padding: 2px 8px; }

/* Timer-Ringe: stapeln */ .ut-area { flex-direction: column; padding: 6px 12px; gap: 0; } .ut-divider { width: 60%; height: 1.5px; } .ut-panel { height: auto; flex: 0 0 auto; } }

/* Querformat erzwingen wenn klein genug */ @media (max-height: 420px) { #ut-setup { flex-direction: row; flex-wrap: wrap; align-content: center; padding: 8px 16px; overflow-y: auto; } .ut-hdr { width: 100%; margin-bottom: 8px; } .ut-hdr h1 { font-size: 22px; } .ut-grid { gap: 8px; margin-bottom: 8px; } .ut-card { padding: 12px 14px; gap: 8px; } .ut-topbar { padding: 6px 12px; } }

</style> </head> <body>

<div id=„ut-app“>

<!-- ══ SETUP ══ -->
<div id="ut-setup">
  <div class="ut-hdr">
    <h1>Unterrichts-Timer</h1>
    <p>Konfiguration der Stunde</p>
  </div>

``` <div class=„ut-grid“>

<div class="ut-card">
  <label>Startzeit</label>
  <select id="ut-sel-start"></select>
</div>
<div class="ut-card">
  <label>Stundendauer</label>
  <select id="ut-sel-dur">
    <option value="45" selected>45 Minuten</option>
    <option value="90">90 Minuten</option>
  </select>
</div>
<div class="ut-card">
  <label>Erster aktiver Timer</label>
  <div class="ut-tchoice">
    <button class="ut-tbtn green active" id="ut-btn-g" onclick="utSetFirst('green')">● Grün</button>
    <button class="ut-tbtn red"          id="ut-btn-r" onclick="utSetFirst('red')">● Rot</button>
  </div>
</div>
<div class="ut-card" style="grid-column:1/-1;flex-direction:row;align-items:center;gap:20px;padding:22px 22px 20px 22px;">
  <div style="flex-shrink:0;min-width:78px;text-align:center;">
    <div class="ut-goal-val" id="ut-goal-val">75%</div>
    <div class="ut-goal-sub">Ziel Grün</div>
  </div>
  <div style="flex:1;display:flex;flex-direction:column;gap:8px;">
    <label class="ut-card-label">Ziel: Anteil grüner Timer-Zeit</label>
    <input type="range" id="ut-slider" min="50" max="95" step="5" value="75" oninput="utGoal(this.value)">
    <div class="ut-rlabels"><span>50%</span><span>95%</span></div>
  </div>
</div>

</div>

<div class=„ut-btnrow“>

<button class="ut-start-btn" id="ut-sbtn" onclick="utConfirm()">Stunde konfigurieren &amp; warten</button>
<button class="ut-now-btn"   id="ut-nbtn" onclick="utNow()" title="Sofort starten ohne Wartezeit">▶ Sofort starten</button>

</div> <div class=„ut-wait-note“ id=„ut-wnote“>

Warte auf Startzeit: <span id="ut-wdisp">--:--</span>
&nbsp;·&nbsp;
<button onclick="utNow()">Sofort starten</button>

</div> ```

</div>
<!-- ══ TIMER ══ -->
<div id="ut-timer">
  <div class="ut-topbar">
    <div class="ut-clock" id="ut-clock"><span class="utd" id="utd-ch0">0</span><span class="utd" id="utd-ch1">0</span><span class="utd utdc">:</span><span class="utd" id="utd-cm0">0</span><span class="utd" id="utd-cm1">0</span><span class="utd utdc">:</span><span class="utd" id="utd-cs0">0</span><span class="utd" id="utd-cs1">0</span></div>
    <div class="ut-topinfo">
      <div class="ut-chip"><span>Gesamt</span><span class="utv utv-time" id="ut-total"><span class="utd" id="utd-total-0">0</span><span class="utd" id="utd-total-1">0</span><span class="utd utdc">:</span><span class="utd" id="utd-total-2">0</span><span class="utd" id="utd-total-3">0</span></span></div>
      <div class="ut-chip"><span>Verbleibend</span><span class="utv utv-time" id="ut-rem"><span class="utd" id="utd-rem-0">4</span><span class="utd" id="utd-rem-1">5</span><span class="utd utdc">:</span><span class="utd" id="utd-rem-2">0</span><span class="utd" id="utd-rem-3">0</span></span></div>
      <div class="ut-chip gc"><span>Ziel</span><span class="utv utv-pct" id="ut-gtop">75%</span></div>
      <div class="ut-chip gc"><span>Grün</span><span class="utv utv-pct" id="ut-gcur"><span class="utd utdd" id="utd-gp-h"> </span><span class="utd utdd" id="utd-gp-t">0</span><span class="utd utdd" id="utd-gp-o">0</span><span class="utdd utdpc">%</span></span></div>
      <span class="ut-otbadge" id="ut-otbadge" style="display:none">Nachzeit</span>
    </div>
  </div>

``` <div class=„ut-area“>

<!-- GREEN -->
<div class="ut-panel" id="ut-pg">
  <div class="ut-rwrap" onclick="utSwitch('green')">
    <svg id="ut-svg-g" viewBox="0 0 300 300" width="260" height="260">
      <circle cx="150" cy="150" r="130" fill="rgba(255,255,255,0.75)"/>
      <circle cx="150" cy="150" r="130" fill="none" stroke="#dcfce7" stroke-width="15"/>
      <circle id="ut-prog-g" cx="150" cy="150" r="130" fill="none"
        stroke="#22c55e" stroke-width="15" stroke-linecap="round"
        stroke-dasharray="816.8" stroke-dashoffset="816.8"
        transform="rotate(-90 150 150)"/>
    </svg>
    <div class="ut-rinner">
      <div class="ut-rlbl" style="color:#16a34a">Grün</div>
      <div class="ut-rtime" id="ut-tg" style="color:#16a34a">00:00</div>
      <div class="ut-rstat" id="ut-sg" style="color:#16a34a">Aktiv</div>
    </div>
  </div>
</div>
<div class="ut-divider"></div>
<!-- RED -->
<div class="ut-panel" id="ut-pr">
  <div class="ut-rwrap" onclick="utSwitch('red')">
    <svg id="ut-svg-r" viewBox="0 0 300 300" width="260" height="260">
      <circle cx="150" cy="150" r="130" fill="rgba(255,255,255,0.75)"/>
      <circle cx="150" cy="150" r="130" fill="none" stroke="#fee2e2" stroke-width="15"/>
      <circle id="ut-prog-r" cx="150" cy="150" r="130" fill="none"
        stroke="#ef4444" stroke-width="15" stroke-linecap="round"
        stroke-dasharray="816.8" stroke-dashoffset="816.8"
        transform="rotate(-90 150 150)"/>
    </svg>
    <div class="ut-rinner">
      <div class="ut-rlbl" style="color:#dc2626">Rot</div>
      <div class="ut-rtime" id="ut-tr" style="color:#dc2626">00:00</div>
      <div class="ut-rstat" id="ut-sr" style="color:#dc2626">Pausiert</div>
    </div>
  </div>
</div>

</div> ```

</div>
<!-- ══ RESULT ══ -->
<div id="ut-result">
  <div class="ut-rcard">
    <div class="ut-rtitle" id="ut-rtitle">Ziel erreicht!</div>
    <div class="ut-rsub">Auswertung der Unterrichtsstunde</div>
    <div class="ut-rbars">
      <div class="ut-rbi">
        <div class="ut-rbil g">Grüne Zeit</div>
        <div class="ut-rbt"><div class="ut-rbf g" id="ut-bg"></div></div>
        <div class="ut-rbp g" id="ut-pg-pct">0%</div>
        <div class="ut-rbt2" id="ut-ag">0.0 min</div>
      </div>
      <div class="ut-rbi">
        <div class="ut-rbil r">Rote Zeit</div>
        <div class="ut-rbt"><div class="ut-rbf r" id="ut-br"></div></div>
        <div class="ut-rbp r" id="ut-pr-pct">0%</div>
        <div class="ut-rbt2" id="ut-ar">0.0 min</div>
      </div>
    </div>
    <div class="ut-rgoal" id="ut-rgoal"></div>
    <div class="ut-racts">
      <button class="ut-rbtn p" onclick="utReset()">Neu starten</button>
    </div>
  </div>
</div>

</div><!– #ut-app –>

<script> (function(){ 'use strict';

var cfg = { startH:7, startM:0, duration:45, first:'green', goal:75 }; var st = { phase:'idle', active:'green', gMs:0, rMs:0, last:null,

          total:0, limit:0, wIv:null, tIv:null, cIv:null };

/* ── helpers ── */ function pad(n){ return String(n).padStart(2,'0'); } function berlin(){

var d=new Date(), b=new Date(d.toLocaleString('en-US',{timeZone:'Europe/Berlin'}));
return {h:b.getHours(),m:b.getMinutes(),s:b.getSeconds(),date:b};

} function mmss(ms){

var s=Math.floor(ms/1000), m=Math.floor(s/60);
return pad(m)+':'+pad(s%60);

} function el(id){ return document.getElementById(id); }

/* ── Init ── */ function init(){

var sel=el('ut-sel-start');
for(var h=7;h<=17;h++){
  for(var m=0;m<60;m+=5){
    if(h===17&&m>0) break;
    var o=document.createElement('option');
    o.value=h+':'+m;
    o.textContent=pad(h)+':'+pad(m)+' Uhr';
    sel.appendChild(o);
  }
}
var now=berlin(), bh=now.h, bm=Math.ceil((now.m+1)/5)*5;
if(bm>=60){bm=0;bh++;}
if(bh>17){bh=17;bm=0;}
sel.value=bh+':'+bm;
startClock();

}

function startClock(){

function tick(){
  var b=berlin();
  var hh=pad(b.h), mm=pad(b.m), ss=pad(b.s);
  el('utd-ch0').textContent=hh[0]; el('utd-ch1').textContent=hh[1];
  el('utd-cm0').textContent=mm[0]; el('utd-cm1').textContent=mm[1];
  el('utd-cs0').textContent=ss[0]; el('utd-cs1').textContent=ss[1];
}
tick();
st.cIv=setInterval(tick,500);

}

/* ── Setup callbacks ── */ window.utSetFirst=function(w){

cfg.first=w;
el('ut-btn-g').classList.toggle('active',w==='green');
el('ut-btn-r').classList.toggle('active',w==='red');

}; window.utGoal=function(v){

cfg.goal=parseInt(v);
el('ut-goal-val').textContent=v+'%';
el('ut-slider').value=v;

}; function applyCfg(){

var p=el('ut-sel-start').value.split(':').map(Number);
cfg.startH=p[0]; cfg.startM=p[1];
cfg.duration=parseInt(el('ut-sel-dur').value);
st.limit=cfg.duration*60*1000;

} window.utConfirm=function(){

applyCfg();
el('ut-sbtn').disabled=true;
el('ut-nbtn').disabled=true;
el('ut-sbtn').textContent='Warte auf Startzeit…';
el('ut-wnote').classList.add('show');
updWait();
st.wIv=setInterval(function(){
  updWait();
  var n=berlin();
  if(n.h===cfg.startH&&n.m===cfg.startM&&n.s<3){
    clearInterval(st.wIv); begin();
  }
},500);

}; window.utNow=function(){

clearInterval(st.wIv);
applyCfg();
begin();

}; function updWait(){ el('ut-wdisp').textContent=pad(cfg.startH)+':'+pad(cfg.startM); }

/* ── Begin ── */ function begin(){

st.phase='running'; st.active=cfg.first;
st.gMs=0; st.rMs=0; st.total=0;
st.last=Date.now();
el('ut-gtop').textContent=cfg.goal+'%';
// Verbleibend korrekt initialisieren über Digit-Spans (nicht textContent!)
setMmss('utd-rem-0','utd-rem-1','utd-rem-2','utd-rem-3', st.limit);
el('ut-setup').style.display='none';
el('ut-timer').style.display='flex';
panels(); resize();
st.tIv=setInterval(tick,100);

}

/* ── Tick ── */ function tick(){

if(st.phase==='done') return;
var now=Date.now(), d=now-st.last; st.last=now;
if(st.active==='green') st.gMs+=d; else st.rMs+=d;
st.total=st.gMs+st.rMs;
if(st.phase==='running'&&st.total>=st.limit){
  if(st.active==='green'){ end(); return; }
  else{ st.phase='overtime'; el('ut-otbadge').style.display='inline-flex'; }
}
render();

}

/* ── Switch ── */ window.utSwitch=function(w){

if(st.phase==='done'||st.phase==='idle') return;
if(st.phase==='overtime'&&w==='green'){
  var now=Date.now(),d=now-st.last; st.last=now;
  if(st.active==='red') st.rMs+=d; else st.gMs+=d;
  st.total=st.gMs+st.rMs;
  end(); return;
}
if(st.active===w) return;
st.active=w; st.last=Date.now();
panels(); render();

};

/* ── Digit helpers ── */ function setMmss(d0, d1, d2, d3, ms){

var s=Math.floor(ms/1000), m=Math.floor(s/60);
var mm=pad(m), ss=pad(s%60);
el(d0).textContent=mm[0];
el(d1).textContent=mm[1];
el(d2).textContent=ss[0];
el(d3).textContent=ss[1];

} function setGreenPct(gp){

// Hunderter: '1' bei 100, sonst geschütztes Leerzeichen
el('utd-gp-h').textContent = gp === 100 ? '1' : '\u2007';
// Zehner: Ziffer wenn >= 10, sonst Leerzeichen
el('utd-gp-t').textContent = gp >= 10 ? String(Math.floor(gp / 10) % 10) : '\u2007';
// Einer: immer eine Ziffer
el('utd-gp-o').textContent = String(gp % 10);

}

/* ── Render ── */ function render(){

el('ut-tg').textContent=mmss(st.gMs);
el('ut-tr').textContent=mmss(st.rMs);
setMmss('utd-total-0','utd-total-1','utd-total-2','utd-total-3', st.total);
setMmss('utd-rem-0',  'utd-rem-1',  'utd-rem-2',  'utd-rem-3',  Math.max(0,st.limit-st.total));
var gp=st.total>0?Math.round(st.gMs/st.total*100):0;
setGreenPct(gp);
if(st.limit>0){
  var C=816.8;
  el('ut-prog-g').style.strokeDashoffset=Math.max(0,C-(st.gMs/st.limit)*C);
  el('ut-prog-r').style.strokeDashoffset=Math.max(0,C-(st.rMs/st.limit)*C);
}

} function panels(){

el('ut-pg').className='ut-panel'+(st.active==='green'?' ag':'');
el('ut-pr').className='ut-panel'+(st.active==='red'?' ar':'');
el('ut-sg').textContent=st.active==='green'?'Läuft':'Pausiert';
el('ut-sr').textContent=st.active==='red'?'Läuft':'Pausiert';

}

/* ── End ── */ function end(){

st.phase='done'; clearInterval(st.tIv); render();
var tot=st.total, gp=tot>0?Math.round(st.gMs/tot*100):0, rp=100-gp, ok=gp>=cfg.goal;
setTimeout(function(){
  var gm=(st.gMs/60000).toFixed(1), rm=(st.rMs/60000).toFixed(1);
  el('ut-rtitle').textContent=ok?'✓ Ziel erreicht!':'✗ Ziel nicht erreicht';
  el('ut-rtitle').className='ut-rtitle '+(ok?'ok':'no');
  el('ut-pg-pct').textContent=gp+'%'; el('ut-pr-pct').textContent=rp+'%';
  el('ut-ag').textContent=gm+' min';  el('ut-ar').textContent=rm+' min';
  el('ut-rgoal').innerHTML='Ziel: <strong>'+cfg.goal+'% grüne Zeit</strong> &nbsp;·&nbsp; Ergebnis: <strong>'+gp+'% grün</strong> / <strong>'+rp+'% rot</strong>';
  el('ut-result').style.display='flex';
  setTimeout(function(){ el('ut-bg').style.width=gp+'%'; el('ut-br').style.width=rp+'%'; },80);
},350);

}

/* ── Reset ── */ window.utReset=function(){

clearInterval(st.tIv); clearInterval(st.wIv);
st={phase:'idle',active:'green',gMs:0,rMs:0,last:null,total:0,limit:0,wIv:null,tIv:null,cIv:st.cIv};
el('ut-result').style.display='none';
el('ut-timer').style.display='none';
el('ut-setup').style.display='flex';
el('ut-sbtn').disabled=false; el('ut-nbtn').disabled=false;
el('ut-sbtn').textContent='Stunde konfigurieren & warten';
el('ut-wnote').classList.remove('show');
el('ut-otbadge').style.display='none';
el('ut-prog-g').style.strokeDashoffset=816.8;
el('ut-prog-r').style.strokeDashoffset=816.8;

};

/* ── Resize ── */ function resize(){

var area=document.querySelector('#ut-app .ut-area');
if(!area) return;
var areaH = area.clientHeight > 0 ? area.clientHeight : window.innerHeight - 60;
var areaW = area.clientWidth  > 0 ? area.clientWidth  : window.innerWidth;
var sz=Math.max(150, Math.min(areaH - 20, areaW / 2 - 44, 340));
['ut-svg-g','ut-svg-r'].forEach(function(id){
  var s=el(id); if(s){s.style.width=sz+'px';s.style.height=sz+'px';}
});
var fs=Math.max(24,sz*0.205);
document.querySelectorAll('#ut-app .ut-rtime').forEach(function(e){e.style.fontSize=fs+'px';});

} window.addEventListener('resize',resize);

init(); })(); </script>

</body> </html>

Cookies helfen bei der Bereitstellung von Inhalten. Diese Website verwendet Cookies. Mit der Nutzung der Website erklären Sie sich damit einverstanden, dass Cookies auf Ihrem Computer gespeichert werden. Außerdem bestätigen Sie, dass Sie unsere Datenschutzerklärung gelesen und verstanden haben. Wenn Sie nicht einverstanden sind, verlassen Sie die Website.Weitere Information
tools/ur-timer.1773302235.txt.gz · Zuletzt geändert: von Eric Weber