A world that is a torus, with a figure-eight sun
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557@import "@fontsource/space-grotesk/500.css";@import "@fontsource/space-grotesk/600.css";@import "@fontsource/ibm-plex-sans/400.css";@import "@fontsource/ibm-plex-sans/500.css";@import "@fontsource/ibm-plex-mono/400.css";@import "@fontsource/ibm-plex-mono/500.css";
:root { --bg-deep: #0b0e14; --bg-panel: #131822; --bg-panel-border: #232b38;
--torus-glaze: #c97b56; --sun-gold: #ffb454; --orbit-trace: #6fd3c7; --bg-track: #1a2130;
--text-primary: #e9e6df; --text-secondary: #8d94a3; --text-tertiary: #545e70;
--font-display: "Space Grotesk", sans-serif; --font-body: "IBM Plex Sans", sans-serif; --font-mono: "IBM Plex Mono", monospace;
--radius-md: 10px; --radius-sm: 6px;
color-scheme: dark;}
* { box-sizing: border-box;}
html,body { height: 100%;}
body { margin: 0; background: var(--bg-deep); color: var(--text-primary); font-family: var(--font-body); overflow: hidden;}
#app { display: grid; grid-template-rows: auto 1fr auto; height: 100dvh; width: 100vw;}
/* -- top bar -------------------------------------------------------- */
.topbar { display: flex; align-items: center; justify-content: space-between; gap: 1.5rem; padding: 0.85rem 1.5rem; border-bottom: 1px solid var(--bg-panel-border); background: var(--bg-panel);}
.topbar__title { display: flex; align-items: baseline; gap: 0.65rem; min-width: 0;}
.topbar__eyebrow { font-family: var(--font-display); font-size: 0.7rem; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase; color: var(--torus-glaze); white-space: nowrap;}
.topbar__title h1 { font-family: var(--font-display); font-size: 1.05rem; font-weight: 500; margin: 0; color: var(--text-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;}
/* -- viewport: the 3D panel --------------------------------------------- */
.viewport { display: grid; min-height: 0;}
.panel { position: relative; background: var(--bg-deep); min-width: 0; min-height: 0;}
.panel__canvas-host { position: absolute; inset: 0; width: 100%; height: 100%; display: block;}
/* Two symmetric overlay affordances bookend the viewport: Physics (left) controls the world's parameters, Cutaway (right) controls how you see it. Same pill treatment, different accent color on press. */.overlay-pill { position: absolute; top: 0.9rem; z-index: 2; display: flex; align-items: center; gap: 0.45rem; padding: 0.4rem 0.75rem 0.4rem 0.6rem; border-radius: 999px; border: 1px solid var(--bg-panel-border); background: rgba(19, 24, 34, 0.75); backdrop-filter: blur(6px); color: var(--text-secondary); font-family: var(--font-display); font-size: 0.72rem; font-weight: 500; letter-spacing: 0.02em; cursor: pointer; transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease;}
.overlay-pill--left { left: 1rem;}
.overlay-pill--right { right: 1rem;}
.overlay-pill:hover { border-color: #364155; color: var(--text-primary);}
.overlay-pill:focus-visible { outline: 2px solid var(--sun-gold); outline-offset: 2px;}
.overlay-pill svg { width: 16px; height: 16px; flex-shrink: 0;}
.overlay-pill[aria-pressed="true"] { border-color: var(--orbit-trace); color: var(--orbit-trace); background: rgba(111, 211, 199, 0.1);}
.overlay-pill--physics[aria-pressed="true"] { border-color: var(--sun-gold); color: var(--sun-gold); background: rgba(255, 180, 84, 0.1);}
/* -- physics drawer ------------------------------------------------------ */
.physics-drawer { overflow: hidden; max-height: 0; transition: max-height 260ms cubic-bezier(0.4, 0, 0.2, 1); background: var(--bg-panel); border-top: 1px solid var(--bg-panel-border);}
.physics-drawer.open { max-height: 10.5rem;}
.physics-drawer__inner { padding: 1.1rem 1.5rem 1.3rem; display: grid; grid-template-columns: repeat(2, 1fr); gap: 1.6rem;}
.slider-field { display: flex; flex-direction: column; gap: 0.55rem;}
.slider-field__head { display: flex; align-items: baseline; justify-content: space-between; gap: 0.5rem;}
.slider-field__label { font-family: var(--font-display); font-size: 0.68rem; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-secondary); display: flex; align-items: center; gap: 0.4rem;}
.slider-field__label .swatch { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0;}
.swatch--season { background: var(--torus-glaze);}
.swatch--orbit { background: var(--orbit-trace);}
.slider-field__value { font-family: var(--font-mono); font-size: 0.82rem; color: var(--text-primary); font-variant-numeric: tabular-nums; white-space: nowrap;}
/* The orbit-size slider shows a live preview of the actual current orbit behind the track, and the season slider a schematic of the world's rotation against the sun's fixed plane -- both previews double as the control's own feedback rather than a separate readout. */.slider-track { position: relative; height: 2.4rem;}
.slider-track__preview { position: absolute; inset: 0; border-radius: 6px; background: var(--bg-track); overflow: hidden; border: 1px solid var(--bg-panel-border);}
.slider-track__preview svg { width: 100%; height: 100%; display: block;}
.slider-track input[type="range"] { -webkit-appearance: none; appearance: none; position: absolute; inset: 0; width: 100%; height: 100%; background: transparent; margin: 0; cursor: pointer;}
.slider-track input[type="range"]::-webkit-slider-runnable-track { height: 100%; background: transparent;}
.slider-track input[type="range"]::-moz-range-track { height: 100%; background: transparent;}
input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; width: 14px; height: 14px; border-radius: 50%; cursor: grab; box-shadow: 0 0 0 3px var(--bg-deep), 0 0 10px 1px currentColor; border: none;}
input[type="range"]::-moz-range-thumb { width: 14px; height: 14px; border-radius: 50%; cursor: grab; box-shadow: 0 0 0 3px var(--bg-deep), 0 0 10px 1px currentColor; border: none;}
.thumb-season::-webkit-slider-thumb,.thumb-season::-moz-range-thumb { background: var(--torus-glaze); color: var(--torus-glaze);}
.thumb-orbit::-webkit-slider-thumb,.thumb-orbit::-moz-range-thumb { background: var(--orbit-trace); color: var(--orbit-trace);}
.slider-field__caption { font-family: var(--font-mono); font-size: 0.66rem; color: var(--text-tertiary); line-height: 1.4;}
@media (max-width: 560px) { .physics-drawer__inner { grid-template-columns: 1fr; }}
/* -- transport strip --------------------------------------------------- */
.transport { display: flex; align-items: center; gap: 1rem; padding: 0.7rem 1.5rem; border-top: 1px solid var(--bg-panel-border); background: var(--bg-panel);}
.transport-btn { display: grid; place-items: center; width: 2.4rem; height: 2.4rem; flex-shrink: 0; border-radius: 50%; border: 1px solid var(--bg-panel-border); background: #1a2130; color: var(--text-primary); cursor: pointer; transition: background-color 120ms ease, border-color 120ms ease;}
.transport-btn:hover { background: #212a3c; border-color: #364155;}
.transport-btn:focus-visible { outline: 2px solid var(--sun-gold); outline-offset: 2px;}
.transport-btn .icon { width: 18px; height: 18px; fill: currentColor;}
.scrubber { position: relative; flex: 1 1 auto; height: 2.4rem; display: flex; align-items: center; cursor: pointer; touch-action: none;}
.scrubber__track { position: absolute; left: 0; right: 0; height: 3px; border-radius: 2px; background: var(--bg-panel-border);}
.scrubber__fill { position: absolute; left: 0; height: 3px; border-radius: 2px; background: var(--orbit-trace); width: 0%; pointer-events: none;}
.scrubber__ticks { position: absolute; inset: 0;}
/* 12 of these now (one every 4 hours of this world's 48-hour day), so each is smaller and plainer than the old 8 labeled critical-point ticks -- a quiet dotted ring, not individually called out. */.scrubber__tick { position: absolute; top: 50%; transform: translate(-50%, -50%); width: 4px; height: 4px; border-radius: 50%; background: var(--text-tertiary); pointer-events: none;}
.scrubber__playhead { position: absolute; top: 50%; left: 0%; width: 12px; height: 12px; border-radius: 50%; transform: translate(-50%, -50%) rotate(45deg); background: var(--sun-gold); box-shadow: 0 0 10px 1px rgba(255, 180, 84, 0.65); pointer-events: none; transition: background-color 120ms ease;}
.readout { font-family: var(--font-mono); font-size: 0.82rem; color: var(--text-secondary); width: 3rem; flex-shrink: 0; font-variant-numeric: tabular-nums;}
.speed-select { display: flex; align-items: center; gap: 0.5rem; flex-shrink: 0;}
.speed-select__label { font-family: var(--font-display); font-size: 0.68rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-tertiary);}
.speed-select select { font-family: var(--font-mono); font-size: 0.8rem; color: var(--text-primary); background: #1a2130; border: 1px solid var(--bg-panel-border); border-radius: var(--radius-sm); padding: 0.3rem 0.5rem; cursor: pointer;}
.speed-select select:focus-visible { outline: 2px solid var(--sun-gold); outline-offset: 1px;}
/* -- 3D panel fallback (e.g. WebGL unavailable) ------------------------ */
.panel-fallback { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 0.5rem; padding: 2rem; text-align: center; font-family: var(--font-body); color: var(--text-secondary);}
.panel-fallback p { margin: 0;}
.panel-fallback__detail { font-family: var(--font-mono); font-size: 0.78rem; color: var(--text-tertiary); max-width: 32ch;}
/* -- status / loading / error overlay --------------------------------- */
.status { position: fixed; inset: 0; display: none; align-items: center; justify-content: center; background: var(--bg-deep); font-family: var(--font-mono); font-size: 0.9rem; color: var(--text-secondary); text-align: center; padding: 2rem; z-index: 10;}
.status.status--visible { display: flex;}
.status.status--error { color: #e08a7a;}
/* -- responsive: stack panels on narrow viewports ----------------------- */
@media (max-width: 860px) { .transport { flex-wrap: wrap; row-gap: 0.6rem; }
.readout { order: 4; }
.speed-select { order: 5; }}
/* -- reduced motion ----------------------------------------------------- */
@media (prefers-reduced-motion: reduce) { .transport-btn, .scrubber__playhead { transition: none; }}