1) Station-mix procedural days: past day 19 the kitchen deals from every station it taught — toast ~34%, then prep cuts (technique onion dice past 21), juice (better reamers + more pips later), the grill (4 pieces past 24), the pan (electric arrives 22, induction 26), the rib eye (random grain, electric past 23), and the fridge delivery. Each with its own ticket voice. Deals are seeded BY DAY: a reload re-deals the identical order (no reroll-scumming) and the harness can reproduce any day. 2) THE LEDGER on the title: one chip per reached day with your best grade stamped on it (S green through F red), click to replay. save.maxDay tracks furthest-ever progress so replaying day 5 for the S never locks day 19 away; old saves migrate (maxDay defaults to day). Verified live: 26-day sweep deals all 7 stations, deterministic re-deals; chip click starts day 5; procedural day-26 steak (electric fuel ramp) played end-to-end: rested, cut across a random grain, 9.1/10. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
721 lines
12 KiB
CSS
721 lines
12 KiB
CSS
:root {
|
|
--ink: #f3e9dc;
|
|
--ink-dim: #a9998a;
|
|
--paper: #efe4cf;
|
|
--char: #16110e;
|
|
--gold: #e8a53a;
|
|
--red: #c0392b;
|
|
--font: 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
|
--mono: ui-monospace, 'SF Mono', Menlo, monospace;
|
|
}
|
|
|
|
* {
|
|
margin: 0;
|
|
padding: 0;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
html,
|
|
body {
|
|
height: 100%;
|
|
overflow: hidden;
|
|
background: var(--char);
|
|
color: var(--ink);
|
|
font-family: var(--font);
|
|
-webkit-font-smoothing: antialiased;
|
|
}
|
|
|
|
#app {
|
|
position: fixed;
|
|
inset: 0;
|
|
}
|
|
|
|
canvas#c {
|
|
position: absolute;
|
|
inset: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
display: block;
|
|
touch-action: none;
|
|
}
|
|
|
|
#ui {
|
|
position: absolute;
|
|
inset: 0;
|
|
pointer-events: none;
|
|
user-select: none;
|
|
}
|
|
|
|
#ui > * {
|
|
pointer-events: auto;
|
|
}
|
|
|
|
.toast-panel {
|
|
position: absolute;
|
|
left: 24px;
|
|
bottom: 24px;
|
|
width: 290px;
|
|
padding: 16px 18px;
|
|
background: rgba(12, 9, 8, 0.72);
|
|
border: 1px solid rgba(243, 233, 220, 0.14);
|
|
border-radius: 10px;
|
|
backdrop-filter: blur(9px);
|
|
}
|
|
|
|
.toast-panel .row {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
.toast-panel .lbl {
|
|
font-size: 10px;
|
|
letter-spacing: 0.14em;
|
|
color: var(--ink-dim);
|
|
width: 74px;
|
|
flex: none;
|
|
}
|
|
|
|
.toast-panel .dial {
|
|
flex: 1;
|
|
accent-color: var(--gold);
|
|
}
|
|
|
|
.toast-panel .val {
|
|
font-family: var(--mono);
|
|
font-size: 13px;
|
|
color: var(--gold);
|
|
width: 18px;
|
|
text-align: right;
|
|
}
|
|
|
|
.toast-panel .sel {
|
|
flex: 1;
|
|
background: rgba(0, 0, 0, 0.4);
|
|
color: var(--ink);
|
|
border: 1px solid rgba(243, 233, 220, 0.18);
|
|
border-radius: 5px;
|
|
padding: 4px 6px;
|
|
font-size: 12px;
|
|
}
|
|
|
|
.toast-panel .cue {
|
|
margin-top: 14px;
|
|
font-size: 15px;
|
|
font-style: italic;
|
|
color: var(--ink);
|
|
min-height: 20px;
|
|
transition: color 0.4s;
|
|
}
|
|
|
|
.toast-panel .hint {
|
|
margin-top: 6px;
|
|
font-size: 11px;
|
|
letter-spacing: 0.1em;
|
|
color: var(--ink-dim);
|
|
min-height: 14px;
|
|
}
|
|
|
|
/* Pressure gauge: fill = what your wrist is making, gold = what the spread
|
|
needs to flow, red = where spreading becomes scraping. */
|
|
.toast-panel .gauge {
|
|
position: relative;
|
|
height: 9px;
|
|
margin-top: 14px;
|
|
border-radius: 5px;
|
|
background: rgba(255, 255, 255, 0.09);
|
|
overflow: hidden;
|
|
}
|
|
|
|
.toast-panel .gauge-fill {
|
|
position: absolute;
|
|
inset: 0 auto 0 0;
|
|
width: 0;
|
|
background: #8a7f70;
|
|
border-radius: 5px;
|
|
transition: background 0.15s;
|
|
}
|
|
|
|
.toast-panel .gauge-mark {
|
|
position: absolute;
|
|
top: -3px;
|
|
bottom: -3px;
|
|
width: 2px;
|
|
margin-left: -1px;
|
|
}
|
|
|
|
.toast-panel .gauge-mark.yield {
|
|
background: var(--gold);
|
|
}
|
|
|
|
.toast-panel .gauge-mark.scrape {
|
|
background: #e2603a;
|
|
}
|
|
|
|
.toast-panel .mode {
|
|
margin-top: 8px;
|
|
font-size: 11px;
|
|
letter-spacing: 0.09em;
|
|
color: var(--ink-dim);
|
|
min-height: 14px;
|
|
}
|
|
|
|
.toast-panel .load {
|
|
height: 5px;
|
|
margin-top: 8px;
|
|
border-radius: 3px;
|
|
background: rgba(255, 255, 255, 0.09);
|
|
overflow: hidden;
|
|
}
|
|
|
|
.toast-panel .load-fill {
|
|
height: 100%;
|
|
width: 0;
|
|
border-radius: 3px;
|
|
}
|
|
|
|
/* ---- the order ticket ---- */
|
|
.ticket {
|
|
position: absolute;
|
|
top: 22px;
|
|
left: 24px;
|
|
width: 268px;
|
|
padding: 16px 18px 14px;
|
|
color: #2b2118;
|
|
background: #efe4cf;
|
|
border-radius: 3px;
|
|
box-shadow: 0 10px 26px rgba(0, 0, 0, 0.5);
|
|
transform: rotate(-0.7deg);
|
|
}
|
|
|
|
.ticket-day {
|
|
font-family: var(--mono);
|
|
font-size: 10px;
|
|
letter-spacing: 0.22em;
|
|
color: #9b8b74;
|
|
}
|
|
|
|
.ticket-who {
|
|
font-size: 12px;
|
|
font-style: italic;
|
|
color: #7d6d58;
|
|
margin-top: 2px;
|
|
}
|
|
|
|
.ticket-text {
|
|
margin-top: 8px;
|
|
font-size: 14px;
|
|
line-height: 1.4;
|
|
}
|
|
|
|
.ticket-spec {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 5px;
|
|
margin-top: 11px;
|
|
}
|
|
|
|
.chip {
|
|
font-size: 10px;
|
|
letter-spacing: 0.08em;
|
|
text-transform: uppercase;
|
|
padding: 3px 7px;
|
|
border-radius: 3px;
|
|
background: rgba(43, 33, 24, 0.1);
|
|
border: 1px solid rgba(43, 33, 24, 0.16);
|
|
}
|
|
|
|
.chip.warn {
|
|
background: rgba(192, 57, 43, 0.14);
|
|
border-color: rgba(192, 57, 43, 0.4);
|
|
color: #8e2c21;
|
|
}
|
|
|
|
.chip.tool {
|
|
background: rgba(40, 80, 130, 0.12);
|
|
border-color: rgba(40, 80, 130, 0.3);
|
|
color: #2d5480;
|
|
}
|
|
|
|
.ticket-hint {
|
|
margin-top: 9px;
|
|
font-size: 11px;
|
|
color: #8a7963;
|
|
font-style: italic;
|
|
}
|
|
|
|
/* ---- the scorecard ---- */
|
|
.judge-panel {
|
|
position: absolute;
|
|
inset: 0;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: stretch;
|
|
pointer-events: none;
|
|
}
|
|
|
|
.judge-panel > * {
|
|
pointer-events: auto;
|
|
}
|
|
|
|
.judge-left {
|
|
width: 33%;
|
|
max-width: 400px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: flex-end;
|
|
padding: 0 0 26px 26px;
|
|
}
|
|
|
|
.judge-face {
|
|
width: 210px;
|
|
align-self: flex-start;
|
|
filter: drop-shadow(0 12px 26px rgba(0, 0, 0, 0.6));
|
|
}
|
|
|
|
.judge-lines {
|
|
margin-top: 8px;
|
|
max-width: 380px;
|
|
}
|
|
|
|
.judge-lines p {
|
|
font-size: 17px;
|
|
line-height: 1.42;
|
|
margin-bottom: 7px;
|
|
color: var(--ink);
|
|
text-shadow: 0 2px 12px rgba(0, 0, 0, 0.9);
|
|
}
|
|
|
|
.judge-lines p:first-child {
|
|
color: var(--ink-dim);
|
|
font-size: 14px;
|
|
}
|
|
|
|
.judge-right {
|
|
width: 380px;
|
|
padding: 26px 26px 26px 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
}
|
|
|
|
.judge-order {
|
|
font-size: 11px;
|
|
letter-spacing: 0.09em;
|
|
text-transform: uppercase;
|
|
color: var(--ink-dim);
|
|
margin-bottom: 12px;
|
|
text-align: right;
|
|
}
|
|
|
|
.judge-card {
|
|
background: rgba(12, 9, 8, 0.76);
|
|
border: 1px solid rgba(243, 233, 220, 0.14);
|
|
border-radius: 9px;
|
|
padding: 14px 16px;
|
|
backdrop-filter: blur(9px);
|
|
}
|
|
|
|
.crit {
|
|
display: grid;
|
|
grid-template-columns: 96px 1fr auto;
|
|
align-items: center;
|
|
gap: 10px;
|
|
padding: 4px 0;
|
|
}
|
|
|
|
/* Station headers on prep-order scorecards. */
|
|
.crit-group {
|
|
font-size: 9px;
|
|
letter-spacing: 0.22em;
|
|
opacity: 0.55;
|
|
margin: 8px 0 2px;
|
|
border-bottom: 1px solid rgba(255, 255, 255, 0.12);
|
|
padding-bottom: 3px;
|
|
}
|
|
|
|
.crit-name {
|
|
font-size: 10px;
|
|
letter-spacing: 0.1em;
|
|
text-transform: uppercase;
|
|
color: var(--ink-dim);
|
|
}
|
|
|
|
.crit-bar {
|
|
height: 6px;
|
|
border-radius: 3px;
|
|
background: rgba(255, 255, 255, 0.09);
|
|
overflow: hidden;
|
|
}
|
|
|
|
.crit-fill {
|
|
display: block;
|
|
height: 100%;
|
|
border-radius: 3px;
|
|
}
|
|
|
|
.crit-detail {
|
|
font-family: var(--mono);
|
|
font-size: 10px;
|
|
color: var(--ink-dim);
|
|
text-align: right;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.crit.total {
|
|
border-top: 1px solid rgba(243, 233, 220, 0.16);
|
|
margin-top: 7px;
|
|
padding-top: 9px;
|
|
}
|
|
|
|
.crit.total .crit-name,
|
|
.crit.total .crit-detail {
|
|
color: var(--gold);
|
|
font-size: 13px;
|
|
}
|
|
|
|
.judge-foot {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
margin-top: 16px;
|
|
}
|
|
|
|
.judge-stamp {
|
|
font-size: 56px;
|
|
font-weight: 800;
|
|
line-height: 1;
|
|
padding: 4px 18px;
|
|
border: 4px solid currentColor;
|
|
border-radius: 7px;
|
|
transform: rotate(-9deg);
|
|
animation: stamp 0.42s cubic-bezier(0.2, 1.7, 0.4, 1);
|
|
}
|
|
|
|
@keyframes stamp {
|
|
0% {
|
|
transform: rotate(-9deg) scale(3.2);
|
|
opacity: 0;
|
|
}
|
|
60% {
|
|
opacity: 1;
|
|
}
|
|
100% {
|
|
transform: rotate(-9deg) scale(1);
|
|
opacity: 1;
|
|
}
|
|
}
|
|
|
|
.grade-S { color: #ffd76a; }
|
|
.grade-A { color: #7fd07f; }
|
|
.grade-B { color: #cfc4b2; }
|
|
.grade-C { color: #d99a4e; }
|
|
.grade-F { color: #d0483a; }
|
|
|
|
.judge-btns {
|
|
display: flex;
|
|
gap: 8px;
|
|
}
|
|
|
|
.btn {
|
|
font-family: var(--font);
|
|
font-size: 11px;
|
|
letter-spacing: 0.13em;
|
|
padding: 10px 16px;
|
|
border-radius: 6px;
|
|
border: 1px solid var(--gold);
|
|
background: var(--gold);
|
|
color: #211a12;
|
|
cursor: pointer;
|
|
font-weight: 700;
|
|
}
|
|
|
|
.btn:hover {
|
|
filter: brightness(1.12);
|
|
}
|
|
|
|
.btn.ghost {
|
|
background: transparent;
|
|
color: var(--ink-dim);
|
|
border-color: rgba(243, 233, 220, 0.24);
|
|
font-weight: 500;
|
|
}
|
|
|
|
.btn.ghost:hover {
|
|
color: var(--ink);
|
|
}
|
|
|
|
/* ---- the drawer ---- */
|
|
/* Full-bleed and pass-through: the cutlery is dragged on the CANVAS beneath.
|
|
The `#ui > *` auto rule has ID specificity and would otherwise force this
|
|
invisible full-screen sheet to pointer-events:auto, swallowing every drag. */
|
|
#ui > .drawer-panel {
|
|
position: absolute;
|
|
inset: 0;
|
|
pointer-events: none;
|
|
}
|
|
/* The info card is the only thing here that could want clicks — it doesn't. */
|
|
|
|
.drawer-card {
|
|
position: absolute;
|
|
top: 26px;
|
|
left: 26px;
|
|
width: 168px;
|
|
padding: 14px 14px 12px;
|
|
background: rgba(12, 9, 8, 0.78);
|
|
border: 1px solid rgba(243, 233, 220, 0.16);
|
|
border-radius: 9px;
|
|
backdrop-filter: blur(9px);
|
|
text-align: center;
|
|
}
|
|
|
|
.drawer-lbl {
|
|
font-size: 10px;
|
|
letter-spacing: 0.22em;
|
|
color: var(--ink-dim);
|
|
}
|
|
|
|
.drawer-sil {
|
|
color: var(--gold);
|
|
margin: 6px 0 2px;
|
|
}
|
|
|
|
.drawer-sil .sil {
|
|
display: block;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
.sil-name {
|
|
font-size: 13px;
|
|
letter-spacing: 0.05em;
|
|
color: var(--ink);
|
|
margin-top: 2px;
|
|
}
|
|
|
|
/* The pity reveal: the answer arriving like a sigh, ten seconds in. */
|
|
.sil-name.revealed {
|
|
font-size: 12px;
|
|
font-style: italic;
|
|
color: var(--ink-dim);
|
|
animation: sigh 1.6s ease-out;
|
|
}
|
|
|
|
@keyframes sigh {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateY(3px);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: none;
|
|
}
|
|
}
|
|
|
|
.drawer-timer {
|
|
margin-top: 12px;
|
|
}
|
|
|
|
.timer-bar {
|
|
height: 5px;
|
|
border-radius: 3px;
|
|
background: rgba(255, 255, 255, 0.1);
|
|
overflow: hidden;
|
|
}
|
|
|
|
.timer-fill {
|
|
height: 100%;
|
|
width: 100%;
|
|
border-radius: 3px;
|
|
transition: width 0.2s linear;
|
|
}
|
|
|
|
.timer-lbl {
|
|
margin-top: 5px;
|
|
font-size: 10px;
|
|
font-style: italic;
|
|
color: var(--ink-dim);
|
|
}
|
|
|
|
.drawer-hint {
|
|
position: absolute;
|
|
bottom: 26px;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
font-size: 11px;
|
|
letter-spacing: 0.1em;
|
|
color: var(--ink-dim);
|
|
text-shadow: 0 2px 10px #000;
|
|
}
|
|
|
|
/* ---- title ---- */
|
|
.title {
|
|
position: absolute;
|
|
inset: 0;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
background: radial-gradient(ellipse at 50% 45%, #241a15 0%, #0d0a08 75%);
|
|
}
|
|
|
|
.title-wrap {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 40px;
|
|
max-width: 900px;
|
|
padding: 24px;
|
|
}
|
|
|
|
.title-art {
|
|
width: 380px;
|
|
max-width: 44vw;
|
|
border-radius: 12px;
|
|
filter: drop-shadow(0 20px 44px rgba(0, 0, 0, 0.7));
|
|
}
|
|
|
|
.title-txt h1 {
|
|
font-size: 62px;
|
|
letter-spacing: 0.05em;
|
|
line-height: 1;
|
|
color: var(--paper);
|
|
}
|
|
|
|
.title-sub {
|
|
margin: 10px 0 26px;
|
|
font-size: 16px;
|
|
font-style: italic;
|
|
color: var(--ink-dim);
|
|
}
|
|
|
|
.title-keys {
|
|
margin-top: 26px;
|
|
font-size: 11px;
|
|
line-height: 1.9;
|
|
letter-spacing: 0.08em;
|
|
color: #6d6155;
|
|
}
|
|
|
|
/* The day ledger: replay any reached day, best grade stamped on the chip. */
|
|
.title-days-lbl {
|
|
margin-top: 20px;
|
|
font-size: 10px;
|
|
letter-spacing: 0.22em;
|
|
color: var(--ink-dim);
|
|
}
|
|
|
|
.title-days {
|
|
margin-top: 8px;
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 5px;
|
|
max-width: 380px;
|
|
max-height: 118px;
|
|
overflow-y: auto;
|
|
}
|
|
|
|
.day-chip {
|
|
width: 34px;
|
|
padding: 4px 0 3px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: 1px;
|
|
background: rgba(243, 233, 220, 0.06);
|
|
border: 1px solid rgba(243, 233, 220, 0.14);
|
|
border-radius: 6px;
|
|
color: var(--ink);
|
|
cursor: pointer;
|
|
font-family: var(--mono);
|
|
}
|
|
|
|
.day-chip:hover {
|
|
background: rgba(232, 165, 58, 0.18);
|
|
border-color: rgba(232, 165, 58, 0.5);
|
|
}
|
|
|
|
.day-num {
|
|
font-size: 11px;
|
|
}
|
|
|
|
.day-grade {
|
|
font-size: 10px;
|
|
color: var(--ink-dim);
|
|
}
|
|
|
|
.day-grade.grade-S {
|
|
color: #6cbf6c;
|
|
font-weight: 700;
|
|
}
|
|
|
|
.day-grade.grade-A {
|
|
color: #8fce8f;
|
|
}
|
|
|
|
.day-grade.grade-B {
|
|
color: #e8a53a;
|
|
}
|
|
|
|
.day-grade.grade-C {
|
|
color: #d2703a;
|
|
}
|
|
|
|
.day-grade.grade-F {
|
|
color: #c0392b;
|
|
}
|
|
|
|
.toast-panel .amount {
|
|
margin-top: 8px;
|
|
font-size: 11px;
|
|
letter-spacing: 0.06em;
|
|
color: var(--ink-dim);
|
|
min-height: 14px;
|
|
font-family: var(--mono);
|
|
}
|
|
|
|
.toast-panel .sel:disabled,
|
|
.toast-panel .dial:disabled {
|
|
opacity: 0.55;
|
|
}
|
|
|
|
/* ---- the slicing bench ---- */
|
|
.slicer-card {
|
|
position: absolute;
|
|
top: 26px;
|
|
left: 26px;
|
|
width: 220px;
|
|
padding: 16px 18px;
|
|
background: rgba(12, 9, 8, 0.78);
|
|
border: 1px solid rgba(243, 233, 220, 0.14);
|
|
border-radius: 10px;
|
|
backdrop-filter: blur(9px);
|
|
}
|
|
|
|
.slicer-ask {
|
|
font-size: 14px;
|
|
color: var(--gold);
|
|
margin: 6px 0 2px;
|
|
}
|
|
|
|
.slicer-thick {
|
|
font-family: var(--mono);
|
|
font-size: 12px;
|
|
color: var(--ink);
|
|
margin: 8px 0 6px;
|
|
}
|
|
|
|
.slicer-wobble {
|
|
margin-top: 8px;
|
|
font-size: 11px;
|
|
letter-spacing: 0.08em;
|
|
color: var(--ink-dim);
|
|
min-height: 14px;
|
|
transition: color 0.3s;
|
|
}
|
|
|
|
.chip.brand {
|
|
background: rgba(120, 82, 30, 0.16);
|
|
border-color: rgba(120, 82, 30, 0.4);
|
|
color: #6d4a1c;
|
|
font-weight: 700;
|
|
}
|