/*
  The home page's own styles (Views/Home.cshtml), on top of site.css: the pitch has sections
  running the full width of the window and motion no other page has, and neither belongs in
  the stylesheet every form loads. Tokens are site.css's; nothing here adds a colour to the
  palette but the bots' three teams, which are data rather than accent.

  Every animation here is off under prefers-reduced-motion. The ones that run on their own,
  in a loop, stop while their section is off screen: js/home.js marks a section in view with
  .is-live, and without the script nothing loops at all.
*/

/* --- frame ----------------------------------------------------------------------- */

main.wide { display: block; }

.shell {
  width: 100%;
  max-width: 72rem;
  margin: 0 auto;
  padding-inline: clamp(1rem, 4vw, 2rem);
}

.section { padding-block: clamp(4rem, 8vw, 6.5rem); }

.section-head { display: flex; flex-direction: column; gap: var(--space-4); max-width: 44rem; }

.section-title {
  font-family: var(--serif);
  font-size: clamp(2rem, 1.3rem + 2.6vw, 3.2rem);
  line-height: 1.08;
  color: var(--cream);
}

.section-lede { font-size: clamp(1rem, .95rem + .25vw, 1.15rem); color: var(--muted); max-width: 38rem; }

.btn-lg { padding: .8rem 1.7rem; font-size: 1.1rem; }
.btn-sm { padding: .3rem .8rem; font-size: .85rem; }

/* Headings slide up into place as they come on screen, driven by the scroll itself rather
   than a script. A browser without scroll-driven animation simply shows them. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .reveal {
      animation: reveal linear both;
      animation-timeline: view();
      animation-range: entry 5% entry 55%;
    }
  }
}
@keyframes reveal { from { opacity: 0; transform: translateY(28px); } }

/* Loops wait for their section to be in view (js/home.js). Only the loops: a one-off
   entrance paused here would leave its element invisible if the script never ran, which is
   also why the upload's list only animates once its section is marked live. The loadout
   tabs turn when their progress line ends, so pausing the line - under the pointer, with
   focus inside, or off screen - pauses the turning. */
.section:not(.is-live) .ping,
.section:not(.is-live) .deck-progress,
.deck:is(:hover, :focus-within) .deck-progress { animation-play-state: paused; }

/* --- hero ------------------------------------------------------------------------ */

.hero {
  display: grid;
  align-items: center;
  min-height: min(calc(100dvh - 3.75rem), 44rem);
  padding-block: clamp(2rem, 5vw, 4rem);
  overflow: clip;
}

.hero-inner {
  display: grid;
  grid-template-columns: minmax(0, 6fr) minmax(0, 5fr);
  align-items: center;
  gap: clamp(1.5rem, 4vw, 4rem);
}

.hero-copy { display: flex; flex-direction: column; gap: var(--space-5); position: relative; z-index: 1; }

.hero-title {
  font-family: var(--serif);
  font-size: clamp(2.6rem, 1.3rem + 3.8vw, 4.5rem);
  line-height: 1.02;
  letter-spacing: -.01em;
  color: var(--cream);
}
.hero-title .line { display: block; }
.hero-title .line:first-child { color: #efe9d8; }
.hero-title .line + .line { color: var(--accent); }

.hero-sub { font-size: clamp(1.05rem, 1rem + .3vw, 1.2rem); color: #b7c3c8; max-width: 30rem; }

.hero-actions { display: flex; flex-wrap: wrap; gap: var(--space-3); margin-top: var(--space-2); }

.hero-light { position: relative; width: 100%; max-width: 34rem; justify-self: center; }

/*
  The recording's edges fade to nothing rather than to black, so it sits on the page with no
  box round it: a mask, since a colour baked into the video to match the page's never quite
  matches once a browser has decoded it.
*/
.hero-video {
  position: relative;
  display: block;
  width: 100%;
  height: auto;
  -webkit-mask-image: radial-gradient(closest-side, #000 45%, rgb(0 0 0 / .55) 72%, transparent 100%);
          mask-image: radial-gradient(closest-side, #000 45%, rgb(0 0 0 / .55) 72%, transparent 100%);
}

/* The light spilling out of the recording onto the page. js/home.js sets --glow from the
   recording's own colour a few times a second; registered, so the change eases. */
@property --glow {
  syntax: "<color>";
  inherits: true;
  initial-value: rgb(206 190 123 / .28);
}
.hero-glow {
  position: absolute;
  inset: -18% -22%;
  background: radial-gradient(closest-side, var(--glow), transparent 75%);
  transition: --glow .6s linear;
  pointer-events: none;
}

@media (prefers-reduced-motion: no-preference) {
  .hero-title .line, .hero-sub, .hero-copy .hero-actions {
    animation: rise .9s var(--ease-out) both;
  }
  .hero-title .line:nth-child(2) { animation-delay: .12s; }
  .hero-sub { animation-delay: .26s; }
  .hero-copy .hero-actions { animation-delay: .38s; }
  .hero-light { animation: ignite 1.8s ease-out .15s both; }
}
@keyframes rise { from { opacity: 0; transform: translateY(18px); } }
@keyframes ignite { from { opacity: 0; filter: brightness(.2); transform: scale(1.04); } }

@media (max-width: 52rem) {
  .hero { min-height: 0; }
  .hero-inner { grid-template-columns: minmax(0, 1fr); }
  .hero-light { max-width: 28rem; margin-top: -1rem; }
}

/* --- realms ---------------------------------------------------------------------- */

/*
  The scenes stay put while the steps beside them scroll past, and show the one for the step
  in view (js/home.js sets data-active).
*/
.realm-story {
  display: grid;
  grid-template-columns: minmax(0, 6fr) minmax(0, 5fr);
  gap: clamp(2rem, 5vw, 5rem);
  margin-top: clamp(2.5rem, 5vw, 4rem);
}

/* The events scene's glow spills past the page's edge on a phone: clipped there rather than
   scrolled to. Clip, not hidden, which would make the section a scroll container and stop
   the stage below sticking. */
.realms { overflow-x: clip; }

/* The whole height under the nav, with the scene in its middle, so the scene's centre is the
   window's centre below the bar - the line each step's text is centred on as it passes. */
.realm-stage {
  position: sticky;
  top: 3.75rem;
  align-self: start;
  height: calc(100vh - 3.75rem);
  display: grid;
  align-items: center;
}

/*
  One scene per step, stacked in one place and shown one at a time (js/home.js sets
  data-active on .scenes). No frame round them: they are pictures of an idea, set straight on
  the page's dark with a pool of the slate's light behind, so none reads as a screen of the
  site or the game. Without the script the first is shown.
*/
.scenes {
  position: relative;
  aspect-ratio: 5 / 4;
  max-height: 30rem;
  display: grid;
  place-items: center;
  background: radial-gradient(closest-side, rgb(46 75 90 / .32), transparent);
}
.scene {
  grid-area: 1 / 1;
  width: 100%;
  display: grid;
  place-items: center;
  gap: var(--space-4);
  opacity: 0;
  transform: translateY(14px) scale(.98);
  transition: opacity .6s var(--ease-out), transform .8s var(--ease-out);
  pointer-events: none;
}
.scenes:not([data-active]) .scene:first-child,
.scenes[data-active="gm"] [data-scene="gm"],
.scenes[data-active="access"] [data-scene="access"],
.scenes[data-active="region"] [data-scene="region"],
.scenes[data-active="rules"] [data-scene="rules"],
.scenes[data-active="event"] [data-scene="event"] { opacity: 1; transform: none; }

/* The GM Commands window itself, as the client draws it at 1536x900. */
.scene-gm { margin: 0; gap: var(--space-2); }
.scene-gm img {
  display: block;
  width: min(100%, 23rem);
  height: auto;
  box-shadow: 0 30px 70px -25px rgb(0 0 0 / .9);
}
.scene-gm figcaption { font-size: .75rem; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }

/* Open or invite only: the one gives way to the other and the code is dealt. */
.scene-access { text-align: center; gap: var(--space-2); }
.access-word { font-family: var(--serif); font-size: clamp(1.6rem, 1.2rem + 1.6vw, 2.4rem); line-height: 1.1; transition: color .6s, opacity .6s; }
.access-open { color: var(--cream); }
.access-private { color: rgb(217 203 162 / .25); }
.scene-access[data-private] .access-open { color: rgb(217 203 162 / .25); text-decoration: line-through; text-decoration-thickness: 1px; }
.scene-access[data-private] .access-private { color: var(--accent); }
.access-code { display: flex; flex-direction: column; align-items: center; gap: .3rem; margin-top: var(--space-5); }
.access-code span { font-size: .75rem; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.access-code b {
  font-family: var(--mono);
  font-weight: 500;
  font-size: clamp(1.4rem, 1.1rem + 1.2vw, 2rem);
  letter-spacing: .18em;
  color: #fffbe0;
  min-height: 1.3em;
}

/* Where it is hosted: the catalogue's regions on a plain lattice of longitude and
   latitude. */
.scene-region { padding-inline: var(--space-2); }
.realm-map { width: 100%; height: auto; overflow: visible; }
.realm-map .graticule { stroke: var(--border); stroke-width: .6; }
.realm-map .dot { fill: var(--muted); r: 3.5; }
.realm-map text { fill: var(--muted); font: 12px "Geist", system-ui, sans-serif; }
.realm-map .is-home .dot { fill: var(--accent); }
.realm-map .is-home text { fill: var(--cream); }
.realm-map .ping { fill: none; stroke: var(--accent); stroke-width: 1; transform-box: fill-box; transform-origin: center; opacity: 0; animation: ping 2.4s ease-out infinite; }
.realm-map .ping-2 { animation-delay: 1.2s; }
@keyframes ping { from { opacity: .9; transform: scale(1); } to { opacity: 0; transform: scale(5); } }

/* The rules: the form's own headings, lit one after another, from classic to yours. */
.rule-words { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; justify-content: center; gap: .6rem .8rem; max-width: 26rem; }
/* Words with a diamond, not boxes: boxed they read as buttons to press. */
.rule-words li {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  padding: .2rem .4rem;
  font-family: var(--serif);
  font-size: clamp(1.05rem, .95rem + .45vw, 1.3rem);
  color: rgb(146 162 169 / .7);
  transition: color .4s;
}
.rule-words li::before {
  content: "";
  width: .45rem;
  height: .45rem;
  border: 1px solid currentColor;
  transform: rotate(45deg);
  transition: background-color .4s;
}
.rule-words li.is-lit { color: var(--cream); }
.rule-words li.is-lit::before { background: var(--accent); border-color: var(--accent); }

/*
  The events, one at a time in one place (js/home.js sets data-pane), over the list that names
  them. A football match, its recording faded at its edges by a mask as the hero's is, with the
  light it throws behind it; then the countdown to a war, in the heading serif and large.
*/
.scene-event { text-align: center; gap: var(--space-3); }
.event-show { display: grid; place-items: center; width: 100%; }
.event-pane {
  grid-area: 1 / 1;
  display: grid;
  place-items: center;
  gap: var(--space-2);
  opacity: 0;
  transition: opacity .7s var(--ease-out);
}
.event-show:not([data-pane]) .event-football,
.event-show[data-pane="football"] .event-football,
.event-show[data-pane="war"] .event-war { opacity: 1; }

.event-football { position: relative; width: min(100%, 27rem); }
.event-video {
  position: relative;
  display: block;
  width: 100%;
  height: auto;
  -webkit-mask-image: radial-gradient(closest-side, #000 50%, rgb(0 0 0 / .55) 76%, transparent 100%);
          mask-image: radial-gradient(closest-side, #000 50%, rgb(0 0 0 / .55) 76%, transparent 100%);
}
/* Larger than the hero's, as the recording's own edge is wider: at the hero's -18% the light
   faded out inside the recording's dark rim and never reached the page. */
.event-glow {
  position: absolute;
  inset: -30% -34%;
  background: radial-gradient(closest-side, var(--glow), transparent 90%);
  transition: --glow .6s linear;
  pointer-events: none;
}

.event-label { font-size: .8rem; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.event-clock { font-family: var(--serif); font-size: clamp(4rem, 3rem + 5vw, 7rem); line-height: 1; color: var(--cream); font-variant-numeric: tabular-nums; }

/* The events, as buttons that choose one, the one showing lit; the last says there are more. */
.event-list {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: baseline;
  gap: var(--space-1) var(--space-2);
  font-size: .8rem;
  color: var(--muted);
}
.event-pick {
  padding: var(--space-2) var(--space-3);
  font: inherit;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--muted);
  background: none;
  border: 0;
  border-bottom: 1px solid transparent;
  cursor: pointer;
  /* Scenes take no pointer (.scene); a hidden one's buttons are inert (js/home.js). */
  pointer-events: auto;
  transition: color .5s, border-color .5s;
}
.event-pick:hover { color: var(--text); }
.event-pick[aria-pressed="true"] { color: var(--accent); border-bottom-color: var(--accent); }
.event-pick:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.event-more { padding-inline: var(--space-2); font-size: .85rem; opacity: .75; }

/* The steps: each tall enough that its scene has a moment on screen. */
/* Each step is centred in a slot of 60vh, and the list is padded so that the first step's
   centre meets the scene's centre just as the scene starts to stick, and the last's just
   before it lets go. */
.realm-steps { list-style: none; margin: 0; padding: calc((100vh - 3.75rem) / 2 - 30vh) 0; }
.realm-step {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--space-3);
  min-height: 60vh;
  padding-block: var(--space-6);
  transition: opacity .5s;
}
.realm-story[data-stepping] .realm-step:not(.is-active) { opacity: .6; }
.realm-step h3 { font-family: var(--serif); font-size: clamp(1.4rem, 1.2rem + .8vw, 1.85rem); color: var(--cream); line-height: 1.15; }
.realm-step p { color: var(--muted); font-size: 1.05rem; max-width: 28rem; }

/*
  On a phone each scene follows its own step - paragraph, picture, paragraph, picture - rather
  than the five pictures stacked above all the text. The stage, the scene stack and the list
  give up their boxes (display: contents), so the steps and the scenes are one column and are
  put in order by `order`; the markup, and so the wide layout, is untouched. Each scene is
  shown whole, and js/home.js plays its motion as it comes into view.
*/
@media (max-width: 54rem) {
  .realm-story { display: flex; flex-direction: column; gap: var(--space-3); }
  .realm-stage, .scenes, .realm-steps { display: contents; }
  .realm-step { min-height: 0; padding-block: var(--space-4) 0; }
  .realm-story[data-stepping] .realm-step:not(.is-active) { opacity: 1; }
  .scene {
    opacity: 1;
    transform: none;
    min-height: 15rem;
    padding: var(--space-5) var(--space-2);
    background: radial-gradient(closest-side, rgb(46 75 90 / .3), transparent);
  }
  [data-step="gm"] { order: 1; }       [data-scene="gm"] { order: 2; }
  [data-step="access"] { order: 3; }   [data-scene="access"] { order: 4; }
  [data-step="region"] { order: 5; }   [data-scene="region"] { order: 6; }
  [data-step="rules"] { order: 7; }    [data-scene="rules"] { order: 8; }
  [data-step="event"] { order: 9; }    [data-scene="event"] { order: 10; }
}

/* --- loadouts -------------------------------------------------------------------- */

.loadouts { background: linear-gradient(180deg, transparent, rgb(46 75 90 / .09) 30%, rgb(46 75 90 / .09) 70%, transparent); }

.deck {
  display: grid;
  grid-template-columns: minmax(12rem, 15rem) minmax(0, 1fr);
  margin-top: clamp(2.5rem, 5vw, 3.5rem);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  corner-shape: bevel;
  overflow: hidden;
  box-shadow: inset 0 1px 0 rgb(226 212 170 / .07);
}

.deck-tabs { display: flex; flex-direction: column; background: var(--well); border-right: 1px solid var(--border); }

.deck-tab {
  position: relative;
  padding: var(--space-4) var(--space-5);
  font: inherit;
  font-family: var(--serif);
  font-size: 1.1rem;
  text-align: left;
  color: var(--muted);
  background: none;
  border: 0;
  border-bottom: 1px solid var(--border);
  cursor: pointer;
  transition: color .3s, background-color .3s;
}
.deck-tab:hover { color: var(--text); }
.deck-tab[aria-selected="true"] { color: var(--cream); background: var(--surface); }
.deck-tab[aria-selected="true"]::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 2px;
  background: var(--accent);
}
.deck-progress {
  position: absolute;
  inset: auto 0 -1px 0;
  height: 1px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
}
/* Longhands, not the shorthand: the shorthand resets animation-play-state, and this rule
   outranks the ones above that pause the line. */
.deck[data-auto] .deck-tab[aria-selected="true"] .deck-progress {
  animation-name: progress;
  animation-duration: var(--deck-ms, 4200ms);
  animation-timing-function: linear;
  animation-fill-mode: both;
}
@keyframes progress { to { transform: scaleX(1); } }

.deck-panels { position: relative; padding: clamp(1.5rem, 3vw, 2.5rem) clamp(1.25rem, 4vw, 3rem); min-height: 18rem; }
.deck-panel { display: flex; flex-direction: column; gap: var(--space-5); }
.deck-panel[hidden] { display: none; }
@media (prefers-reduced-motion: no-preference) {
  .deck-panel { animation: panel-in .6s var(--ease-out) both; }
  .deck-panel .deck-facts > div { animation: rise .6s var(--ease-out) both; }
  .deck-panel .deck-facts > div:nth-child(2) { animation-delay: .06s; }
  .deck-panel .deck-facts > div:nth-child(3) { animation-delay: .12s; }
  .deck-panel .deck-facts > div:nth-child(4) { animation-delay: .18s; }
}
@keyframes panel-in { from { opacity: 0; transform: translateX(14px); } }

.deck-path { font-family: var(--serif); font-size: clamp(1.7rem, 1.3rem + 1.6vw, 2.5rem); line-height: 1.15; color: var(--cream); text-wrap: balance; }

.deck-facts { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) minmax(0, 1fr); gap: var(--space-5) var(--space-6); margin: 0; }
.deck-facts dt { font-size: .75rem; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.deck-facts dd { margin: var(--space-1) 0 0; font-size: 1.05rem; }

.chip {
  display: inline-block;
  width: .95rem;
  height: .95rem;
  margin-right: .5rem;
  vertical-align: -.12em;
  background: var(--chip);
  border: 1px solid rgb(255 255 255 / .25);
  border-radius: 2px;
  corner-shape: bevel;
}

@media (max-width: 44rem) {
  .deck { grid-template-columns: minmax(0, 1fr); }
  .deck-tabs { flex-direction: row; overflow-x: auto; border-right: 0; border-bottom: 1px solid var(--border); scrollbar-width: none; }
  .deck-tab { flex: 0 0 auto; border-bottom: 0; border-right: 1px solid var(--border); padding: var(--space-3) var(--space-4); font-size: 1rem; }
  .deck-tab[aria-selected="true"]::before { inset: auto 0 0 0; width: auto; height: 2px; }
  .deck-facts { grid-template-columns: minmax(0, 1fr); gap: var(--space-4); }
}

/* --- graphics -------------------------------------------------------------------- */

/* The lighting, as the client draws it at night: the wider shot first, the two side by side
   and one above the other on a phone. */
.gallery {
  display: grid;
  grid-template-columns: minmax(0, 3fr) minmax(0, 2.2fr);
  align-items: start;
  gap: var(--space-4);
  margin-top: clamp(2.5rem, 5vw, 3.5rem);
}
.shot { margin: 0; display: flex; flex-direction: column; gap: var(--space-2); }
/* One height for both, cut to fill, so their captions line up. */
.shot img {
  display: block;
  width: 100%;
  height: clamp(13rem, 24vw, 20rem);
  object-fit: cover;
  background: #05080b;
  border: 1px solid var(--border);
  border-radius: 12px;
  corner-shape: bevel;
  box-shadow: 0 30px 60px -30px rgb(0 0 0 / .9);
}
.shot figcaption { font-size: .9rem; color: var(--muted); }
@media (max-width: 44rem) { .gallery { grid-template-columns: minmax(0, 1fr); } .shot img { height: auto; } }

.bento {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-4);
  margin-top: var(--space-4);
}

.bento-cell {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: var(--space-2);
  padding: clamp(1.25rem, 2.5vw, 1.75rem);
  overflow: hidden;
  background: linear-gradient(180deg, rgb(46 75 90 / .14), transparent 10rem), var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  corner-shape: bevel;
  box-shadow: inset 0 1px 0 rgb(226 212 170 / .07);
}
.bento-cell h3 { position: relative; font-family: var(--serif); font-size: 1.45rem; line-height: 1.2; color: var(--cream); }
.bento-cell p { position: relative; color: var(--muted); max-width: 34rem; }

.cell-studio { grid-column: span 2; grid-row: span 2; justify-content: flex-start; }

/* The garment studio: the viewer and its bodies beside the sections and the honeycomb. */
.studio-copy { display: flex; flex-direction: column; gap: var(--space-2); }
.studio {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
  gap: clamp(1rem, 2.5vw, 2rem);
  margin-top: var(--space-5);
}
.studio[hidden] { display: none; }
.studio-view { display: flex; flex-direction: column; gap: var(--space-3); }
/* Vertical swipes scroll the page over it on a phone; across still turns it. */
.studio-canvas { max-width: none; touch-action: pan-y; }
.studio-hint { margin-top: calc(var(--space-2) * -1); }
/* The four bodies under it are .body-grid in site.css. */
.studio-controls { display: flex; flex-direction: column; gap: var(--space-4); }
.studio-comb .honeycomb { max-width: 21rem; margin-inline: auto; }
.studio-shade { display: flex; align-items: center; gap: var(--space-3); }
.studio-shade label { font-weight: 500; font-size: .85rem; color: var(--muted); }
.studio-shade input { flex: 1 1 auto; }
.studio-foot { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: var(--space-3); margin-top: auto; }
.studio-keep { font-size: .95rem; text-decoration: none; }
.studio-keep::after { content: " \2192"; }
.studio-keep:hover { text-decoration: underline; }

/* In game: the editor's palette on a character, the picture on top and the words below it
   rather than laid over it. */
.cell-worn { justify-content: flex-start; padding: 0; margin: 0; }
.cell-worn img {
  display: block;
  width: 100%;
  height: 13rem;
  object-fit: cover;
  object-position: 50% 45%;
  border-bottom: 1px solid var(--border);
}
.cell-worn figcaption { display: flex; flex-direction: column; gap: var(--space-2); padding: clamp(1.25rem, 2.5vw, 1.75rem); }

/* The upload: the maker's files taking their places, then the garment ready. */
.cell-upload { min-height: 17rem; }
.upload-files {
  list-style: none;
  margin: 0 0 auto;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: .4rem;
  font-size: .85rem;
}
.upload-files li {
  display: flex;
  align-items: center;
  gap: .6rem;
  padding: .4rem .6rem;
  background: var(--well);
  border: 1px solid var(--border);
  border-radius: 4px;
  corner-shape: bevel;
}
.file-ext {
  min-width: 2.3rem;
  padding: 0 .3rem;
  font-family: var(--mono);
  font-size: .75rem;
  text-align: center;
  color: var(--accent);
  border: 1px solid rgb(206 190 123 / .4);
  border-radius: 2px;
}
.upload-done { color: var(--ok-text); border-color: #25583a !important; background: var(--ok-bg) !important; }
.upload-done::before { content: "\2713"; font-weight: 700; }
@media (prefers-reduced-motion: no-preference) {
  .is-live .upload-files li { animation: file-in 7s var(--ease-out) infinite both; }
  .upload-files li:nth-child(2) { animation-delay: .5s; }
  .upload-files li:nth-child(3) { animation-delay: 1s; }
  .upload-files li:nth-child(4) { animation-delay: 1.6s; }
}
/* In, held, and out together at the end of the loop. */
@keyframes file-in {
  0% { opacity: 0; transform: translateX(-12px); }
  8%, 80% { opacity: 1; transform: none; }
  92%, 100% { opacity: 0; transform: none; }
}

@media (max-width: 60rem) {
  .bento { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .cell-studio { grid-column: 1 / -1; grid-row: auto; }
}
@media (max-width: 40rem) {
  .bento { grid-template-columns: minmax(0, 1fr); }
  .studio { grid-template-columns: minmax(0, 1fr); }
  /* Smaller, so the picker starts close under it; canvas.garment-viewer in site.css would
     otherwise hold it at 22rem. */
  canvas.studio-canvas { max-width: 15rem; margin-inline: auto; }
  .studio-hint { text-align: center; }
}

/* --- bots ------------------------------------------------------------------------ */

.bots {
  position: relative;
  display: grid;
  align-items: center;
  min-height: clamp(34rem, 78vh, 46rem);
  overflow: hidden;
  border-block: 1px solid var(--border);
  background: radial-gradient(80% 90% at 70% 50%, rgb(46 75 90 / .22), transparent 70%), #060a0e;
}
.bots-canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
.bots::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(90deg, rgb(6 10 14 / .94) 0%, rgb(6 10 14 / .78) 34%, transparent 62%);
  pointer-events: none;
}
.bots-inner { position: relative; z-index: 2; }
.bots-copy { display: flex; flex-direction: column; gap: var(--space-4); max-width: 30rem; }

.bots-legend { list-style: none; margin: var(--space-2) 0 0; padding: 0; display: flex; flex-direction: column; gap: .4rem; font-size: .9rem; color: var(--muted); }
.bots-legend li { display: flex; align-items: center; gap: .6rem; }
.mark { width: .6rem; height: .6rem; transform: rotate(45deg); }
/* The teams: gold for the players, the client's pressed cyan for their bots, and its
   warning red for the other side. The canvas draws in the same three (js/home.js). */
.mark-you { background: #f2d57e; box-shadow: 0 0 8px #f2d57e; }
.mark-bot { background: #39d7ef; }
.mark-foe { background: #ff7050; }

@media (max-width: 44rem) {
  .bots { align-items: start; padding-top: var(--space-6); min-height: 40rem; }
  .bots::before { background: linear-gradient(180deg, rgb(6 10 14 / .95) 0%, rgb(6 10 14 / .8) 42%, transparent 70%); }
}

/* --- the way in ------------------------------------------------------------------ */

.finale { background: radial-gradient(50% 60% at 50% 55%, rgb(206 190 123 / .07), transparent 70%); }
.finale-frame { max-width: 44rem; margin: 0 auto; }
.finale-card { display: flex; flex-direction: column; align-items: center; gap: var(--space-4); padding: clamp(2rem, 5vw, 3.5rem) clamp(1.25rem, 4vw, 3rem); text-align: center; }
.finale-card .hero-actions { justify-content: center; }
