/* @alc-notice */
/*!
 * Copyright (c) 2026 Alien Life Creations. All rights reserved.
 *
 * This file is part of a proprietary work. It is served to your browser
 * because a browser cannot run code it has not received; that is a technical
 * necessity and not a grant of any licence. You may not copy, redistribute,
 * or create derivative works from it.
 *
 * alienlifecreations.com | alienlifearcade.com | alienlifestudio.com
 */
/* @alc-notice-end */
/* ==========================================================================
   ALIEN LIFE STUDIO -- the whole design system, one file, every page.

   PALETTE. Token NAMES are Alien Life Creations' own and always will be,
   because this is a sister site and a sister site is a token-value remap,
   never a token-name change and never a fork (U6).

   Most VALUES are ALC's verbatim. Nine are deliberately not, and every one of
   those nine is declared in `_build/palette.json` with its reason and with
   ALC's own value beside it. That file is the ONE home for the difference:
   `studio_gate.py` reads it and goes red on a value that differs and is NOT
   declared there, and red again if ALC repaints a token the remap claims to
   know the value of. An undeclared difference is exactly as forbidden as it
   was before; what changed is that a DECLARED one is now possible at all.

   THE REMAP, in one line (Gortiva, 2026-09-18): the arcade keeps the
   signature green, the studio leads with cold projection light. The two sites
   were byte-identical in every token and read as the same site. What differs
   now is both USE and value: ALC is a field guide and leads with colour; a
   film site leads with a dark screen, sits its page further back, and spends
   colour on the frame. The brightest thing on any page here is the picture.

   THE RIM. `.screen` is the centrepiece. It is a real bezel with thickness,
   an inner bevel and viewfinder framing marks at its corners, and the controls
   live IN it rather than floating over the picture, so nothing the studio made
   is ever covered by an interface. In fullscreen there is no bezel, so the
   controls become an overlay; that is the one place the rule relaxes, and it
   relaxes because the rim is gone.
   ========================================================================== */

:root{
  /* --- ALC tokens, verbatim ------------------------------------------- */
  --green:#48FF2B; --green-deep:#2ECF1A;
  --violet:#A35AAF; --violet-deep:#6E3C79;
  --lime:#93FB06; --lime-deep:#5FA400;
  --gold:#DBFF07; --gold-deep:#A6C000;
  --maxw:1160px;

  /* --- DECLARED REMAP: every line below is in _build/palette.json ------
     with ALC's own value and the reason. Changing one here without changing
     it there is a RED gate, on purpose: that is the drift this used to
     forbid absolutely and now forbids unless it is written down. --------- */
  --cyan:#3FFAF5; --cyan-deep:#1F9AA5;   /* ALC's, verbatim */
  --space:#0A0A12; --space-2:#0E1420;    /* ALC's, verbatim */
  --card:#0F1620;                        /* ALC's, verbatim */
  --ink:#EAF2E8; --ink-soft:#9DB2A6; --ink-label:#7FBF6A;  /* ALC's, verbatim */
  --accent:var(--green); --accent-deep:var(--green-deep);

  /* THE PINK LINE, and it is the WHOLE remap now (Gortiva, 2026-09-18, third
     and final call of the day). The studio tried leading with cyan, then with
     pink over a red-black ground. Both changed the site's colour; this changes
     its EDGES. The ground, the ink, the accent and the star field are Alien
     Life Creations' own again, and the only thing that is the studio's is the
     line around everything.
     It is one token because `--card-line` already draws all three places he
     named: every container's border, the rule under the header, and the rule
     over the footer. Repainting it once does all of them and there is nothing
     to keep in step.
     The pink itself is borrowed from alienlifeshop.com, which has carried
     these two hexes live since 2026-07-25. */
  --pink:#FF4FD8; --pink-deep:#C2299E;
  --card-line:#C2299E;                   /* every border, and the two rules */
  --card-line-hover:#FF4FD8;             /* hover resolves to the full pink */

  /* --- the rim's own metal, derived from the palette, not new colour --- */
  --rim-1:#151B22; --rim-2:#0C1118; --rim-line:#28323C;
  --rim-bevel:#3A4652; --picture:#05070A;

  /* --- THE FILM GATE: the studio's container material (Gortiva, 09-18).
     The arcade's container is a cabinet: hard corners, phosphor glow, the
     accent burning at the edge. The studio's is a film gate: a matte plate,
     an inner bevel, one lit hairline, and the perforation running down the
     leading edge. Same geometry in both (U1 and U3 are untouched), different
     metal. These are the rim's own tokens reused, not new colour. -------- */
  --gate-face:linear-gradient(180deg,#111A24,#0B1118);
  --gate-line:#C2299E; --gate-bevel:#FF4FD8; --gate-perf:#2A1220;

  --font:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  --mono:ui-monospace,"SF Mono",Menlo,Consolas,monospace;
  --ease:cubic-bezier(.22,.61,.36,1);
}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%; scroll-behavior:smooth}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}}

body{
  margin:0; background:var(--space); color:var(--ink);
  font-family:var(--font); line-height:1.65;
  overflow-x:clip;                        /* U3.3: clip, never hidden */
  min-height:100vh; min-height:100dvh;    /* U3.4 */
  display:flex; flex-direction:column;
}
#constellation{position:fixed; inset:0; width:100%; height:100%;
  z-index:0; pointer-events:none}
.wrap{width:100%; max-width:var(--maxw); margin:0 auto;
  padding:0 clamp(16px,4vw,28px); position:relative; z-index:1}
main{flex:1 0 auto}
a{color:var(--cyan); text-decoration-thickness:1px; text-underline-offset:3px}
a:hover{color:var(--accent)}
:focus-visible{outline:2px solid var(--accent); outline-offset:3px; border-radius:6px}
.sr-only{position:absolute; width:1px; height:1px; overflow:hidden;
  clip:rect(0,0,0,0); white-space:nowrap}
img,video{max-width:100%; display:block}

/* ===================== header ===================== */
.top{position:relative; z-index:2; border-bottom:1px solid var(--card-line);
  box-shadow:0 1px 14px -4px var(--pink-deep);
  background:linear-gradient(180deg,rgba(11,15,11,.92),rgba(10,10,18,.72));
  backdrop-filter:blur(8px)}
.top .wrap{display:flex; align-items:center; gap:14px; min-height:68px;
  flex-wrap:wrap}
.brand{display:flex; align-items:center; gap:11px; text-decoration:none;
  margin-right:auto; min-width:0}
.brand img{width:38px; height:38px; border-radius:50%;
  border:1px solid var(--card-line); flex:none}
.brand b{font-size:14px; letter-spacing:.19em; text-transform:uppercase;
  color:var(--ink); font-weight:700; white-space:nowrap}
.brand span{display:block; font-size:10.5px; letter-spacing:.26em;
  text-transform:uppercase; color:var(--ink-label); font-weight:700}
.top nav{display:flex; gap:6px; flex-wrap:wrap}
.top nav a{padding:7px 13px; border-radius:999px; font-size:13.5px;
  color:var(--ink-soft); text-decoration:none; border:1px solid transparent;
  white-space:nowrap}
.top nav a:hover{color:var(--ink); border-color:var(--card-line);
  background:var(--card)}
.top nav a[aria-current]{color:var(--accent); border-color:var(--card-line-hover)}

/* ===================== type ===================== */
.eyebrow{font-size:11.5px; letter-spacing:.26em; text-transform:uppercase;
  color:var(--accent); font-weight:700; margin:0 0 12px}
h1{font-size:clamp(30px,5.4vw,54px); line-height:1.06; margin:0 0 14px;
  letter-spacing:.01em; font-weight:800}
h2.sec-head{text-align:center; font-size:clamp(20px,3.2vw,27px);
  margin:0 0 8px; letter-spacing:.01em}
.lead{max-width:62ch; margin:0 auto 26px; text-align:center;
  color:var(--ink-soft); font-size:15.5px}
.logline{font-size:clamp(16px,2.1vw,19px); color:var(--ink-soft);
  max-width:56ch; margin:0 0 20px}

/* ===================== THE SCREEN RIM ===================== */
.screen{
  position:relative; border-radius:20px;
  padding:clamp(10px,1.4vw,16px);
  background:
    linear-gradient(180deg,var(--rim-1) 0%, var(--rim-2) 62%, #090D13 100%);
  border:1px solid var(--rim-line);
  box-shadow:
    0 0 0 1px rgba(0,0,0,.6),
    0 26px 60px -22px rgba(0,0,0,.95),
    inset 0 1px 0 rgba(255,255,255,.045);
}
/* the accent hairline along the top of the bezel: the one lit edge */
.screen::before{content:""; position:absolute; left:14%; right:14%; top:-1px;
  height:1px; background:linear-gradient(90deg,
    transparent, var(--accent-deep) 22%, var(--cyan) 50%, var(--accent-deep) 78%,
    transparent); opacity:.55}

/* viewfinder framing marks, on the BEZEL so they never cover the picture */
.screen .mk{position:absolute; width:13px; height:13px; pointer-events:none;
  border:2px solid var(--accent-deep); opacity:.5; border-radius:2px}
.screen .mk.tl{top:5px; left:5px; border-right:0; border-bottom:0}
.screen .mk.tr{top:5px; right:5px; border-left:0; border-bottom:0}
.screen .mk.bl{bottom:5px; left:5px; border-right:0; border-top:0}
.screen .mk.br{bottom:5px; right:5px; border-left:0; border-top:0}

.picture{position:relative; aspect-ratio:16/9; border-radius:10px;
  overflow:hidden; background:var(--picture);
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.9),
             inset 0 0 34px -8px rgba(0,0,0,.9),
             0 0 0 1px var(--rim-bevel)}
.picture video{width:100%; height:100%; object-fit:contain; background:#000}
.picture video::-webkit-media-controls{display:none!important}

/* the poster/idle state and its play button */
.pict-idle{position:absolute; inset:0; display:grid; place-items:center;
  background:var(--picture); cursor:pointer; border:0; width:100%; padding:0}
.pict-idle img{position:absolute; inset:0; width:100%; height:100%;
  object-fit:cover; opacity:.55}
.pict-idle .big{position:relative; width:74px; height:74px; border-radius:50%;
  display:grid; place-items:center; background:rgba(10,10,18,.66);
  border:1.5px solid var(--accent); box-shadow:0 0 26px -6px var(--accent-deep);
  transition:transform .22s var(--ease), box-shadow .22s var(--ease)}
.pict-idle:hover .big{transform:scale(1.07);
  box-shadow:0 0 34px -4px var(--accent)}
@media (prefers-reduced-motion:reduce){.pict-idle:hover .big{transform:none}}
.pict-idle .big svg{width:26px; height:26px; margin-left:4px; fill:var(--accent)}

/* ------- the control bar, IN the rim ------- */
.ctl{display:flex; align-items:center; gap:8px; padding:10px 4px 2px;
  flex-wrap:nowrap; min-width:0}
.ctl button{appearance:none; background:transparent; border:1px solid transparent;
  color:var(--ink-soft); border-radius:8px; cursor:pointer; padding:6px;
  display:grid; place-items:center; flex:none; line-height:0}
.ctl button:hover{color:var(--ink); background:rgba(255,255,255,.055)}
.ctl button svg{width:19px; height:19px; fill:currentColor}
.ctl button[aria-pressed="true"]{color:var(--accent)}
.ctl .time{font-family:var(--mono); font-size:12px; color:var(--ink-soft);
  flex:none; letter-spacing:.02em; font-variant-numeric:tabular-nums}
.ctl .spacer{flex:1 1 auto; min-width:0}

/* scrubber: its own row so it is full width and easy to hit */
.bar{position:relative; height:22px; display:flex; align-items:center;
  cursor:pointer; touch-action:none; margin:2px 4px 0}
.bar .track{position:relative; height:4px; width:100%; border-radius:99px;
  background:rgba(255,255,255,.13); overflow:hidden}
.bar .buf{position:absolute; inset:0 auto 0 0; width:0;
  background:rgba(255,255,255,.18)}
.bar .played{position:absolute; inset:0 auto 0 0; width:0;
  background:linear-gradient(90deg,var(--accent-deep),var(--accent))}
.bar .knob{position:absolute; top:50%; left:0; width:13px; height:13px;
  margin:-6.5px 0 0 -6.5px; border-radius:50%; background:var(--accent);
  box-shadow:0 0 0 3px rgba(72,255,43,.2); opacity:0;
  transition:opacity .16s var(--ease)}
.bar:hover .knob, .bar:focus-visible .knob, .bar.dragging .knob{opacity:1}
.bar:hover .track{height:6px}
.bar .tip{position:absolute; bottom:24px; transform:translateX(-50%);
  background:#05070A; border:1px solid var(--rim-line); color:var(--ink);
  font-family:var(--mono); font-size:11.5px; padding:3px 7px; border-radius:6px;
  pointer-events:none; opacity:0; white-space:nowrap}
.bar:hover .tip{opacity:1}

/* volume */
.vol{display:flex; align-items:center; gap:6px; flex:none}
.vol input{appearance:none; width:0; height:4px; border-radius:99px;
  background:rgba(255,255,255,.16); cursor:pointer; padding:0;
  /* opacity as well as width: a zero-width range input still PAINTS its
     thumb, which read as a stray green dot floating in the control bar. */
  opacity:0; transition:width .2s var(--ease), opacity .2s var(--ease)}
.vol:hover input, .vol input:focus-visible{width:72px; opacity:1}
.vol input::-webkit-slider-thumb{appearance:none; width:12px; height:12px;
  border-radius:50%; background:var(--accent); cursor:pointer}
.vol input::-moz-range-thumb{width:12px; height:12px; border:0;
  border-radius:50%; background:var(--accent); cursor:pointer}
@media (max-width:620px){.vol input, .vol:hover input{width:0; display:none}}

/* THE CONTROL BAR HAS A FLOOR, and it was 454px wide.
   `.ctl` is flex-nowrap with ten fixed-size children, so below ~455px it could
   not shrink and pushed the whole document sideways: measured 134px of overflow
   at 320px, 79px at 375px, 40px at 414px, identically on every page. A rim that
   breaks the page it frames is not a rim.
   The fix is not to let it wrap (a control bar on two lines reads as broken);
   it is to DROP the controls that have keyboard and gesture equivalents and
   keep the ones that have none. Skip back/forward stay reachable with J and L
   and by scrubbing; picture-in-picture is a desktop affordance. Play, seek,
   time, mute, captions, settings and fullscreen survive at every width. */
@media (max-width:560px){
  .ctl{gap:4px; padding-inline:0}
  .ctl [data-back], .ctl [data-fwd], .ctl [data-pip]{display:none}
  .ctl .time{font-size:11px}
  .ctl button{padding:5px}
  .ctl button svg{width:18px; height:18px}
}
@media (max-width:380px){
  .ctl .time{font-size:10.5px; letter-spacing:0}
  .ctl button{padding:4px}
}

/* settings menu */
.menu-wrap{position:relative; flex:none}
.menu{position:absolute; right:0; bottom:calc(100% + 8px); min-width:212px;
  background:#0B1017; border:1px solid var(--rim-line); border-radius:12px;
  padding:6px; box-shadow:0 18px 40px -14px rgba(0,0,0,.95); z-index:6}
/* `hidden` HIDES, WHATEVER A COMPONENT DECLARES (2026-09-19). The HTML spec's own rule is
   `[hidden]{display:none}` with no `!important`, so ANY class rule that sets `display` beats it.
   `.pict-idle` set `display:grid` and had no `[hidden]` guard, so `player.js` hiding the idle
   layer on `play` did nothing: the play button and its poster kept drawing over a video that was
   playing underneath, which reads exactly like a film with sound and no picture. Gortiva saw it on
   THE POTLUCK; it had been doing the same to TOO BRIGHT since the player was written.
   Two components had been guarded one at a time (`.menu[hidden]`, `.cue[hidden]`) and the third
   was missed, which is what a list does. This is the rule, so the next component cannot miss it. */
[hidden]{display:none !important}
.menu h4{margin:8px 10px 4px; font-size:10.5px; letter-spacing:.2em;
  text-transform:uppercase; color:var(--ink-label); font-weight:700}
.menu button{display:flex; width:100%; justify-content:space-between;
  align-items:center; gap:10px; padding:7px 10px; border-radius:8px;
  font-size:13.5px; color:var(--ink-soft); text-align:left}
.menu button:hover{background:rgba(255,255,255,.06); color:var(--ink)}
.menu button[aria-checked="true"]{color:var(--accent)}
.menu button[aria-checked="true"]::after{content:"\\2713"; font-size:12px}
.menu button[disabled]{opacity:.42; cursor:default}
.menu button[disabled]:hover{background:transparent; color:var(--ink-soft)}
.menu .note{margin:2px 10px 8px; font-size:11.5px; color:#6E8478;
  line-height:1.45}

/* the caption line, drawn by us so it sits above the rim's own controls */
.cue{position:absolute; left:4%; right:4%; bottom:5%; text-align:center;
  font-size:clamp(14px,1.7vw,19px); line-height:1.4; color:#fff;
  text-shadow:0 2px 5px #000,0 0 2px #000; pointer-events:none;
  background:rgba(0,0,0,.42); padding:5px 12px; border-radius:8px;
  width:fit-content; margin:0 auto; max-width:86%}

/* fullscreen: the bezel is gone, so the controls become an overlay */
.screen:fullscreen{padding:0; border-radius:0; border:0; background:#000}
.screen:fullscreen .mk{display:none}
.screen:fullscreen .picture{aspect-ratio:auto; height:100vh;
  border-radius:0; box-shadow:none}
.screen:fullscreen .ctl,.screen:fullscreen .bar{position:absolute;
  left:0; right:0; z-index:5; background:linear-gradient(180deg,
  transparent,rgba(0,0,0,.82)); padding-inline:16px}
.screen:fullscreen .bar{bottom:44px; margin:0}
.screen:fullscreen .ctl{bottom:0; padding-bottom:10px}
.screen:fullscreen.idle .ctl,.screen:fullscreen.idle .bar{opacity:0;
  transition:opacity .3s var(--ease)}
.screen:fullscreen.idle{cursor:none}

/* ===================== hero ===================== */
.hero{padding:clamp(26px,5vw,52px) 0 clamp(18px,3vw,30px)}
.hero-grid{display:grid; gap:clamp(20px,3.4vw,38px); align-items:center;
  grid-template-columns:minmax(0,1.32fr) minmax(0,1fr)}   /* U3.1 */
@media (max-width:900px){.hero-grid{grid-template-columns:minmax(0,1fr)}}

/* ===================== chips + meta ===================== */
.chips{display:flex; gap:8px; flex-wrap:wrap; margin:0 0 16px; padding:0;
  list-style:none}
.chip{display:inline-flex; align-items:center; gap:7px; padding:5px 11px;
  border-radius:999px; border:1px solid var(--card-line); background:var(--card);
  font-size:11.5px; letter-spacing:.12em; text-transform:uppercase;
  color:var(--ink-soft); font-weight:700; white-space:nowrap}
.chip .dot{width:6px; height:6px; border-radius:50%; background:var(--ink-label)}
.chip.planned{border-color:var(--violet-deep); color:#C9A6D2}
.chip.planned .dot{background:var(--violet)}
/* filming moves cyan -> gold: cyan is now the SITE lead, so a status that
   stayed cyan would stop being a signal and start being chrome. */
/* HELD: finished, and deliberately not being shown. Cyan rather than the
   green of released or the violet of planned, because it is neither of
   those: the film exists, and the decision not to show it is someone's
   rather than the pipeline's. */
.chip.held{border-color:var(--cyan-deep); color:#9FE8F5}
.chip.held .dot{background:var(--cyan)}
.chip.filming{border-color:var(--gold-deep); color:#E8F58A}
.chip.filming .dot{background:var(--gold)}
/* released STAYS green. Green-means-done is universal and it is the one
   place on this site the arcade colour still earns its keep. */
.chip.released{border-color:var(--green-deep); color:#A9F59B}
.chip.released .dot{background:var(--green);
  box-shadow:0 0 8px var(--green-deep)}

.btn{display:inline-flex; align-items:center; gap:9px; padding:11px 19px;
  border-radius:999px; text-decoration:none; font-size:14px; font-weight:700;
  border:1px solid var(--card-line-hover); color:var(--space);
  background:var(--accent); transition:transform .18s var(--ease)}
.btn:hover{transform:translateY(-1px); color:var(--space)}
.btn.ghost{background:transparent; color:var(--ink);
  border-color:var(--card-line)}
.btn.ghost:hover{border-color:var(--card-line-hover); color:var(--accent)}
@media (prefers-reduced-motion:reduce){.btn:hover{transform:none}}
.btn svg{width:15px; height:15px; fill:currentColor}

/* ===================== the slate grid ===================== */
section{padding:clamp(28px,5vw,58px) 0}
/* THREE ACROSS, AND IT IS A FIXED COUNT ON PURPOSE (2026-09-20). This was
   `auto-fit, minmax(min(290px,100%),1fr)`, which sizes the card from how many
   there are: with one film on the slate the single track stretched to the full
   1116 px wrap and the 16/9 poster became a 628 px tall panel holding a 50 px
   glyph. Auto-fit is right for a shelf whose length nobody controls; the slate
   is a dozen entries at most and its card should be the same size at one film
   as at twelve. A fixed three also means a card's picture has ONE width to be
   encoded for, which is what lets media/<slug>-card.jpg be 760 px rather than
   1280. Twelve cards is four rows.
   U3 still owns the responsive floor: two across below 860, one below 560. */
.slate{display:grid; gap:clamp(14px,2vw,20px); padding:0; margin:26px 0 0;
  list-style:none; grid-template-columns:repeat(3,minmax(0,1fr))}
@media (max-width:860px){.slate{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:560px){.slate{grid-template-columns:minmax(0,1fr)}}
/* THE FILM GATE. Every panel on this site is one plate of the same metal as
   the rim around the picture, so the page reads as the inside of a machine
   that runs film rather than as a shelf of cards. The arcade's container is a
   cabinet and does the opposite: hard edge, phosphor burn, accent at the rim.
   The GEOMETRY is identical on both sites, and it has to be: U1 owns the
   layout and U3 owns the responsive floor. What differs is the material. */
.card{min-width:0; border:1px solid var(--gate-line); border-radius:16px;
  background:var(--gate-face); overflow:hidden; display:flex;
  flex-direction:column; position:relative; padding-left:10px;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.035),
             inset 0 0 0 1px rgba(0,0,0,.5),
             0 18px 40px -30px rgba(0,0,0,.9);
  transition:border-color .2s var(--ease), transform .2s var(--ease)}
/* the perforation down the leading edge: a film gate's sprocket run, drawn
   with one repeating-gradient rather than an image, so it costs nothing and
   scales with the panel. */
.card::before{content:""; position:absolute; left:0; top:0; bottom:0;
  width:9px; pointer-events:none; border-right:1px solid var(--gate-line);
  background:repeating-linear-gradient(180deg,
    transparent 0 9px, var(--gate-perf) 9px 17px)}
.card:hover{border-color:var(--card-line-hover); transform:translateY(-3px)}
.card:hover::before{border-right-color:var(--gate-bevel)}
@media (prefers-reduced-motion:reduce){.card:hover{transform:none}}
.card > a{text-decoration:none; color:inherit; display:flex;
  flex-direction:column; height:100%}

/* THE CARD'S POSTER IS THE FILM'S OWN FRAME WHEN THERE IS ONE, and the drawn
   aperture when there is not. Until 2026-09-20 it was always the glyph, and
   this comment said "there is no still to show, so showing one would be a lie"
   -- written truthfully when the site had no footage and left standing after
   two films were rendered, so the slate was drawing an empty-frame mark over a
   film the visitor could already watch. The accent gradient stays underneath:
   it is what a planned card is, and what an image loads on top of. */
.card .poster{position:relative; aspect-ratio:16/9; display:grid;
  place-items:center; border-bottom:1px solid var(--card-line);
  background:radial-gradient(120% 130% at 50% 8%,
    color-mix(in srgb,var(--accent) 20%, transparent), transparent 64%),
    linear-gradient(168deg,#0C1219,#070A0F)}
.card .poster svg{width:50px; height:50px; opacity:.5; stroke:var(--accent);
  fill:none; stroke-width:1.5}
/* the frame fills the plate. `grid-area` rather than absolute positioning so
   the poster keeps its own 16/9 height from the aspect-ratio above and does not
   need the image to have loaded to be the right size. */
.card .poster img{grid-area:1/1; width:100%; height:100%; object-fit:cover;
  display:block}
/* the accent survives as a wash over the frame, so a card still reads as ITS
   film's colour rather than as a generic thumbnail, and the runtime chip in the
   corner keeps something to sit against on a bright frame. */
.card .poster:has(img)::after{content:""; grid-area:1/1; pointer-events:none;
  background:linear-gradient(180deg,
    color-mix(in srgb,var(--accent) 9%, transparent) 0%,
    transparent 38%, rgba(4,6,9,.34) 100%)}
.card .poster .runtime{position:absolute; right:9px; bottom:9px;
  font-family:var(--mono); font-size:11px; color:var(--ink-soft);
  background:rgba(5,7,10,.8); border:1px solid var(--card-line);
  padding:2px 7px; border-radius:6px}
.card .body{padding:16px 17px 18px; display:flex; flex-direction:column;
  gap:9px; flex:1}
.card h3{margin:0; font-size:18px; color:var(--ink)}
.card p{margin:0; font-size:14px; color:var(--ink-soft)}
.card .foot{margin-top:auto; padding-top:4px; display:flex; gap:8px;
  flex-wrap:wrap; align-items:center}

/* ===================== detail page ===================== */
.detail{padding:clamp(22px,4vw,40px) 0 0}
.detail-grid{display:grid; gap:clamp(22px,3.4vw,40px); margin-top:clamp(22px,4vw,38px);
  grid-template-columns:minmax(0,1.6fr) minmax(0,1fr)}
@media (max-width:900px){.detail-grid{grid-template-columns:minmax(0,1fr)}}
.prose p{margin:0 0 15px; font-size:16px; color:var(--ink-soft); max-width:66ch}
.prose p:first-of-type{color:var(--ink); font-size:17px}
/* the facts panel is the same plate, minus the perforation: it is read, not
   run. One lit hairline across the top, exactly as the rim has. */
.facts{border:1px solid var(--gate-line); border-radius:14px; position:relative;
  background:var(--gate-face); padding:6px 18px 14px; align-self:start;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.035),
             inset 0 0 0 1px rgba(0,0,0,.45)}
.facts::before{content:""; position:absolute; left:16%; right:16%; top:-1px;
  height:1px; opacity:.5; background:linear-gradient(90deg,
    transparent, var(--accent-deep) 24%, var(--cyan) 50%,
    var(--accent-deep) 76%, transparent)}
.facts dl{margin:0}
.facts dt{font-size:10.5px; letter-spacing:.2em; text-transform:uppercase;
  color:var(--ink-label); font-weight:700; margin:14px 0 3px}
.facts dd{margin:0; font-size:14.5px; color:var(--ink)}
.pager{display:flex; gap:12px; justify-content:space-between; flex-wrap:wrap;
  margin:clamp(30px,5vw,52px) 0 0; padding-top:22px;
  border-top:1px solid var(--card-line)}
.pager a{display:flex; flex-direction:column; gap:2px; text-decoration:none;
  font-size:14px; color:var(--ink); min-width:0}
.pager a small{font-size:10.5px; letter-spacing:.18em; text-transform:uppercase;
  color:var(--ink-label); font-weight:700}
.pager a:last-child{text-align:right; margin-left:auto}

/* ===================== notes + footer ===================== */
.note{border:1px solid var(--violet-deep); border-radius:14px;
  background:linear-gradient(180deg,rgba(163,90,175,.09),transparent);
  padding:16px 20px; color:var(--ink-soft); font-size:14.5px;
  max-width:74ch; margin:0 auto; text-align:center}
.note strong{color:var(--ink)}

footer{position:relative; z-index:1; flex-shrink:0;
  margin-top:clamp(34px,6vw,70px); padding:26px 0 34px;
  border-top:1px solid var(--card-line);
  box-shadow:0 -1px 14px -4px var(--pink-deep);
  color:var(--ink-soft); font-size:13.5px}
footer .wrap{display:flex; gap:16px; flex-wrap:wrap; align-items:center;
  justify-content:space-between}
footer nav{display:flex; gap:16px; flex-wrap:wrap}
footer p{margin:0; max-width:60ch}

/* ======================================================================
   FROM THE ARCADE -- the sibling shelf (2026-09-18).

   The arcade's live games, baked in at build time from its own
   /games.json. Never fetched: alienlifearcade.com is a different origin
   and this page must not need that site to be up to finish drawing.

   IT LOOKS LIKE THE ARCADE, ON PURPOSE. Every other panel here is a film
   gate in cold cyan. These are cabinets in the arcade's green, so the
   shelf reads as a window into somewhere else rather than as more studio.
   Both palettes are Alien Life Creations' own tokens, and only which one
   leads moves. The GEOMETRY is this site's `.slate` grid, unchanged: the
   guest borrows our layout and brings its own material.
   ====================================================================== */
.arcade-shelf {
  /* the grid the film slate uses, stated here rather than borrowed from
     `.slate`, so the guest shelf owns its own layout (U3.1: minmax(min(..),1fr)
     and never a bare fixed min, or the track cannot shrink and the document
     scrolls sideways). */
  list-style: none;
  margin: 26px 0 0;
  padding: 0;
  display: grid;
  gap: clamp(14px, 2vw, 20px);
  grid-template-columns: repeat(auto-fit, minmax(min(290px, 100%), 1fr));
}
.arcade-shelf .gcard {
  border-color: #1E3A2A;
  background: var(--card-2, #0C121b);
  padding-left: 0;                    /* no film perforation on a cabinet */
}
/* the cabinet's lit moulding, two short runs at the top corners */
.arcade-shelf .gcard::before {
  inset: 0 0 auto 0;
  left: 0;
  width: auto;
  height: 2px;
  bottom: auto;
  border-right: 0;
  opacity: .5;
  background:
    linear-gradient(90deg, var(--green) 0, transparent 34px),
    linear-gradient(270deg, var(--green) 0, transparent 34px);
}
.arcade-shelf .gcard:hover { border-color: var(--green-deep); }
.arcade-shelf .gcard:hover::before { opacity: .92; }
.arcade-shelf .gcard > a {
  display: flex;
  flex-direction: column;
  height: 100%;
  text-decoration: none;
  color: inherit;
}
.arcade-shelf .poster {
  display: block;
  aspect-ratio: 16 / 9;
  border-bottom: 1px solid #1E3A2A;
  background: linear-gradient(140deg, #0E1420, #0C121b);
  overflow: hidden;
}
.arcade-shelf .poster img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}
.arcade-shelf .body {
  display: flex;
  flex-direction: column;
  gap: 9px;
  padding: 16px 17px 18px;
  flex: 1;
}
.arcade-shelf .game-genre {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: .16em;
  text-transform: uppercase;
  font-weight: 700;
  color: #7FBF6A;                     /* the arcade's own label ink */
}
.arcade-shelf h3 { margin: 0; font-size: 17px; color: var(--ink); }
.arcade-shelf p { margin: 0; font-size: 14px; color: var(--ink-soft); }
.arcade-shelf .game-go {
  margin-top: auto;
  padding-top: 4px;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--green);
}
/* the section's own button borrows the arcade's green rather than the
   studio's lead, because it leaves this site */
#arcade .btn.ghost { border-color: var(--green-deep); }
#arcade .btn.ghost:hover { border-color: var(--green); color: var(--green); }
/* THE WAITING SLOT WAS DELETED HERE, 2026-09-20. It drew a green ring for an
   arcade game with no card image, so a visitor could tell "not drawn yet" from
   "went wrong". Gortiva's call is that such a game no longer takes a slot at
   all: `shelf_games()` skips it and the next game with art moves up, so the
   selector `.arcade-shelf .poster:not(:has(img))` can no longer match anything
   this generator emits. Dead style, deleted rather than left to be puzzled
   over; git holds it if the rule is ever reversed. */
