/* The 3D scene is an entrance. The terminal remains normal, accessible HTML. */
#scene-shell{position:fixed;inset:0;z-index:2;display:none;color:#d3dace;
  background:radial-gradient(ellipse at 53% 45%,#17211c 0%,#090e0b 48%,#050706 100%)}
body.scene-loading #scene-shell,body.scene-3d #scene-shell{display:block}
#scene-canvas{position:absolute;inset:0;width:100%;height:100%;touch-action:none;outline:0}
.scene-vignette{position:absolute;inset:0;pointer-events:none;
  background:radial-gradient(ellipse at 53% 48%,transparent 30%,rgba(0,0,0,.2) 69%,rgba(0,0,0,.58) 100%)}
.scene-grain{position:absolute;inset:0;pointer-events:none;opacity:.035;
  background-image:url("data:image/svg+xml,%3Csvg viewBox='0 0 180 180' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.91' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' opacity='.7' filter='url(%23n)'/%3E%3C/svg%3E")}
.scene-header{position:absolute;top:36px;left:42px;right:42px;display:flex;align-items:flex-start;justify-content:space-between;pointer-events:none}
.scene-brand{font-size:15px;font-weight:700;letter-spacing:.3em;color:#e3e8dc;display:flex;gap:12px;align-items:center}
.scene-brand::before{content:"";width:12px;height:12px;border:2px solid #a2d8a7;box-shadow:inset 0 0 0 2px #060c08;transform:rotate(45deg)}
.scene-edition{margin-top:9px;margin-left:26px;font-size:8px;letter-spacing:.23em;color:#667b6d}
.scene-status{text-align:right;font-size:9px;line-height:1.8;letter-spacing:.18em;color:#76897b}
.scene-status b{font-weight:400;color:#b5c7b4}
.scene-status i{display:inline-block;width:5px;height:5px;background:#a6d29a;border-radius:50%;margin-right:7px;box-shadow:0 0 9px #91e19b}
.scene-caption{position:absolute;left:42px;top:45%;pointer-events:none}
.scene-caption .sc-index{font-size:9px;letter-spacing:.2em;color:#516456;margin-bottom:21px}
.scene-caption p{font-size:10px;letter-spacing:.2em;line-height:2.15;color:#8b9d8d}
.scene-caption p strong{color:#d1dccb;font-weight:400}
.scene-caption .sc-line{width:30px;height:1px;background:#415e49;margin:20px 0}
.scene-caption small{font-size:8px;letter-spacing:.14em;color:#516456;line-height:1.9;display:block}
.scene-side{position:absolute;right:42px;top:43%;writing-mode:vertical-rl;font-size:8px;letter-spacing:.35em;color:#54665a;pointer-events:none}
.scene-footer{position:absolute;bottom:34px;left:42px;right:42px;display:flex;align-items:flex-end;justify-content:space-between;gap:24px}
.scene-stats{display:flex;gap:35px;align-items:flex-end}
.scene-stat b{display:block;font-size:26px;font-weight:400;letter-spacing:-.06em;color:#dbe4d4}
.scene-stat span{display:block;margin-top:8px;font-size:8px;letter-spacing:.19em;color:#718576}
.scene-stat+.scene-stat{border-left:1px solid #293a2e;padding-left:30px}
.scene-actions{text-align:right}
#scene-enter{min-height:48px;padding:0 25px;font-size:10px;font-weight:700;letter-spacing:.16em;background:#b8dba7;color:#102113;border:1px solid #c4e7b3;
  box-shadow:0 0 30px rgba(153,203,130,.08);transition:background .18s,box-shadow .18s,transform .18s}
#scene-enter:hover{background:#d1ecc3;box-shadow:0 0 35px rgba(153,203,130,.15);transform:translateY(-2px)}
#scene-enter span{padding-left:25px;font-size:16px}
.scene-hint{font-size:8px;letter-spacing:.14em;color:#6b7e6e;margin-top:13px}
#scene-reset{position:absolute;left:50%;bottom:41px;transform:translateX(-50%);font-size:9px;letter-spacing:.15em;color:#8a9d8c;padding:10px 14px;border:1px solid #293d2f;background:rgba(4,9,6,.5)}
#scene-reset:hover{color:#d7e8d2;border-color:#63816a}
#scene-loader{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:220px;text-align:center;pointer-events:none}
#scene-loader span{font-size:9px;letter-spacing:.22em;color:#93ab95}
.scene-loading-track{height:1px;background:#203b29;margin-top:17px}
#scene-loading-fill{display:block;height:1px;width:0;background:#a6d19d;transition:width .2s}
/* Before the model starts arriving there is nothing to measure: three.js is
   two megabytes of module and a dynamic import reports no progress. A bar
   pinned at zero for three seconds reads as broken, so say "working" until
   there are real bytes to count, then switch to counting them. */
.scene-loading-track.is-waiting #scene-loading-fill{width:30%;transition:none;
  animation:scene-sweep 1.25s cubic-bezier(.5,0,.5,1) infinite}
@keyframes scene-sweep{from{transform:translateX(-105%)}to{transform:translateX(335%)}}
@media(prefers-reduced-motion:reduce){
  .scene-loading-track.is-waiting #scene-loading-fill{width:100%;opacity:.35;animation:none}
}
body.scene-3d #scene-loader{display:none}
/* The same white the welcome card starts on, so the frame the canvas hands
   over on and the first DOM frame are the same colour. */
.scene-flash{position:absolute;inset:0;background:#d9ffe6;opacity:var(--scene-flash,0);pointer-events:none;z-index:4}
.scene-header,.scene-caption,.scene-side,.scene-footer,#scene-reset{transition:opacity .4s,transform .4s}
body.scene-entering .scene-header,body.scene-entering .scene-caption,body.scene-entering .scene-side,
body.scene-entering .scene-footer,body.scene-entering #scene-reset{opacity:0;pointer-events:none}
body.scene-3d[data-cam="full"] #scene-shell,body.scene-loading[data-cam="full"] #scene-shell{display:none}
body.scene-loading #scene,body.scene-3d #scene{display:none}
body.scene-loading[data-cam="desk"] #os,body.scene-3d[data-cam="desk"] #os,
body.scene-loading #glasshit,body.scene-3d #glasshit{visibility:hidden;pointer-events:none}
body.scene-3d #stage,body.scene-loading #stage{z-index:3;pointer-events:none}
body.scene-3d[data-cam="full"] #os,body.scene-loading[data-cam="full"] #os{pointer-events:auto}
/* No arrival animation here. os.js runs the same gsnap the video entrance
   has always ended on, on #os, and a brightness ramp on #desktop underneath
   it only smears the snap it is sitting inside. */
body.scene-3d #back{font-size:8px;letter-spacing:.08em}
@media(max-width:1150px){.scene-caption{display:none}.scene-side{display:none}.scene-header{top:26px;left:28px;right:28px}.scene-footer{left:28px;right:28px;bottom:25px}.scene-stat b{font-size:22px}.scene-stats{gap:22px}.scene-stat+.scene-stat{padding-left:22px}}
@media(max-width:880px),(max-aspect-ratio:1/1){#scene-shell{display:none!important}}
@media(prefers-reduced-motion:reduce){.scene-header,.scene-caption,.scene-side,.scene-footer,#scene-reset,#scene-enter{transition:none}body.scene-3d[data-cam="full"] #desktop{animation:none}}

/* ---- the reveal ----
   The overlay is in the markup from first paint so nothing arrives late and
   shifts the layout, but it stays out of the way until the monitor is on.
   Each block is offset a little further than the last, which reads as the
   room coming up rather than as five things appearing at once. */
#scene-shell .scene-header,#scene-shell .scene-caption,#scene-shell .scene-side,
#scene-shell .scene-footer,#scene-shell #scene-reset{opacity:0;transform:translateY(6px)}
#scene-shell.is-live .scene-header,#scene-shell.is-live .scene-caption,
#scene-shell.is-live .scene-side,#scene-shell.is-live .scene-footer,
#scene-shell.is-live #scene-reset{opacity:1;transform:none;
  transition:opacity .7s cubic-bezier(.2,.7,.3,1),transform .7s cubic-bezier(.2,.7,.3,1)}
#scene-shell.is-live .scene-header{transition-delay:.05s}
#scene-shell.is-live .scene-caption{transition-delay:.20s}
#scene-shell.is-live .scene-side{transition-delay:.30s}
#scene-shell.is-live .scene-footer{transition-delay:.26s}
#scene-shell.is-live #scene-reset{transition-delay:.42s}
/* The entering push-in overrides all of it: that rule must win over these. */
body.scene-entering #scene-shell.is-live .scene-header,
body.scene-entering #scene-shell.is-live .scene-caption,
body.scene-entering #scene-shell.is-live .scene-side,
body.scene-entering #scene-shell.is-live .scene-footer,
body.scene-entering #scene-shell.is-live #scene-reset{opacity:0;transition-delay:0s}

/* The canvas is a control: it takes focus and it shows it. */
#scene-canvas:focus-visible{outline:1px solid #a6d29a;outline-offset:-3px}
#scene-enter:focus-visible,#scene-reset:focus-visible{outline:1px solid #cdeec0;outline-offset:2px}

/* The status column is three short rows, not a paragraph. */
.scene-status div+div{margin-top:2px}
.scene-status div:nth-child(2){color:#5d7263;letter-spacing:.2em}
.scene-brand,.scene-status,.scene-caption p,.scene-stat b{text-shadow:0 0 18px rgba(0,0,0,.65)}

@media(prefers-reduced-motion:reduce){
  #scene-shell .scene-header,#scene-shell .scene-caption,#scene-shell .scene-side,
  #scene-shell .scene-footer,#scene-shell #scene-reset{opacity:1;transform:none;transition:none}
}

/* ---- very wide displays ----
   Every size above is in px, which is right: this chrome is a fixed frame
   around a rendered object, not a text column, and it should not grow with
   the browser's font setting. But a 9px label with a 42px inset is lost on
   a 2560px display — the frame stops reading as a frame and becomes four
   specks in the corners. One step up, once, at the width where that starts. */
@media(min-width:1900px){
  .scene-header{top:48px;left:60px;right:60px}
  .scene-footer{bottom:46px;left:60px;right:60px}
  .scene-caption{left:60px}
  .scene-side{right:56px;font-size:10px}
  .scene-brand{font-size:19px}
  .scene-brand::before{width:15px;height:15px}
  .scene-edition{font-size:10px;margin-left:32px}
  .scene-status{font-size:11px}
  .scene-caption .sc-index{font-size:11px}
  .scene-caption p{font-size:13px;line-height:2.1}
  .scene-caption small{font-size:10px}
  .scene-stat b{font-size:34px}
  .scene-stat span{font-size:10px}
  .scene-stats{gap:44px}
  .scene-stat+.scene-stat{padding-left:38px}
  #scene-enter{font-size:12px;padding:0 32px;min-height:56px}
  #scene-enter span{font-size:19px}
  .scene-hint{font-size:10px}
  #scene-reset{font-size:11px;bottom:52px}
  #scene-loader{width:280px}
  #scene-loader span{font-size:11px}
}

/* Stage entrance: skip stays available from first paint through handoff. */
#scene-skip{position:absolute;right:36px;top:32px;z-index:5;padding:12px 16px;
  border:1px solid #657369;background:#101812e8;color:#d8e0cd;font-size:10px;letter-spacing:.15em;
  transition:border-color .16s,background .16s,color .16s}
#scene-skip:hover{border-color:#c0d2b3;background:#263327}
#scene-sequence{position:absolute;bottom:54px;left:50%;transform:translateX(-50%);
  color:#b7c5ad;font-size:10px;letter-spacing:.27em;pointer-events:none;white-space:nowrap}
#scene-skip[hidden],#scene-sequence[hidden],.scene-file[hidden]{display:none}
.scene-file{position:absolute;transform:translate(-50%,0);font-size:8px;letter-spacing:.1em;
  padding:8px 9px;background:#0a110dea;border:1px solid #42513e;color:#c5d3b8;white-space:nowrap;
  transition:color .16s,border-color .16s,background .16s}
.scene-file:hover,.scene-file:focus-visible{color:#f1ffdf;background:#213425;border-color:#c1dfab}
body.scene-entering .scene-file{visibility:hidden}
#scene-shell .scene-caption{top:24%;opacity:0;display:none}
.scene-view-controls{position:absolute;bottom:37px;left:50%;transform:translateX(-50%);
  display:flex;gap:10px;opacity:0;pointer-events:none;transition:opacity .3s}
#scene-shell.is-live .scene-view-controls{opacity:1;pointer-events:auto}
.scene-view-controls #scene-reset,.scene-view-controls #scene-replay,.scene-view-controls #scene-guide{position:static;transform:none;
  font-size:9px;letter-spacing:.12em;color:#8a9d8c;padding:10px 12px;border:1px solid #293d2f;background:#040906a6;
  transition:color .16s,border-color .16s,background .16s}
.scene-view-controls #scene-reset:hover,.scene-view-controls #scene-replay:hover,.scene-view-controls #scene-guide:hover{background:#0c150fd9}
.scene-view-controls #scene-replay:hover,.scene-view-controls #scene-guide:hover{color:#d7e8d2;border-color:#63816a}
body.scene-entering #scene-shell .scene-view-controls{opacity:0;pointer-events:none}
body.scene-3d.glitch #os{animation:stage-arrival .22s ease-out}
@keyframes stage-arrival{from{opacity:.7;transform:scale(1.015)}to{opacity:1;transform:none}}

/* ---- Archive cards ----
   These were cream paper on a wooden shelf: a second visual language sitting
   on top of a site that is otherwise one phosphor tube. They are now the same
   object the terminal's windows are — chiselled bevel, striped active bar,
   raster raking across the text rather than text floating over it — so opening
   a file reads as the machine displaying it rather than as a document pasted
   over the room.

   They are still the native <dialog>, so focus handling, Escape and the
   backdrop remain the platform's rather than ours. */
dialog#archive-card{width:min(860px,calc(100vw - 48px))}
#archive-card,#auth-card,#guide-card{--card-ground:#030d07;--card-ink:var(--grn);--card-muted:var(--label);
  --card-rule:var(--line);--card-rule-2:var(--line-2);
  margin:auto;padding:0;width:min(780px,calc(100vw - 48px));max-width:none;
  max-height:calc(100dvh - 64px);
  color:var(--card-ink);background:var(--card-ground);border:0;border-radius:4px;
  box-shadow:
    inset 1px 1px 0 rgba(93,255,143,.5),
    inset -1px -1px 0 rgba(0,22,10,.95),
    inset 2px 2px 0 rgba(93,255,143,.16),
    inset -2px -2px 0 rgba(0,40,18,.8),
    0 28px 90px rgba(0,0,0,.72),
    0 0 70px rgba(93,255,143,.07);
  overflow:hidden;font-family:"JetBrains Mono",ui-monospace,monospace}
#archive-card[open],#auth-card[open],#guide-card[open]{display:flex;flex-direction:column;
  animation:card-on 420ms cubic-bezier(.16,1,.3,1)}
#archive-card::backdrop,#auth-card::backdrop,#guide-card::backdrop{background:rgba(1,4,2,.82);backdrop-filter:blur(3px)}
/* The tube opening on the file: a struck line that unfolds into the card,
   with the beam still washing across it as the content arrives.

   clip-path, not transform — the same reason the windows use it. A scale
   animation drags every control on the card around under the pointer for
   the length of the reveal, so a click aimed at an FAQ row lands wherever
   that row has travelled to by the time the press is dispatched. Clipping
   emits the card progressively instead of moving it: every row is at its
   real coordinates on the first frame, and it reads more like a tube
   anyway, which does not stretch the picture as it opens. */
@keyframes card-on{
  0%{clip-path:inset(49.8% 0);opacity:.9}
  30%{clip-path:inset(49.3% 0);opacity:1}
  100%{clip-path:inset(0 0);opacity:1}
}
#archive-card::before,#auth-card::before,#guide-card::before{content:"";position:absolute;inset:0;z-index:6;pointer-events:none;opacity:0;
  background:linear-gradient(to bottom,transparent 34%,rgba(170,255,208,.55) 49%,
    rgba(170,255,208,.55) 51%,transparent 66%)}
#archive-card[open]::before,#auth-card[open]::before,#guide-card[open]::before{animation:card-strike 560ms ease-out}
@keyframes card-strike{0%{opacity:1}26%{opacity:.7}100%{opacity:0}}
/* Raster over everything on the card, text included — the same rule the
   terminal's glass follows, for the same reason. */
#archive-card::after,#auth-card::after,#guide-card::after{content:"";position:absolute;inset:0;z-index:5;pointer-events:none;
  background:repeating-linear-gradient(to bottom,rgba(0,0,0,.3) 0 1px,transparent 1px 3px)}

/* The topline is the terminal's active title bar, down to the stripes and the
   solid ground its name sits on — but a step darker than the terminal's.
   That bar is 19px over a window a few hundred wide; this one is 780px, and
   the palette's top green across that much surface is the loudest object on
   the glass, louder than the file it is labelling. The name keeps the bright
   plate, so the hierarchy still runs name, bar, content. */
.archive-topline{display:flex;justify-content:space-between;align-items:center;
  gap:12px;padding:0 4px 0 11px;height:26px;margin:3px 3px 0;flex:none;
  color:var(--ink);background:repeating-linear-gradient(to bottom,#3aa76a 0 1px,#1b6640 1px 2px);
  font-size:9.5px;font-weight:700;letter-spacing:.14em}
.archive-topline>span{background:#86ffb0;padding:1px 6px;margin-left:-6px}
.archive-topline b{font-weight:400;opacity:.5;padding:0 6px}
#archive-close,#auth-close,#guide-close{flex:none;width:21px;height:18px;font-size:11px;font-weight:700;line-height:1;
  display:grid;place-items:center;color:var(--ink);border:0;border-radius:0;
  box-shadow:inset 1px 1px 0 rgba(93,255,143,.55),inset -1px -1px 0 rgba(0,22,10,.9);
  transition:background .14s,color .14s}
#archive-close:hover,#auth-close:hover,#guide-close:hover{background:var(--ink);color:var(--grn-2)}

.archive-heading{padding:22px 26px 20px;border-bottom:1px solid var(--card-rule-2);flex:none}
.archive-eyebrow{display:flex;justify-content:space-between;gap:16px;margin-bottom:15px;
  color:var(--card-muted);font-size:9px;letter-spacing:.18em}
.archive-eyebrow span:first-child{color:var(--grn);text-shadow:var(--phos)}
.archive-heading h2{font-size:clamp(20px,2.1vw,27px);line-height:1.22;font-weight:700;
  letter-spacing:-.045em;color:var(--grn-2);text-shadow:var(--phos)}
.archive-heading p{margin-top:10px;font-size:11px;line-height:1.65;color:var(--card-muted)}
/* No scroll-behavior:smooth here. It buys nothing a wheel does not already
   do, and it makes every scrollIntoView report a rect the element is still
   travelling away from — including the one render() does to put a freshly
   opened file back at the top. */
.archive-content{padding:4px 26px 24px;overflow-y:auto;overscroll-behavior:contain;
  min-height:0;scrollbar-width:thin;scrollbar-color:var(--line-2) transparent}
.archive-content::-webkit-scrollbar{width:8px}
.archive-content::-webkit-scrollbar-thumb{background:var(--line-2)}
.archive-content::-webkit-scrollbar-track{background:transparent}

/* One rule per row, full width. Two columns of a 350px measure broke
   every sentence onto a second or third line and made the card longer
   than the six rules needed. */
.archive-rules{list-style:none;display:grid;grid-template-columns:1fr}
.archive-rules li{display:flex;align-items:flex-start;gap:12px;padding:8px 0;
  border-bottom:1px solid var(--card-rule)}
.archive-rule-number{font-size:10px;line-height:1.7;color:var(--dim);flex:none;padding-top:1px}
.archive-rules p{font-size:11.5px;line-height:1.75;color:var(--grn)}
.archive-faq{margin-top:16px}
.archive-faq h3{display:flex;justify-content:space-between;align-items:center;gap:16px;
  font-size:11px;letter-spacing:.1em;color:var(--grn-2);margin-bottom:8px;text-shadow:var(--phos)}
.archive-faq h3 span{font-size:8px;letter-spacing:.16em;font-weight:400;color:var(--card-muted)}
.archive-faq details{border-bottom:1px solid var(--card-rule)}
.archive-faq summary{list-style:none;cursor:pointer;display:flex;justify-content:space-between;
  gap:14px;font-size:11px;font-weight:700;padding:9px 0;line-height:1.7;transition:color .14s}
.archive-faq summary:hover{color:var(--grn-2)}
.archive-faq summary::-webkit-details-marker{display:none}
.archive-faq summary::after{content:"+";font-size:12px;line-height:1.5;flex:none;color:var(--vio-txt)}
.archive-faq details[open] summary::after{content:"\2212"}
.archive-faq details p{font-size:10.5px;line-height:1.75;color:var(--card-muted);
  padding:0 24px 13px 0;max-width:65ch}

/* Resource rows carry the terminal's link grammar: hairline-separated rows on
   the window ground, with the destination in violet like every other link. */
.archive-links{display:grid;grid-template-columns:1fr 1fr;gap:1px;background:var(--card-rule);
  margin-top:18px;border:1px solid var(--card-rule)}
.archive-link{position:relative;display:flex;flex-direction:column;
  padding:16px 34px 16px 16px;background:var(--ink);color:var(--card-ink);
  transition:background .16s,color .16s}
.archive-link:hover{background:rgba(93,255,143,.06)}
.archive-link-meta{font-size:8px;letter-spacing:.12em;color:var(--card-muted);line-height:1.6;
  overflow-wrap:anywhere;margin-bottom:13px}
.archive-link strong{font-size:11.5px;line-height:1.5;color:var(--grn-2)}
.archive-link-desc{font-size:9.5px;letter-spacing:.06em;color:var(--card-muted);margin-top:6px;line-height:1.6}
.archive-link-arrow{position:absolute;right:13px;top:15px;font-size:13px;color:var(--vio-txt);
  transition:color .16s,transform .16s}
.archive-link:hover .archive-link-arrow{color:var(--grn);transform:translate(1px,-1px)}
.archive-link-note{font-size:9px;line-height:1.7;margin-top:16px;color:var(--card-muted)}

.archive-footer{display:flex;justify-content:space-between;align-items:center;gap:12px;flex:none;
  padding:11px 26px;border-top:1px solid var(--card-rule-2);background:#020a05}
.archive-footer nav{display:flex;gap:8px}
.archive-footer button{font-size:9px;letter-spacing:.14em;padding:8px 12px;color:var(--dim);
  border:1px solid var(--card-rule-2);transition:color .15s,border-color .15s,background .15s}
.archive-footer button span{margin-left:7px}
.archive-footer button:hover{color:var(--grn-2);border-color:var(--grn)}
.archive-footer button[aria-pressed="true"]{background:var(--grn-2);border-color:var(--grn-2);
  color:var(--ink);text-shadow:none}
.archive-close-hint{font-size:8px;letter-spacing:.16em;color:var(--card-muted)}
.archive-sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0,0,0,0);white-space:nowrap;border:0}
#archive-card :focus-visible,#auth-card :focus-visible,#guide-card :focus-visible{outline:1px solid var(--grn-2);outline-offset:2px}
#archive-close:focus-visible,#auth-close:focus-visible,#guide-close:focus-visible{outline-color:var(--ink);outline-offset:-3px}
.archive-content:focus-visible{outline-offset:-3px}

/* ---- putting a file back ----
   <dialog> closes on the frame it is told to, and it should: the focus
   return, Escape and the checks all depend on that being immediate. So the
   set turning the picture off is a separate, inert layer left behind on the
   way out — the card collapses to a line and the line blinks to a dot, while
   the real dialog is already gone and focus is already back on the shelf. */
.archive-ghost{position:fixed;inset:0;z-index:2147483000;pointer-events:none}
.archive-ghost i{position:absolute;inset:0;background:rgba(1,4,2,.82);
  animation:ghost-dim 260ms ease-out forwards}
.archive-ghost b{position:absolute;left:var(--gx);top:var(--gy);width:var(--gw);height:var(--gh);
  background:#0a1c12;box-shadow:inset 0 0 0 1px #2f9159;border-radius:4px;
  animation:ghost-collapse 300ms cubic-bezier(.55,0,.75,.15) forwards}
@keyframes ghost-dim{to{opacity:0}}
@keyframes ghost-collapse{
  0%{transform:scaleY(1);background:#0a1c12;opacity:1}
  52%{transform:scaleY(.014);background:#a8ffcb;opacity:1}
  76%{transform:scaleY(.009) scaleX(.86);background:#e6fff0;opacity:1}
  100%{transform:scaleY(.007) scaleX(0);background:#fff;opacity:0}
}

@media(max-width:650px){
  #archive-card,#auth-card,#guide-card{width:calc(100vw - 24px);max-height:calc(100dvh - 24px)}
  .archive-heading{padding:18px}.archive-content{padding:0 18px 18px}
  .archive-rules,.archive-links{grid-template-columns:1fr}.archive-rules li{padding:14px 0}
  .archive-eyebrow span:last-child,.archive-close-hint{display:none}
  .archive-footer{padding:10px 18px}
}
@media(prefers-reduced-motion:reduce){
  #archive-card[open],#archive-card[open]::before,#auth-card[open],#auth-card[open]::before,#guide-card[open],#guide-card[open]::before{animation:none}
  .archive-link,.archive-link-arrow,.archive-footer button,.archive-faq summary,
  #archive-close{transition:none}
  .archive-ghost{display:none}
}
@media(max-width:1150px){.scene-view-controls{bottom:99px}.scene-file{font-size:8px}}
@media(prefers-reduced-motion:reduce){
  body.scene-3d.glitch #os{animation:none}.scene-view-controls,.scene-file{transition:none}
}
