hypeorcode
Network offOpen alone (new tab)

Run details

Model
opencode/space-bunny-free
Route
opencode CLI
Reasoning
provider default
Limits
60 min · 524,288 output tokens
Date
2 Oct 2026
Time
4 min 35 s
Size
26 kB
Tokens
23,916 in, 17,821 out
Paid
Not billed per run (CLI plan)

Raw files: output · meta.json

Exact prompt

Draw a mechanical wristwatch that shows the current local time, with a sweeping seconds hand and a date window. Make it look expensive.

It must be one complete, self-contained HTML file: inline all CSS and JavaScript, and make no network requests of any kind (no CDNs, web fonts or remote images). Save it as index.html in the current directory, then stop. Do not ask questions.

Source

26 kB 797 lines Raw

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<title>Meridien — Automatic</title>
<style>
  :root{
    --gold-1:#f9ecc4;
    --gold-2:#e2c483;
    --gold-3:#bd9450;
    --gold-4:#8a6526;
    --gold-5:#5f4415;
    --cream:#f3ece0;
    --lume:#c9f2dd;
    --dial-1:#2e3f52;
    --dial-2:#1b2735;
    --dial-3:#0d141d;
    --case-w:380px;
    --bezel-w:352px;
    --dial-w:316px;
  }

  *{box-sizing:border-box;margin:0;padding:0}

  html,body{height:100%}

  body{
    background:
      radial-gradient(120% 90% at 50% -10%, #232a33 0%, #14181d 38%, #0a0c0f 72%, #060708 100%),
      #060708;
    color:var(--cream);
    font-family:"Didot","Bodoni 72","Hoefler Text","Playfair Display",Garamond,Georgia,"Times New Roman",serif;
    display:flex;align-items:center;justify-content:center;
    min-height:100vh;
    padding:40px 16px;
    -webkit-font-smoothing:antialiased;
    overflow-x:hidden;
  }

  /* ---------- studio ambience ---------- */
  body::before{
    content:"";
    position:fixed;inset:0;
    background:
      radial-gradient(60% 45% at 50% 46%, rgba(255,246,225,.10), rgba(255,246,225,0) 70%),
      radial-gradient(35% 22% at 22% 12%, rgba(150,190,255,.07), rgba(150,190,255,0) 70%);
    pointer-events:none;
  }
  body::after{
    content:"";
    position:fixed;left:0;right:0;bottom:0;height:34vh;
    background:linear-gradient(to top, rgba(255,255,255,.05), rgba(255,255,255,0));
    pointer-events:none;
  }

  .scene{
    position:relative;
    display:flex;flex-direction:column;align-items:center;
    transform-origin:center center;
  }

  .shadow{
    position:absolute;left:50%;top:50%;
    width:calc(var(--case-w) * 1.5);height:calc(var(--case-w) * 1.5);
    transform:translate(-50%,-46%);
    background:radial-gradient(closest-side, rgba(0,0,0,.85), rgba(0,0,0,.45) 55%, rgba(0,0,0,0) 78%);
    filter:blur(6px);
    z-index:-1;
  }

  /* ---------- leather strap ---------- */
  .strap{
    position:relative;
    width:calc(var(--case-w) * .56);
    height:150px;
    border-radius:14px;
    background:
      radial-gradient(60% 120% at 50% 100%, rgba(255,255,255,.10), rgba(255,255,255,0) 60%),
      linear-gradient(90deg, #0a0705 0%, #241a13 12%, #3a2a1d 38%, #2a1e15 62%, #150e09 88%, #0a0705 100%);
    box-shadow:
      inset 0 0 0 1px rgba(255,225,180,.10),
      inset 0 14px 22px rgba(0,0,0,.55),
      0 14px 26px rgba(0,0,0,.55);
  }
  .strap::before{
    content:"";
    position:absolute;inset:0;
    border-radius:14px;
    background:
      repeating-linear-gradient(64deg, rgba(255,255,255,.035) 0 1px, rgba(0,0,0,0) 1px 5px),
      repeating-linear-gradient(-58deg, rgba(0,0,0,.10) 0 2px, rgba(0,0,0,0) 2px 7px);
    mix-blend-mode:overlay;
    opacity:.9;
  }
  .strap::after{
    content:"";
    position:absolute;inset:7px;
    border-radius:9px;
    border-left:2px dashed rgba(226,205,164,.30);
    border-right:2px dashed rgba(226,205,164,.30);
    opacity:.75;
  }
  .strap--top{border-radius:16px 16px 5px 5px;margin-bottom:-8px}
  .strap--top::after{border-top:0}
  .strap--bot{border-radius:5px 5px 20px 20px;margin-top:-8px}
  .strap--bot::after{border-bottom:0}

  .holes{
    position:absolute;left:50%;top:14px;bottom:14px;
    width:16px;transform:translateX(-50%);
    display:flex;flex-direction:column;justify-content:space-evenly;align-items:center;
  }
  .holes i{
    width:11px;height:7px;border-radius:50%;
    background:radial-gradient(closest-side,#000,#0d0906);
    box-shadow:inset 0 1px 2px rgba(0,0,0,.95), 0 1px 0 rgba(255,225,180,.13);
  }

  /* ---------- case ---------- */
  .case{
    position:relative;
    width:var(--case-w);height:var(--case-w);
    border-radius:50%;
    background:
      conic-gradient(from 205deg,
        #5f636a 0deg, #c9ced4 22deg, #83888f 48deg, #eef1f5 74deg, #6b7076 100deg,
        #b9bec5 128deg, #54585e 156deg, #dde1e6 186deg, #7c8188 214deg, #f3f5f8 244deg,
        #666b71 272deg, #c4c9cf 302deg, #5b5f65 330deg, #e8ebef 352deg, #5f636a 360deg);
    box-shadow:
      0 40px 70px rgba(0,0,0,.72),
      0 14px 24px rgba(0,0,0,.5),
      0 0 0 1px rgba(0,0,0,.6),
      inset 0 0 2px rgba(255,255,255,.55);
    display:flex;align-items:center;justify-content:center;
  }
  /* polished chamfer */
  .case::before{
    content:"";
    position:absolute;inset:0;border-radius:50%;
    background:linear-gradient(150deg, rgba(255,255,255,.45) 0%, rgba(255,255,255,0) 26%, rgba(0,0,0,.30) 74%, rgba(0,0,0,.10) 100%);
    mix-blend-mode:overlay;
  }
  .case::after{
    content:"";
    position:absolute;inset:3px;border-radius:50%;
    border:1px solid rgba(255,255,255,.28);
    box-shadow:inset 0 0 12px rgba(255,255,255,.10);
  }

  .bezel{
    position:relative;
    width:var(--bezel-w);height:var(--bezel-w);
    border-radius:50%;
    background:
      radial-gradient(100% 100% at 32% 22%, #2b3037 0%, #171b21 42%, #0b0e12 78%, #05070a 100%);
    box-shadow:
      inset 0 3px 5px rgba(255,255,255,.22),
      inset 0 -6px 14px rgba(0,0,0,.85),
      0 2px 5px rgba(0,0,0,.6),
      0 0 0 2px rgba(0,0,0,.75);
    display:flex;align-items:center;justify-content:center;
  }
  .bezel::before{
    content:"";
    position:absolute;inset:0;border-radius:50%;
    background:conic-gradient(from 0deg,
      rgba(255,255,255,.14) 0deg, rgba(255,255,255,0) 30deg,
      rgba(255,255,255,.10) 90deg, rgba(255,255,255,0) 140deg,
      rgba(255,255,255,.16) 200deg, rgba(255,255,255,0) 250deg,
      rgba(255,255,255,.12) 310deg, rgba(255,255,255,.14) 360deg);
  }

  /* ---------- dial ---------- */
  .dial{
    position:relative;
    width:var(--dial-w);height:var(--dial-w);
    border-radius:50%;
    overflow:hidden;
    background:
      radial-gradient(120% 120% at 30% 18%, var(--dial-1) 0%, var(--dial-2) 46%, var(--dial-3) 100%);
    box-shadow:
      inset 0 0 0 1px rgba(0,0,0,.9),
      inset 0 10px 26px rgba(0,0,0,.55),
      inset 0 -14px 30px rgba(0,0,0,.5);
  }

  /* brushed sunburst + micro guilloché */
  .dial__brush,
  .dial__guilloche,
  .dial__sheen,
  .dial__vignette{
    position:absolute;inset:0;border-radius:50%;pointer-events:none;
  }
  .dial__brush{
    background:repeating-conic-gradient(from 0deg,
      rgba(255,255,255,.055) 0deg 1.05deg,
      rgba(255,255,255,0) 1.05deg 2.35deg,
      rgba(0,0,0,.06) 2.35deg 3.5deg,
      rgba(255,255,255,0) 3.5deg 4.9deg);
    mix-blend-mode:soft-light;
  }
  .dial__guilloche{
    background:
      repeating-radial-gradient(circle at 50% 50%, rgba(255,255,255,.045) 0 .5px, rgba(255,255,255,0) .5px 3px),
      repeating-conic-gradient(from 12deg, rgba(255,255,255,.03) 0deg .55deg, rgba(255,255,255,0) .55deg 1.5deg);
    opacity:.55;
  }
  .dial__sheen{
    background:conic-gradient(from 0deg,
      rgba(255,255,255,0) 0deg,
      rgba(255,246,225,.13) 40deg,
      rgba(255,255,255,0) 90deg,
      rgba(0,0,0,.10) 180deg,
      rgba(255,255,255,0) 270deg,
      rgba(255,246,225,.09) 320deg,
      rgba(255,255,255,0) 360deg);
    mix-blend-mode:soft-light;
    animation:spin 42s linear infinite;
  }
  @keyframes spin{to{transform:rotate(360deg)}}

  .dial__vignette{
    background:radial-gradient(closest-side, rgba(0,0,0,0) 52%, rgba(0,0,0,.28) 82%, rgba(0,0,0,.55) 100%);
  }

  /* ---------- dial typography ---------- */
  .brand{
    position:absolute;left:50%;top:calc(50% - 45px);
    transform:translate(-50%,-50%);
    text-align:center;pointer-events:none;
  }
  .brand__name{
    font-size:19px;letter-spacing:.34em;text-indent:.34em;
    line-height:1;
    background:linear-gradient(180deg,var(--gold-1) 0%,var(--gold-2) 38%,var(--gold-3) 58%,var(--gold-4) 76%,var(--gold-2) 100%);
    -webkit-background-clip:text;background-clip:text;color:transparent;
    text-shadow:0 1px 0 rgba(0,0,0,.5);
    filter:drop-shadow(0 1px 1px rgba(0,0,0,.6));
  }
  .brand__sub{
    margin-top:6px;
    font-size:8.5px;letter-spacing:.44em;text-indent:.44em;
    color:rgba(240,232,216,.52);
  }
  .model{
    position:absolute;left:50%;top:calc(50% + 62px);
    transform:translate(-50%,-50%);
    font-size:8.5px;letter-spacing:.30em;text-indent:.30em;
    color:rgba(240,232,216,.44);
    pointer-events:none;
  }

  /* ---------- date window ---------- */
  .date{
    position:absolute;
    left:calc(50% + 57px);
    top:50%;
    width:50px;height:34px;
    transform:translateY(-50%);
    border-radius:4px;
    background:linear-gradient(180deg,#fdfcf8,#eae5da 55%,#d9d3c6);
    display:flex;align-items:center;justify-content:center;
    font-size:21px;letter-spacing:.02em;
    color:#16181c;
    font-family:"Didot","Bodoni 72",Georgia,serif;
    box-shadow:
      inset 0 1px 2px rgba(255,255,255,.9),
      inset 0 -2px 4px rgba(0,0,0,.18),
      0 0 0 1.5px var(--gold-3),
      0 0 0 2.5px rgba(0,0,0,.55),
      0 2px 5px rgba(0,0,0,.45);
  }
  .date::after{
    content:"";
    position:absolute;inset:0;border-radius:4px;
    background:linear-gradient(200deg, rgba(255,255,255,.75), rgba(255,255,255,0) 45%);
    pointer-events:none;
  }

  /* ---------- svg layers ---------- */
  .layer{position:absolute;inset:0;width:100%;height:100%;pointer-events:none}

  .idx-fill{fill:url(#gIndex)}
  .idx-lume{fill:url(#gLume)}
  .tick{fill:rgba(243,236,224,.72)}
  .tick-min{fill:rgba(243,236,224,.34)}

  /* ---------- hands ---------- */
  .hand{
    transform-box:view-box;
    filter:drop-shadow(0 3px 3px rgba(0,0,0,.55));
  }
  .hand-gold{fill:url(#gHand); stroke:rgba(90,64,18,.55); stroke-width:.5}
  .hand-facet{fill:rgba(74,50,10,.55)}
  .hand-lume{fill:url(#gLume)}

  /* ---------- crystal ---------- */
  .crystal{
    position:absolute;inset:0;border-radius:50%;pointer-events:none;
    background:
      linear-gradient(122deg,
        rgba(255,255,255,.20) 0%,
        rgba(255,255,255,.07) 14%,
        rgba(255,255,255,.01) 30%,
        rgba(255,255,255,0) 55%,
        rgba(255,255,255,.05) 74%,
        rgba(255,255,255,.16) 92%,
        rgba(255,255,255,.22) 100%);
  }
  .crystal::before{
    content:"";
    position:absolute;left:-14%;top:-22%;
    width:64%;height:46%;
    border-radius:50%;
    background:radial-gradient(closest-side, rgba(255,255,255,.24), rgba(255,255,255,.06) 55%, rgba(255,255,255,0) 78%);
    filter:blur(4px);
    transform:rotate(-22deg);
  }
  .crystal::after{
    content:"";
    position:absolute;inset:0;border-radius:50%;
    box-shadow:
      inset 0 0 0 1px rgba(255,255,255,.22),
      inset 0 2px 6px rgba(255,255,255,.18),
      inset 0 -10px 22px rgba(0,0,0,.35);
  }
  .arc-glint{
    position:absolute;inset:8px;border-radius:50%;pointer-events:none;
    border-top:1px solid rgba(255,255,255,.30);
    border-left:1px solid rgba(255,255,255,.10);
    transform:rotate(-28deg) scale(1.015);
  }

  /* ---------- crown ---------- */
  .crown{
    position:absolute;
    right:calc(var(--case-w) / -2 + 2px);
    top:50%;
    transform:translateY(-50%);
    width:34px;height:52px;
    border-radius:7px / 9px;
    background:
      linear-gradient(90deg,#3a3d42 0%,#8e939a 12%,#e9ecf0 26%,#a7acb3 38%,
                      #eef1f4 50%,#a2a7ae 62%,#e6e9ed 76%,#8b9097 88%,#3d4045 100%);
    box-shadow:
      0 8px 16px rgba(0,0,0,.6),
      inset 0 1px 0 rgba(255,255,255,.6),
      inset 0 -1px 0 rgba(0,0,0,.5);
    cursor:pointer;
    border:0;padding:0;
  }
  .crown::before{
    content:"";
    position:absolute;inset:5px 4px;
    border-radius:5px / 7px;
    background:repeating-linear-gradient(180deg,
      rgba(255,255,255,.55) 0 1.5px, rgba(0,0,0,.28) 1.5px 3.5px);
    opacity:.75;
  }
  .crown::after{
    content:"";
    position:absolute;inset:0;border-radius:7px / 9px;
    box-shadow:inset 0 0 0 1px rgba(255,255,255,.25);
  }
  .crown:active{filter:brightness(.9)}
  .crown:focus-visible{outline:2px solid rgba(226,205,164,.8);outline-offset:4px}

  .crown__cap{
    position:absolute;right:calc(var(--case-w) / -2 + 2px);
    top:50%;
    transform:translateY(-50%);
    width:12px;height:22px;
    border-radius:0 4px 4px 0;
    background:linear-gradient(90deg,#6c7076,#c9ced4 40%,#8b9097 70%,#4b4e53);
    box-shadow:inset 0 1px 0 rgba(255,255,255,.5);
    pointer-events:none;
  }

  /* ---------- caption ---------- */
  .caption{
    margin-top:26px;text-align:center;
    opacity:.5;
  }
  .caption h1{
    font-size:13px;font-weight:400;letter-spacing:.42em;text-indent:.42em;
    color:rgba(243,236,224,.82);
  }
  .caption p{
    margin-top:9px;
    font-size:10.5px;letter-spacing:.24em;text-indent:.24em;
    color:rgba(243,236,224,.42);
    font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif;
  }

  @media (prefers-reduced-motion: reduce){
    .dial__sheen{animation:none}
  }

  @media (max-width: 760px){ :root{ --case-w:300px; --bezel-w:278px; --dial-w:250px } }
  @media (max-width: 460px){ :root{ --case-w:232px; --bezel-w:215px; --dial-w:193px } }
  @media (max-height: 780px) and (min-width: 761px){
    :root{ --case-w:300px; --bezel-w:278px; --dial-w:250px }
  }
</style>
</head>
<body>

<div class="scene">
  <div class="shadow" aria-hidden="true"></div>

  <div class="strap strap--top" aria-hidden="true"></div>

  <div class="case">
    <div class="bezel">
      <div class="dial">

        <div class="dial__brush" aria-hidden="true"></div>
        <div class="dial__guilloche" aria-hidden="true"></div>

        <!-- static: chapter ring, applied indices, power reserve -->
        <svg class="layer" id="staticLayer" viewBox="0 0 316 316" role="img" aria-label="Dial markings"></svg>

        <div class="brand" aria-hidden="true">
          <div class="brand__name">MERIDIEN</div>
          <div class="brand__sub">GENÈVE</div>
        </div>

        <div class="date" id="dateWindow" aria-hidden="true">01</div>

        <div class="model" aria-hidden="true">AUTOMATIC</div>

        <div class="dial__sheen" aria-hidden="true"></div>

        <!-- moving: hands -->
        <svg class="layer" id="handLayer" viewBox="0 0 316 316" role="img" aria-label="Time hands"></svg>

        <div class="crystal" aria-hidden="true"></div>
        <div class="arc-glint" aria-hidden="true"></div>
      </div>
    </div>

    <button class="crown" id="crown" type="button" aria-label="Wind the watch"></button>
    <div class="crown__cap" aria-hidden="true"></div>
  </div>

  <div class="strap strap--bot" aria-hidden="true">
    <div class="holes"><i></i><i></i><i></i><i></i><i></i></div>
  </div>

  <div class="caption">
    <h1>MERIDIEN</h1>
    <p>Automatic · 21&nbsp;Jewels · Click the crown to wind</p>
  </div>
</div>

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

  var C = 158;                 // dial centre in viewBox units
  var R_TRACK = 146;           // minute track
  var R_IDX   = 118;           // applied index centre

  var staticLayer = document.getElementById("staticLayer");
  var handLayer   = document.getElementById("handLayer");
  var dateWindow  = document.getElementById("dateWindow");
  var crown       = document.getElementById("crown");

  var SVGNS = "http://www.w3.org/2000/svg";
  var REDUCED = window.matchMedia("(prefers-reduced-motion: reduce)").matches;

  function el(name, attrs, parent) {
    var n = document.createElementNS(SVGNS, name);
    for (var k in attrs) if (attrs[k] !== null) n.setAttribute(k, attrs[k]);
    (parent || staticLayer).appendChild(n);
    return n;
  }
  function polar(cx, cy, r, deg) {
    var a = (deg - 90) * Math.PI / 180;
    return [cx + r * Math.cos(a), cy + r * Math.sin(a)];
  }

  /* ---------------- static dial ---------------- */
  staticLayer.innerHTML =
    '<defs>' +
      '<linearGradient id="gIndex" x1="0" y1="0" x2="0" y2="1">' +
        '<stop offset="0"   stop-color="#fdf3d6"/>' +
        '<stop offset=".34" stop-color="#e6cb8c"/>' +
        '<stop offset=".62" stop-color="#b98f49"/>' +
        '<stop offset=".84" stop-color="#8a6526"/>' +
        '<stop offset="1"   stop-color="#dcbe7c"/>' +
      '</linearGradient>' +
      '<linearGradient id="gLume" x1="0" y1="0" x2="0" y2="1">' +
        '<stop offset="0" stop-color="#e9fbf2"/>' +
        '<stop offset=".55" stop-color="#c3ecd8"/>' +
        '<stop offset="1" stop-color="#8fc6ae"/>' +
      '</linearGradient>' +
      '<radialGradient id="gRehaut" cx=".5" cy=".5" r=".5">' +
        '<stop offset=".78" stop-color="#000" stop-opacity="0"/>' +
        '<stop offset="1" stop-color="#000" stop-opacity=".55"/>' +
      '</radialGradient>' +
    '</defs>';

  // minute + hour track ticks
  for (var i = 0; i < 60; i++) {
    var isHour = i % 5 === 0;
    var a = i * 6;
    var len = isHour ? 12 : 6;
    var w   = isHour ? 2.2 : 1;
    var p1  = polar(C, C, R_TRACK, a);
    var p2  = polar(C, C, R_TRACK - len, a);
    el("line", {
      x1: p1[0].toFixed(2), y1: p1[1].toFixed(2),
      x2: p2[0].toFixed(2), y2: p2[1].toFixed(2),
      "stroke-width": w,
      "stroke-linecap": "round",
      stroke: isHour ? "rgba(226,205,164,.78)" : "rgba(243,236,224,.34)",
      fill: "none"
    });
  }

  // applied faceted baton indices
  function baton(deg, length, width) {
    var g = el("g", { transform: "rotate(" + deg + " " + C + " " + C + ")" }, staticLayer);
    var half = width / 2;
    var rOut = R_IDX + length / 2;
    var rIn  = R_IDX - length / 2;
    // body
    el("path", {
      d: "M " + (C - half) + " " + (C - rOut) +
         " L " + (C + half) + " " + (C - rOut) +
         " L " + (C + half * 0.62) + " " + (C - rIn) +
         " L " + (C - half * 0.62) + " " + (C - rIn) + " Z",
      class: "idx-fill",
      stroke: "rgba(70,48,10,.6)", "stroke-width": ".6"
    }, g);
    // lume core
    el("rect", {
      x: (C - half * 0.34).toFixed(2),
      y: (C - rOut + length * 0.20).toFixed(2),
      width: (width * 0.34).toFixed(2),
      height: (length * 0.58).toFixed(2),
      rx: ".6", class: "idx-lume", opacity: ".85"
    }, g);
    // top bevel highlight
    el("line", {
      x1: (C - half).toFixed(2), y1: (C - rOut).toFixed(2),
      x2: (C + half).toFixed(2), y2: (C - rOut).toFixed(2),
      stroke: "rgba(255,250,232,.65)", "stroke-width": ".8", "stroke-linecap": "round"
    }, g);
    return g;
  }

  for (var h = 0; h < 12; h++) {
    var deg = h * 30;
    if (h === 0) {
      baton(deg - 4.2, 26, 5.6);
      baton(deg + 4.2, 26, 5.6);
    } else if (h === 9) {
      baton(deg, 17, 5.6);          // shortened to clear the power reserve
    } else {
      baton(deg, 24, 5.6);
    }
  }

  // rehaut / inner shadow ring
  el("circle", { cx: C, cy: C, r: R_TRACK + 8, fill: "url(#gRehaut)" });

  /* ---- power reserve indicator (9 o'clock) ---- */
  var PR_X = C - 82, PR_Y = C, PR_R = 26;
  var prArc, prNeedle;
  (function powerReserve() {
    var g = el("g", {}, staticLayer);

    // recessed subdial well
    el("circle", {
      cx: PR_X, cy: PR_Y, r: PR_R + 5,
      fill: "rgba(0,0,0,.42)",
      stroke: "rgba(226,205,164,.22)", "stroke-width": ".8"
    }, g);
    el("circle", {
      cx: PR_X, cy: PR_Y, r: PR_R + 3.4,
      fill: "none", stroke: "rgba(0,0,0,.55)", "stroke-width": "1.4"
    }, g);

    var a1 = polar(PR_X, PR_Y, PR_R - 4, 200);
    var a2 = polar(PR_X, PR_Y, PR_R - 4, -20);
    el("path", {
      d: "M " + a1[0].toFixed(2) + " " + a1[1].toFixed(2) +
         " A " + (PR_R - 4) + " " + (PR_R - 4) + " 0 1 1 " +
         a2[0].toFixed(2) + " " + a2[1].toFixed(2),
      fill: "none", stroke: "rgba(255,255,255,.13)", "stroke-width": "2",
      "stroke-linecap": "round", pathLength: "100"
    }, g);

    prArc = el("path", {
      d: "M " + a1[0].toFixed(2) + " " + a1[1].toFixed(2) +
         " A " + (PR_R - 4) + " " + (PR_R - 4) + " 0 1 1 " +
         a2[0].toFixed(2) + " " + a2[1].toFixed(2),
      fill: "none", stroke: "url(#gIndex)", "stroke-width": "2",
      "stroke-linecap": "round", pathLength: "100",
      "stroke-dasharray": "100", "stroke-dashoffset": "38"
    }, g);

    // scale marks
    for (var k = 0; k <= 8; k++) {
      var ang = 200 - (220 / 8) * k;
      var big = (k === 0 || k === 4 || k === 8);
      var r1 = PR_R - 1, r2 = r1 + (big ? 4.4 : 2.6);
      var q1 = polar(PR_X, PR_Y, r1, ang);
      var q2 = polar(PR_X, PR_Y, r2, ang);
      el("line", {
        x1: q1[0].toFixed(2), y1: q1[1].toFixed(2),
        x2: q2[0].toFixed(2), y2: q2[1].toFixed(2),
        stroke: big ? "rgba(226,205,164,.62)" : "rgba(243,236,224,.26)",
        "stroke-width": big ? 1.3 : .7, "stroke-linecap": "round"
      }, g);
    }

    prNeedle = el("g", {}, g);
    el("line", {
      x1: PR_X, y1: PR_Y + 5, x2: PR_X, y2: PR_Y - (PR_R - 6),
      stroke: "url(#gIndex)", "stroke-width": "1.5", "stroke-linecap": "round"
    }, prNeedle);
    el("circle", { cx: PR_X, cy: PR_Y, r: "2.4", fill: "url(#gIndex)" }, prNeedle);
  })();

  /* ---------------- hands ---------------- */
  handLayer.innerHTML =
    '<defs>' +
      '<linearGradient id="gHand" x1="0" y1="0" x2="1" y2="0">' +
        '<stop offset="0"    stop-color="#8a6526"/>' +
        '<stop offset=".18"  stop-color="#e8cf94"/>' +
        '<stop offset=".42"  stop-color="#fdf3d6"/>' +
        '<stop offset=".62"  stop-color="#e2c483"/>' +
        '<stop offset=".85"  stop-color="#a67c2c"/>' +
        '<stop offset="1"    stop-color="#f0dca8"/>' +
      '</linearGradient>' +
      '<radialGradient id="gCap" cx=".34" cy=".3" r=".8">' +
        '<stop offset="0" stop-color="#fdf6e2"/>' +
        '<stop offset=".5" stop-color="#d3ac66"/>' +
        '<stop offset="1" stop-color="#6c4c1a"/>' +
      '</radialGradient>' +
    '</defs>';

  var hourG = el("g", { class: "hand", id: "hourHand" }, handLayer);
  var minG  = el("g", { class: "hand", id: "minHand" }, handLayer);

  // dauphine hand builder
  function dauphine(parent, length, width, tail) {
    var tip = C - length;
    var sh  = width / 2;
    el("path", {
      d: "M " + C + " " + tip +
         " L " + (C - sh) + " " + (tip + length * 0.20) +
         " L " + (C - sh * 0.70) + " " + (C + tail) +
         " L " + C + " " + (C + tail + width * 0.42) +
         " L " + (C + sh * 0.70) + " " + (C + tail) +
         " L " + (C + sh) + " " + (tip + length * 0.20) + " Z",
      class: "hand-gold"
    }, parent);
    // faceted shadow half
    el("path", {
      d: "M " + C + " " + tip +
         " L " + (C + sh) + " " + (tip + length * 0.20) +
         " L " + (C + sh * 0.70) + " " + (C + tail) +
         " L " + C + " " + (C + tail + width * 0.42) + " Z",
      class: "hand-facet"
    }, parent);
    // lume channel
    el("path", {
      d: "M " + C + " " + (tip + length * 0.26) +
         " L " + (C - sh * 0.30) + " " + (tip + length * 0.30) +
         " L " + (C - sh * 0.24) + " " + (C + tail - 2) +
         " L " + C + " " + (C + tail + 1) +
         " L " + (C + sh * 0.24) + " " + (C + tail - 2) +
         " L " + (C + sh * 0.30) + " " + (tip + length * 0.30) + " Z",
      class: "hand-lume", opacity: ".9"
    }, parent);
  }

  dauphine(hourG, 100, 15, 13);
  dauphine(minG, 132, 12, 15);

  // seconds hand
  var secG = el("g", { class: "hand", id: "secHand" }, handLayer);
  el("rect", { x: C - 0.9, y: C - 142, width: 1.8, height: 168, rx: 0.9, fill: "url(#gIndex)" }, secG);
  el("circle", { cx: C, cy: C + 24, r: 6.4, fill: "none", stroke: "url(#gIndex)", "stroke-width": 1.6 }, secG);
  el("circle", { cx: C, cy: C - 132, r: 3.4, fill: "url(#gLume)", stroke: "rgba(90,64,18,.5)", "stroke-width": ".5" }, secG);

  // centre cap
  el("circle", { cx: C, cy: C, r: 6.2, fill: "url(#gCap)", stroke: "rgba(50,34,8,.6)", "stroke-width": ".6" }, handLayer);
  el("circle", { cx: C, cy: C, r: 2.1, fill: "rgba(20,14,4,.85)" }, handLayer);

  /* ---------------- power reserve state ---------------- */
  var reserve = 0.62;
  var reserveTarget = reserve;
  var autoWinding = false;

  function renderReserve() {
    var v = Math.max(0, Math.min(1, reserve));
    prArc.setAttribute("stroke-dashoffset", (100 - v * 100).toFixed(2));
    var ang = 200 - v * 220;
    prNeedle.setAttribute("transform",
      "rotate(" + ang.toFixed(2) + " " + PR_X + " " + PR_Y + ")");
  }

  function wind() {
    reserveTarget = 1;
    autoWinding = false;
  }
  crown.addEventListener("click", wind);
  staticLayer.addEventListener("click", wind);

  /* ---------------- time ---------------- */

  function setTransform(node, deg) {
    node.setAttribute("transform", "rotate(" + deg.toFixed(3) + " " + C + " " + C + ")");
  }

  function renderTime(ms) {
    var d = new Date();
    var s = ms / 1000;

    var sec = s % 60;
    var min = (d.getMinutes() + sec / 60) % 60;
    var hr  = (d.getHours() % 12) + min / 60;

    setTransform(hourG, hr * 30);
    setTransform(minG, min * 6);
    setTransform(secG, sec * 6);
  }

  var secBase = 0, secStart = performance.now();

  function tick() {
    var now = new Date();
    secBase = now.getSeconds() * 1000 + now.getMilliseconds();
    secStart = performance.now();
    renderDate();
    setTimeout(tick, 1000 - now.getMilliseconds());
  }

  function frame() {
    var now = performance.now();
    var ms = secBase + (now - secStart);

    if (!REDUCED) {
      renderTime(ms);
    } else {
      var d = new Date();
      var sec = d.getSeconds();
      var min = d.getMinutes() + sec / 60;
      var hr = (d.getHours() % 12) + min / 60;
      setTransform(hourG, hr * 30);
      setTransform(minG, min * 6);
      setTransform(secG, sec * 6);
    }

    // power reserve drains, then the rotor self-winds it back up
    var prev = reserve;
    if (reserveTarget > reserve) {
      reserve = Math.min(reserveTarget, reserve + 0.006);
    } else {
      reserve = Math.max(0, reserve - 0.0035);
      if (reserve === 0) { reserveTarget = 1; autoWinding = true; }
    }
    if (autoWinding && reserve >= 0.999) reserveTarget = reserve;
    if (Math.abs(reserve - prev) > 0.0001) renderReserve();

    requestAnimationFrame(frame);
  }

  function renderDate() {
    var txt = ("0" + new Date().getDate()).slice(-2);
    if (dateWindow.textContent !== txt) dateWindow.textContent = txt;
  }

  renderDate();
  renderReserve();
  tick();
  requestAnimationFrame(frame);

  // keep in sync when returning from a background tab
  document.addEventListener("visibilitychange", function () {
    if (!document.hidden) {
      var now = new Date();
      secBase = now.getSeconds() * 1000 + now.getMilliseconds();
      secStart = performance.now();
      renderDate();
    }
  });
})();
</script>
</body>
</html>

Space Bunny: other attempts

  • Space Bunny, Pelican: Not run: no OpenRouter route
  • Space Bunny, Landing: Not run: no OpenRouter route
  • Space Bunny, Breakout: Not run: no OpenRouter route
  • About · 164 words