/* The desk, as the Work of owenfisher.co (version G, built on E by tools/build-g.py). Real bits of interface from Owen's work,
   laid on a designer's desk to pick up, look at and push around. Every piece moves on springs, its shadow grows with its
   height, and no two pieces ever share a layer. The page arrives being built: a crew of cursors draws each frame, types the
   words and puts the pieces down, a little messily. Tidy up brings the crew back to line everything up on the grid.

   E's frame (the corners, the nav, the glass chat) is E's own; this file only adds the desk and the studio above it. Its
   tokens live on the desk and the studio, never on :root, so About and Working together look exactly as they did. */

.desk-app, .studio {
  --line: rgb(27 26 24 / .1); --pencil-soft: oklch(55% 0.19 29 / .09); --sel: #2b7fff; --veil: .86;
  --t-title: clamp(1.15rem, 0.95rem + 0.55vw, 1.45rem); --t-small: 0.875rem;
  --cap-w: clamp(12.5rem, 16vw, 17.5rem);
  --d-cols: 10; --d-ease: cubic-bezier(.2, .8, .2, 1);
}
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) :is(.desk-app, .studio) { --line: rgb(231 230 227 / .12); --pencil-soft: oklch(70% 0.17 31 / .11); --sel: #5aa2ff; --veil: .93; } }
:root[data-theme="dark"] :is(.desk-app, .studio) { --line: rgb(231 230 227 / .12); --pencil-soft: oklch(70% 0.17 31 / .11); --sel: #5aa2ff; --veil: .93; }
.desk-app button, .studio button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
.desk-app button:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; border-radius: 6px; }

/* While the desk is the Work, E's frame is pinned to the screen and the desk scrolls under it: clicks pass through the frame
   to the desk, except on its links and buttons. Its status line steps aside for Tidy up. */
html.desk-on .app { position: fixed; inset: 0; z-index: 2; pointer-events: none; }
html.desk-on .app a, html.desk-on .app button, html.desk-on .app .seg { pointer-events: auto; }
html.desk-on .app .corner.bl { visibility: hidden; }
/* below 960px E's frame flows down the page; pinned, its foot is held at the bottom of the screen instead */
@media (width < 960px) {
  html.desk-on .app .br { position: fixed; right: var(--frame-x); bottom: calc(var(--frame-y) + env(safe-area-inset-bottom, 0px)); padding: 0; }
}
@media (width < 600px) {
  html.desk-on .app .br .address { display: none; }   /* on a phone the foot holds Tidy up, the chat and an envelope: the address is in About */
  html.desk-on .app .br > :has(#copy), html.desk-on .app .br > #copy { display: none !important; }   /* !important: E's metal ring sets its wrapper's display inline */   /* "Copy" alone would not say what it copies */
  html.desk-on .app .br .mail-btn { display: inline-flex; }
}
/* the envelope: on a phone, in place of Copy, it opens the visitor's mail app addressed to Owen; it matches Tidy up across the foot */
.mail-btn { display: none; width: var(--ctl); height: var(--ctl); border-radius: 999px; align-items: center; justify-content: center; background: var(--ink); color: var(--paper);
  box-shadow: 0 12px 30px -14px rgb(0 0 0 / .5); -webkit-tap-highlight-color: transparent; transition: transform 180ms var(--d-ease, ease); }
.mail-btn svg { width: 1rem; height: 1rem; }
.mail-btn:active { transform: scale(.96); }
.mail-btn:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
.desk-app { position: relative; z-index: 1; transition: opacity 280ms var(--d-ease); }
.desk-app.away { opacity: 0; }

/* Tidy up: always there, since the desk starts messy; it sends the crew in to put everything back on the grid */
.tidy { position: fixed; z-index: 500; left: var(--frame-x); bottom: var(--frame-y); display: inline-flex; align-items: center; gap: 0.5rem; padding: 0.5rem 1.05rem 0.5rem 0.85rem; border-radius: 999px;
  background: var(--ink); color: var(--paper); font-size: var(--t-small); white-space: nowrap; box-shadow: 0 12px 30px -14px rgb(0 0 0 / .5); transition: transform 180ms var(--d-ease), background-color 200ms var(--d-ease), color 200ms var(--d-ease); }
.desk-app .tidy { height: var(--ctl); background: var(--ink); color: var(--paper); padding: 0 calc(var(--bl-h) + 2px) 0 var(--bl-h); font-size: var(--step-n1); font-weight: 400; line-height: 1; }   /* the frame's control size and words (E's --ctl); .desk-app button resets font and padding, this puts them back */
.tidy svg { width: 1rem; height: 1rem; }
.tidy:active { transform: scale(.96); }
.desk-app .tidy[aria-pressed="true"] { background: var(--surface); color: var(--ink); box-shadow: 0 0 0 1px var(--line), 0 12px 30px -16px rgb(0 0 0 / .4); }

/* the words about a piece that has been picked up, either side of it */
.cap { position: fixed; z-index: 450; top: 50%; transform: translateY(-50%); width: var(--cap-w); display: grid; gap: 0.35rem; transition: opacity 300ms var(--d-ease); }
.cap-l { left: var(--frame-x); }
.cap-r { right: var(--frame-x); text-align: right; justify-items: end; }
.cap .nm { font-weight: 500; }
.cap .dt { color: var(--secondary); font-size: var(--t-small); line-height: 1.5; text-wrap: pretty; }
.cap .ct { color: var(--grey); font-size: var(--t-small); font-variant-numeric: tabular-nums; }
.cap .arrows { display: flex; gap: 0.35rem; margin-top: 0.5rem; }
.desk-app .cap .arrows button, .desk-app .chip { height: 2.25rem; min-width: 2.25rem; border-radius: 999px; display: inline-grid; place-items: center; background: var(--tint); }
.desk-app .chip { justify-self: start; padding: 0 0.95rem; font-size: var(--t-small); margin-bottom: 0.6rem; }
.cap svg { width: 0.95rem; height: 0.95rem; }

/* as the desk scrolls under them, the corners keep a soft edge of desk colour behind them, so the words never sit on the work */
.edge { position: fixed; left: 0; right: 0; z-index: 400; height: calc(var(--frame-y) * 2 + 3.4rem); background: var(--canvas); pointer-events: none; opacity: 0;
  transition: opacity 260ms var(--d-ease), background-color 800ms var(--d-ease); }
.edge.top { top: 0; height: var(--d-head, calc(var(--frame-y) * 2 + 3.4rem)); -webkit-mask-image: linear-gradient(#000 55%, transparent); mask-image: linear-gradient(#000 55%, transparent); }
.edge.bottom { bottom: 0; height: var(--d-foot, calc(var(--frame-y) * 2 + 3.4rem)); -webkit-mask-image: linear-gradient(transparent, #000 45%); mask-image: linear-gradient(transparent, #000 45%); }
.edge.on { opacity: 1; }

/* the desk is as tall as the work needs: the page scrolls, the frame stays put */
#desk { position: absolute; left: 0; top: 0; width: 100%; height: 100vh; z-index: 0; overflow: hidden; touch-action: pan-y; }
.bit { position: absolute; left: 0; top: 0; transform-origin: 50% 50%; display: block; padding: 0; border: 0; background: none; cursor: grab; touch-action: none; -webkit-tap-highlight-color: transparent; transition: opacity 320ms var(--d-ease); }
.desk-app.scrolls .bit { touch-action: pan-y; }   /* where the page scrolls, a swipe up or down over a piece scrolls it; sideways picks the piece up */
.bit.moving { will-change: transform; }
.bit img { position: absolute; inset: 0; display: block; width: 100%; height: 100%; pointer-events: none; user-select: none; -webkit-user-select: none; -webkit-user-drag: none; }
/* the lift shadow: the piece's own silhouette, blurred once, then only moved and faded as the piece rises */
.bit .sh { opacity: 0; transform-origin: 50% 50%; will-change: transform, opacity; }
.bit:active { cursor: grabbing; }
.bit:focus-visible { outline: none; }
.bit:focus-visible img:last-child { outline: calc(2px / var(--k, .3)) solid var(--ink); outline-offset: -30px; border-radius: 20px; }
/* while a piece is lifted, everything under it sits behind one veil the colour of the desk, deepest where the words sit */
.veil { position: fixed; inset: 0; z-index: 8000000; background: var(--canvas); opacity: 0; pointer-events: none; transition: opacity 360ms var(--d-ease), background-color 800ms var(--d-ease);
  -webkit-mask-image: linear-gradient(90deg, #000 0 21%, rgb(0 0 0 / var(--veil, .86)) 31% 69%, #000 79%); mask-image: linear-gradient(90deg, #000 0 21%, rgb(0 0 0 / var(--veil, .86)) 31% 69%, #000 79%); }
.veil.on { opacity: 1; }
@media (width < 700px) { .veil { -webkit-mask-image: linear-gradient(180deg, #000 0 30%, rgb(0 0 0 / var(--veil, .86)) 42%); mask-image: linear-gradient(180deg, #000 0 30%, rgb(0 0 0 / var(--veil, .86)) 42%); } }

/* ---- the studio: the grid, rulers, selections, guides, measurements and the crew's cursors ---- */
.ov { position: fixed; inset: 0; z-index: 420; pointer-events: none; }
.ov-grid { display: grid; grid-template-columns: repeat(var(--d-cols), 1fr); column-gap: var(--g-gap); padding: 0 var(--frame-x); }
.ov-grid i { border-inline: 1px solid color-mix(in oklab, var(--sel) 34%, transparent); background: color-mix(in oklab, var(--sel) 4%, transparent); transform: scaleY(0); transform-origin: 50% 0; }
.ov-grid b { position: fixed; top: 0; bottom: 0; width: 1px; background: var(--pencil); transform: scaleY(0); transform-origin: 50% 0; }
.ov-grid b.l { left: var(--frame-x); }
.ov-grid b.r { right: var(--frame-x); }
.ov-grid.on i, .ov-grid.on b { transform: scaleY(1); transition: transform 760ms cubic-bezier(.16, 1, .3, 1); }
.ov-grid:not(.on) i, .ov-grid:not(.on) b { transition: transform 280ms var(--d-ease); transform-origin: 50% 100%; }
.ov-note { position: fixed; z-index: 530; left: 50%; bottom: calc(var(--frame-y) + 4rem); transform: translate(-50%, 6px); padding: 0.25rem 0.75rem; border-radius: 999px; background: var(--ink); color: var(--paper);
  font-size: var(--t-small); font-variant-numeric: tabular-nums; white-space: nowrap; opacity: 0; transition: opacity 200ms var(--d-ease), transform 200ms var(--d-ease); pointer-events: none; }
.ov-note.on { opacity: 1; transform: translate(-50%, 0); }
.studio { position: fixed; inset: 0; z-index: 30; pointer-events: none; }   /* above the frame and the chat, never in the way */
.ruler { position: absolute; top: 0; left: 0; display: block; opacity: 0; transition: transform 600ms cubic-bezier(.2, .9, .2, 1), opacity 240ms var(--d-ease); }
#rulerX { transform: translateY(-100%); }
#rulerY { transform: translateX(-100%); }
.studio.rulers #rulerX, .studio.rulers #rulerY { opacity: 1; transform: none; }
.guides { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.guides .g { stroke: var(--sel); stroke-width: 1; stroke-dasharray: 2 3; opacity: .75; }
.guides .m { stroke: var(--pencil); stroke-width: 1; }
.guides .m.snap { stroke-width: 2; }
.guides .tz { fill: none; stroke: var(--sel); stroke-width: 1; stroke-dasharray: 3 3; opacity: .55; }
.guides .pad { fill: rgb(34 160 107 / .26); }
.guides .pt { fill: #137a50; font: 700 9px var(--sans); }
.guides rect { fill: var(--pencil); }
.guides text { fill: #fff; font: 600 11px var(--sans); font-variant-numeric: tabular-nums; }
.sel { position: absolute; left: 0; top: 0; box-sizing: border-box; border: 1px solid var(--c, var(--sel)); opacity: 0; transition: opacity 160ms var(--d-ease); }
.sel.on { opacity: 1; }
.sel.marquee { background: color-mix(in oklab, var(--c, var(--sel)) 9%, transparent); }
.sel.marquee i { display: none; }
.sel i { position: absolute; width: 7px; height: 7px; box-sizing: border-box; background: #fff; border: 1px solid var(--c, var(--sel)); }
.sel i:nth-child(1) { left: -4px; top: -4px; } .sel i:nth-child(2) { right: -4px; top: -4px; } .sel i:nth-child(3) { left: -4px; bottom: -4px; } .sel i:nth-child(4) { right: -4px; bottom: -4px; }
.size { position: absolute; left: 0; top: 0; padding: 0 6px; border-radius: 4px; background: var(--c, var(--sel)); color: #fff; font: 600 11px/17px var(--sans); font-variant-numeric: tabular-nums; white-space: nowrap; opacity: 0; transition: opacity 160ms var(--d-ease); }
.size.on { opacity: 1; }
.cursor { position: absolute; left: 0; top: 0; width: 100px; height: 40px; opacity: 0; transition: opacity 260ms var(--d-ease); filter: drop-shadow(0 1px 1.5px rgb(0 0 0 / .25)); will-change: transform; pointer-events: none; }
/* a real box round the arrow and its name, on a layer of its own: a box of no size with a drop shadow left trails of the
   shadow behind it in Safari as it moved (seen on an iPhone, 15 Oct 2026) */
.cursor.on { opacity: 1; }
.cursor svg { position: absolute; display: none; }
.cursor.arrow .c-arrow, .cursor.cross .c-cross, .cursor.beam .c-beam, .cursor.resize .c-resize { display: block; }
.cursor .f { fill: var(--c, var(--sel)); }
.cursor .k { stroke: var(--c, var(--sel)); }
#sel, #size, #ghost { display: none; }
.cursor .c-arrow { left: -1px; top: -1px; } .cursor .c-cross, .cursor .c-beam, .cursor .c-resize { left: -9px; top: -9px; }
.cursor b { position: absolute; left: 13px; top: 17px; padding: 0 7px; border-radius: 999px; background: var(--c, var(--sel)); color: #fff; font: 600 11px/18px var(--sans); white-space: nowrap; }
.caret { position: absolute; left: 0; top: 0; width: 2px; border-radius: 1px; background: var(--sel); opacity: 0; }
.caret.on { opacity: 1; animation: blink 1s steps(1) infinite; }
@keyframes blink { 50% { opacity: 0; } }

/* the intro: until the crew has drawn a thing, it is not there (decided before first paint, see the head) */
html.desk-intro .unbuilt { opacity: 0 !important; }

@media (width < 700px) {
  .cap { top: var(--d-top, 72px); transform: none; width: auto; left: var(--frame-x); right: var(--frame-x); }
  .cap-r { display: none; }
}
@media (width < 600px) {   /* Tidy up as a round button, so it, the chat and Copy share the foot */
  .desk-app .tidy { width: var(--ctl); height: var(--ctl); padding: 0; justify-content: center; }
  .tidy span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
}
