/* ------------------------------------------------------------------ fonts */

@font-face {
  font-family: 'Titillium Web';
  src: url(Titillium_Web/TitilliumWeb-Regular.ttf) format('truetype');
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: 'Titillium Web';
  src: url(Titillium_Web/TitilliumWeb-SemiBold.ttf) format('truetype');
  font-weight: 600;
  font-display: swap;
}
@font-face {
  font-family: 'Titillium Web';
  src: url(Titillium_Web/TitilliumWeb-Bold.ttf) format('truetype');
  font-weight: 700;
  font-display: swap;
}
@font-face {
  font-family: 'Titillium Web';
  src: url(Titillium_Web/TitilliumWeb-Black.ttf) format('truetype');
  font-weight: 900;
  font-display: swap;
}

/* ------------------------------------------------------------------ theme */

:root {
  --bg: #17171d;
  --bg-2: #101015;
  --ink: #f4f2f8;
  --ink-dim: #a5a1b5;
  --ink-faint: #6f6b80;

  --pink: #f83fc7;
  --pink-soft: #ff6ad5;
  --teal: #28afb0;
  --deep: #19647e;
  --gold: #f4d35e;
  --orange: #ee964b;
  --mint: #5ce0b0;

  /* One gradient shared by the title and the segmented control */
  --brand-gradient: linear-gradient(96deg, #ff6ad5 0%, #f4d35e 40%, #28afb0 74%, #2f88a8 100%);

  --surface: rgba(255, 255, 255, 0.045);
  --surface-2: rgba(255, 255, 255, 0.08);
  --line: rgba(255, 255, 255, 0.11);

  --radius: 16px;
  --radius-lg: 24px;

  --shadow-lift: 0 18px 40px -18px rgba(0, 0, 0, 0.85);
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  font-family: 'Titillium Web', system-ui, -apple-system, 'Segoe UI', sans-serif;
  font-weight: 400;
  color: var(--ink);
  background: var(--bg);
  background-image:
    radial-gradient(900px 620px at 50% -12%, rgba(248, 63, 199, 0.16), transparent 65%),
    radial-gradient(700px 520px at 100% 8%, rgba(40, 175, 176, 0.13), transparent 62%),
    radial-gradient(760px 560px at 0% 96%, rgba(25, 100, 126, 0.16), transparent 62%),
    linear-gradient(180deg, var(--bg) 0%, var(--bg-2) 100%);
  background-attachment: fixed;
  -webkit-font-smoothing: antialiased;
}

/* The faint background grid that used to live here as a .glow div + rule is
   now the shared "grid-glow" engine effect (Public/effects/grid-glow.css),
   enabled via site.json's "effects" list — a body::before pseudo-element,
   no markup needed. */

.shell {
  position: relative;
  z-index: 1;
  flex: 1;
  width: 100%;
  max-width: 760px;
  margin: 0 auto;
  padding: clamp(2rem, 6vw, 4rem) 1.25rem 3rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(1.75rem, 4vw, 2.5rem);
}

/* -------------------------------------------------------------- masthead */

.masthead { text-align: center; }

.eyebrow {
  margin: 0 0 0.6rem;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.title {
  margin: 0;
  /* Bungee is arcade-signage display type; Titillium Black is the self-hosted
     fallback if Google Fonts can't be reached. */
  font-family: 'Bungee', 'Titillium Web', system-ui, sans-serif;
  font-weight: 400;
  font-size: clamp(1.55rem, 5.4vw, 2.9rem);
  line-height: 1.15;
  letter-spacing: 0;
  background-image: var(--brand-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}

.tagline {
  margin: 0.85rem auto 0;
  max-width: 34ch;
  color: var(--ink-dim);
  font-size: clamp(0.95rem, 2.2vw, 1.05rem);
  line-height: 1.55;
}

/* --------------------------------------------------------------- console */

.console-wrap { perspective: 1200px; }

.console {
  position: relative;
  width: clamp(230px, 52vw, 285px);
  transition: transform 0.5s cubic-bezier(0.2, 0.9, 0.25, 1);
  transform-style: preserve-3d;
  /* Let vertical scrolling through, but keep horizontal drags for the
     history swipe. */
  touch-action: pan-y;
}

.console picture { display: block; }

/* Konami unlock flourish */
.console.unlocked { animation: unlock-pop 0.75s cubic-bezier(0.3, 1.3, 0.4, 1); }

@keyframes unlock-pop {
  0%   { transform: scale(1); filter: none; }
  35%  { transform: scale(1.07) rotate(-2deg); filter: brightness(1.35) saturate(1.5); }
  100% { transform: scale(1); filter: none; }
}

.console-img {
  display: block;
  width: 100%;
  height: auto;
  filter: drop-shadow(0 26px 44px rgba(200, 20, 150, 0.22));
}

/* Matches the glass interior of VideoGame.png (500x640): x 98, y 65, 307x221 */
.screen {
  position: absolute;
  z-index: 2;
  left: 19%;        /*  95 / 500 */
  top: 9.6875%;     /*  62 / 640 */
  width: 62.6%;     /* 313 / 500 */
  height: 35.4688%; /* 227 / 640 */
  border-radius: 7.35% / 10.13%;  /* the frame's own 23px outer curve */
  overflow: hidden;
  /* Name type is sized against the screen itself, so it fits at any console size */
  container-type: size;
  container-name: screen;
  display: flex;
  flex-direction: column;
  padding: 0.7rem 1rem 0.5rem;
  gap: 0.35rem;
  text-align: center;
}

/* Holds the face and the name. Kept as its own flow box so the counter below
   can never be overlapped, descenders included. */
.screen-body {
  position: relative;
  z-index: 2;
  flex: 1 1 auto;
  min-height: 0;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* The screen texture, laid over both the face and the name */
.screen-scanlines {
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  background: repeating-linear-gradient(
    to bottom,
    rgba(30, 10, 40, 0.055) 0px,
    rgba(30, 10, 40, 0.055) 1px,
    transparent 1px,
    transparent 3px
  );
}

/* Hit areas over the printed controls, sized from the artwork (500x640) and
   padded out a little so they stay tappable on a 230px console. */
.pad-hit {
  position: absolute;
  z-index: 4;
  cursor: pointer;
  border-radius: 18%;
  -webkit-tap-highlight-color: transparent;
}
/* A single marker that moves to whichever button is under the pointer, so it's
   obvious what you're about to press. Positioned against the artwork itself, in
   app.js, so the hit areas can be sized independently of the printed buttons. */
.pad-glow {
  position: absolute;
  z-index: 3;
  border-radius: 30%;
  background: #000;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.16s ease, left 0.09s ease, top 0.09s ease,
              width 0.09s ease, height 0.09s ease;
}
.pad-glow.round { border-radius: 50%; }
.pad-glow.hover { opacity: 0.20; }
.pad-glow.press { opacity: 0.38; transition-duration: 0.04s; }

/* Measured from the artwork: d-pad 97..196 x 376..475, the button diamond
   274..406 x 343..475, start/select 212..291 x 545..574 — each padded a little. */
.pad-hit[data-pad="dpad"] { left: 17.8%; top: 57.500%; width: 23.0%; height: 17.97%; }
.pad-hit[data-pad="face"] { left: 53.2%; top: 52.344%; width: 29.6%; height: 23.13%; }
.pad-hit[data-pad="meta"] { left: 40.4%; top: 83.594%; width: 19.8%; height:  7.66%; }

/* The 1997 skin: a second copy of the artwork, recoloured to grey plastic and
   a green LCD, faded in over the default one. Injected by app.js on unlock so
   it costs nothing until then. */
.console-alt {
  position: absolute;
  inset: 0;
  z-index: 1;
  opacity: 0;
  transition: opacity 0.45s ease;
  pointer-events: none;
}
.console-alt img { display: block; width: 100%; height: auto; }
.console.is-1997 .console-alt { opacity: 1; }

.console.is-1997 .screen-glass { background-image: url(screen-blank-1997.png); }
.console.is-1997 .name { color: #16320f; }
.console.is-1997 .screen-hint { color: rgba(22, 50, 15, 0.55); }
.console.is-1997 .tone-stamp {
  background: rgba(10, 26, 6, 0.4);
  border-color: rgba(255, 255, 255, 0.3);
  color: #dff0c2;
}

/* Blank screen plate. Transparent at rest so the artwork's own face shows
   through; fades in to cover it the moment a name is rolled. */
.screen-glass {
  position: absolute;
  inset: 0;
  z-index: 1;
  background-image: url(screen-blank.png);
  /* The plate is an exact crop of the artwork at (95,62), so it must be drawn
     exactly 1:1 — overdrawing it shifts its own frame off the printed one. */
  background-size: 100% 100%;
  background-repeat: no-repeat;
  opacity: 0;
  transition: opacity 0.28s ease;
}

.screen.is-on .screen-glass { opacity: 1; }

/* generated name */
.name {
  position: relative;
  z-index: 1;
  display: block;
  width: 100%;
  font-weight: 900;
  font-size: 1.7rem;                      /* fallback */
  font-size: calc(var(--fit, 16) * 1cqw); /* --fit is measured and set in app.js */
  /* Roomy enough that the line box contains the font's descenders, so a name
     ending in g/y/p can't dip out of the measured height. */
  line-height: 1.14;
  letter-spacing: -0.02em;
  color: #241033;
  text-wrap: balance;
}

/* Last resort only: app.js adds this when even the smallest size can't fit a
   word on one line, so a break mid-word beats text running off the screen. */
.name.break { overflow-wrap: break-word; word-break: break-word; }

/* Empty until a name is rolled, so it needs no hide/show state of its own. */
.name.pop { animation: name-pop 0.42s cubic-bezier(0.2, 1.4, 0.4, 1); }

/* Transform only, on purpose: every frame of this animation is legible, so the
   name can never be left invisible or blurred if the animation doesn't run. */
@keyframes name-pop {
  0%   { transform: translateY(7px) scale(0.88); }
  100% { transform: none; }
}

.screen-hint {
  position: relative;
  z-index: 2;
  flex: none;
  margin: 0;
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(36, 16, 51, 0.42);
}

/* tone chip pinned to the chassis */
.tone-stamp {
  position: absolute;
  left: 50%;
  top: 47%;
  transform: translateX(-50%);
  padding: 0.3em 0.85em;
  border-radius: 999px;
  background: rgba(20, 4, 20, 0.28);
  border: 1px solid rgba(255, 255, 255, 0.28);
  color: #ffe9fa;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  white-space: nowrap;
}

/* ----------------------------------------------------------------- stage */

/* Console, dock and results share one container. That container is the dock's
   sticky containing block, which is what lets the dock stay pinned while you
   scroll the results and then release once you reach the article. */
.stage {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(1.25rem, 3vw, 2rem);
}

.console-wrap { order: 1; }
.kbd-hint     { order: 2; }
.dock         { order: 3; }
.history      { order: 4; }

/* Where the dock genuinely needs to stay put — anything short or narrow enough
   that the page scrolls — lay it out after the results so it has runway to
   remain pinned the whole way down them. */
@media (max-width: 760px), (max-height: 760px) {
  .dock { order: 5; }
}

/* ------------------------------------------------------------------ dock */

/* Sticks to the bottom of the viewport while the generator is on screen. Once
   its natural position scrolls into view it lands and moves with the page, so
   it never hovers over the article below. */
.dock {
  position: sticky;
  bottom: max(0.7rem, env(safe-area-inset-bottom));
  z-index: 5;
  width: 100%;
  max-width: 34rem;
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  padding: 0.6rem;
  border-radius: 26px;
  background: rgba(19, 19, 25, 0.72);
  border: 1px solid rgba(255, 255, 255, 0.14);
  backdrop-filter: blur(20px) saturate(1.5);
  -webkit-backdrop-filter: blur(20px) saturate(1.5);
  box-shadow: 0 20px 45px -20px rgba(0, 0, 0, 0.9),
              inset 0 1px 0 rgba(255, 255, 255, 0.07);
}

/* -------------------------------------------------------- tone selector */

.segmented {
  max-width: 100%;
  padding: 4px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid var(--line);
  /* Clip the scroller to the capsule so chips passing the ends disappear behind
     the curve. clip-path rather than overflow+radius: the scroller is composited
     whenever its fade mask is live, and a composited child can escape a rounded
     overflow clip. */
  overflow: hidden;
  clip-path: inset(0 round 999px);
}

.segmented-scroll {
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.segmented-scroll::-webkit-scrollbar { display: none; }

/* Fade only the side that actually has more content to reach, so an edge is
   never softened when there is nothing hidden beyond it. */
.segmented-scroll.fade-start {
  mask-image: linear-gradient(90deg, transparent 0, #000 26px, #000 100%);
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 26px, #000 100%);
}
.segmented-scroll.fade-end {
  mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 26px), transparent 100%);
  -webkit-mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 26px), transparent 100%);
}
.segmented-scroll.fade-start.fade-end {
  mask-image: linear-gradient(90deg, transparent 0, #000 26px,
                              #000 calc(100% - 26px), transparent 100%);
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 26px,
                              #000 calc(100% - 26px), transparent 100%);
}

.segmented-track {
  position: relative;
  display: flex;
  gap: 2px;
  width: max-content;
  min-width: 100%;
}

/* The thumb doesn't carry its own gradient — it's a moving window onto one
   gradient stretched across the whole track, so the colour a tab lights up in
   depends on where it sits. app.js sets the size/offset to match the track. */
.segmented-thumb {
  position: absolute;
  top: 0;
  left: 0;
  border-radius: 999px;
  background-image: var(--brand-gradient);
  background-repeat: no-repeat;
  background-size: 100% 100%;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.3),
              0 1px 2px rgba(0, 0, 0, 0.28);
  /* Geometry rather than transform, so the moving window and the gradient
     behind it stay locked together through the transition. */
  transition: left 0.32s cubic-bezier(0.3, 1.1, 0.35, 1),
              top 0.32s cubic-bezier(0.3, 1.1, 0.35, 1),
              width 0.32s cubic-bezier(0.3, 1.1, 0.35, 1),
              height 0.32s cubic-bezier(0.3, 1.1, 0.35, 1),
              background-position 0.32s cubic-bezier(0.3, 1.1, 0.35, 1);
}

.segmented-option {
  position: relative;
  z-index: 1;
  appearance: none;
  border: 0;
  background: none;
  cursor: pointer;
  font: inherit;
  font-weight: 600;
  font-size: 0.9rem;
  color: var(--ink-dim);
  min-height: 42px;           /* comfortable touch target */
  padding: 0 1.05em;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  white-space: nowrap;
  /* Grow to share out any spare width so the labels span the whole bar, but
     never shrink below their text — that's what lets the track overflow and
     scroll instead when the tones don't fit. */
  flex: 1 0 auto;
  transition: color 0.2s ease;
}

.segmented-option[aria-checked="true"] { color: #fff; }

/* The unlocked 1997 tone */
.segmented-option.is-secret { color: var(--gold); }
.segmented-option.is-secret[aria-checked="true"] { color: #fff; }
.segmented-option.is-secret::before { content: '★'; margin-right: 0.4em; font-size: 0.85em; }
.segmented-option:focus-visible { outline: 2px solid var(--pink-soft); outline-offset: -3px; }

/* ------------------------------------------------------------ dock actions */

.dock-actions {
  display: flex;
  gap: 0.5rem;
}

/* Pill-shaped to match the tone selector it sits under */
.generate {
  flex: 1 1 auto;
  appearance: none;
  border: 0;
  cursor: pointer;
  font: inherit;
  font-weight: 900;
  font-size: 1.05rem;
  letter-spacing: -0.01em;
  color: #180d16;
  min-height: 50px;
  padding: 0 1.4em;
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6em;
  background-image: var(--brand-gradient);
  background-size: 190% auto;
  background-position: 0% 50%;
  box-shadow: 0 10px 24px -10px rgba(248, 63, 199, 0.75),
              inset 0 1px 0 rgba(255, 255, 255, 0.45);
  transition: background-position 0.55s ease, transform 0.12s ease, box-shadow 0.3s ease;
}

.generate:active { transform: scale(0.985); }
.generate:focus-visible { outline: 3px solid var(--pink-soft); outline-offset: 3px; }

.generate-icon {
  font-size: 1.15em;
  line-height: 1;
  transition: transform 0.45s cubic-bezier(0.3, 1.2, 0.4, 1);
}
.generate.kick .generate-icon { animation: spin 0.55s cubic-bezier(0.3, 1, 0.4, 1); }

@keyframes spin { from { transform: rotate(0turn); } to { transform: rotate(1turn); } }

.ghost {
  flex: none;
  appearance: none;
  cursor: pointer;
  font: inherit;
  font-weight: 600;
  font-size: 0.9rem;
  color: var(--ink-dim);
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--line);
  border-radius: 999px;
  min-height: 50px;
  padding: 0 1.25em;
  transition: color 0.2s ease, border-color 0.2s ease, background 0.2s ease;
}
.ghost:disabled { opacity: 0.4; cursor: not-allowed; }
.ghost:focus-visible { outline: 2px solid var(--pink-soft); outline-offset: 2px; }

/* Keyboard shortcuts only mean something with a keyboard */
.kbd-hint {
  margin: -0.75rem 0 0;
  font-size: 0.82rem;
  color: var(--ink-faint);
}
@media (hover: none), (pointer: coarse) {
  .kbd-hint { display: none; }
}

kbd {
  font: inherit;
  font-size: 0.78em;
  font-weight: 700;
  padding: 0.2em 0.5em;
  border-radius: 6px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink-dim);
}

/* --------------------------------------------------------------- history */

.history {
  width: 100%;
  max-width: 520px;
}

.history-title {
  margin: 0 0 0.75rem;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--ink-faint);
  text-align: center;
}

.history-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.history-item {
  width: 100%;
  appearance: none;
  cursor: pointer;
  font: inherit;
  text-align: left;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.7em 1em;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink-dim);
  transition: color 0.2s ease, background 0.2s ease, border-color 0.2s ease, transform 0.2s ease;
}

.history-item:focus-visible { outline: 2px solid var(--pink-soft); outline-offset: 2px; }

/* The entry currently on the console screen */
.history-item.is-current {
  color: var(--ink);
  background: rgba(255, 106, 213, 0.1);
  border-color: rgba(255, 106, 213, 0.42);
}
.history-item.is-current .history-tone { color: var(--pink-soft); }

/* Plain text, deliberately quiet — it shouldn't compete with Generate */
.history-clear {
  display: block;
  margin: 0.8rem auto 0;
  appearance: none;
  background: none;
  border: 0;
  cursor: pointer;
  font: inherit;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--ink-faint);
  padding: 0.45em 1em;
  border-radius: 999px;
  transition: color 0.2s ease, background 0.2s ease;
}
.history-clear:focus-visible { outline: 2px solid var(--pink-soft); outline-offset: 2px; }

.history-name { font-weight: 600; }

.history-tone {
  flex: none;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* ----------------------------------------------------------------- prose */

/* Selector matches the engine's own ".prose-section .prose" (tokens.css)
   rather than a bare ".prose" — same specificity, so this (loaded after
   tokens.css as extra-css) wins the cascade instead of losing pieces of it
   silently, particularly max-width, which tokens.css also sets. Also adds
   the centering .prose lost when this content moved from inside gamena's
   own flex-centered .shell into a page-level section: without an
   explicit margin, a narrower-than-container block just left-aligns. */
.prose-section .prose {
  width: 100%;
  max-width: 34rem;
  margin: 1.5rem auto 0;
  padding-top: 2.5rem;
  border-top: 1px solid var(--line);
  color: var(--ink-dim);
  font-size: 0.95rem;
  line-height: 1.65;
}

.prose-section .prose h2 {
  margin: 2.25rem 0 0.6rem;
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.prose-section .prose h2:first-child { margin-top: 0; }

.prose-section .prose h3 {
  margin: 1.5rem 0 0.4rem;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--ink);
}

.prose p { margin: 0 0 0.9rem; }
.prose strong { color: var(--ink); font-weight: 600; }
.prose em { color: var(--ink); font-style: normal; opacity: 0.82; }

/* Was ".tone-list" — now the engine's own shared default for any prose
   bullet list (tokens.css ".prose-section .prose ul/li", using the site's
   own --accent instead of a hardcoded pink), so no per-site override is
   needed here any more. */

/* ---------------------------------------------------------------- footer */

.site-footer {
  position: relative;
  z-index: 1;
  padding: 1.5rem 1.25rem calc(1.5rem + env(safe-area-inset-bottom));
  text-align: center;
  font-size: 0.85rem;
  color: var(--ink-faint);
  display: flex;
  gap: 0.6rem;
  justify-content: center;
  align-items: center;
}

.site-footer a {
  color: var(--ink-dim);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color 0.2s ease, border-color 0.2s ease;
}

/* ----------------------------------------------------------------- toast */

.toast {
  position: fixed;
  left: 50%;
  bottom: 1.5rem;
  z-index: 10;
  transform: translate(-50%, 140%);
  max-width: min(90vw, 26rem);
  padding: 0.7em 1.2em;
  border-radius: 999px;
  background: rgba(19, 19, 25, 0.72);
  border: 1px solid rgba(255, 255, 255, 0.14);
  backdrop-filter: blur(20px) saturate(1.5);
  -webkit-backdrop-filter: blur(20px) saturate(1.5);
  box-shadow: var(--shadow-lift);
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--ink);
  opacity: 0;
  transition: transform 0.35s cubic-bezier(0.2, 1.2, 0.3, 1), opacity 0.25s ease;
  pointer-events: none;
  text-align: center;
}

.toast.is-visible { transform: translate(-50%, 0); opacity: 1; }

/* ------------------------------------------------------------ responsive */

/* Hover states only where hovering exists — otherwise iOS latches them on tap */
@media (hover: hover) and (pointer: fine) {
  .console-wrap:hover .console { transform: rotateX(4deg) rotateY(-4deg); }
  .segmented-option:hover { color: var(--ink); }
  .generate:hover {
    background-position: 100% 50%;
    box-shadow: 0 14px 30px -10px rgba(40, 175, 176, 0.7),
                inset 0 1px 0 rgba(255, 255, 255, 0.5);
  }
  .generate:hover .generate-icon { transform: rotate(180deg); }
  .ghost:hover:not(:disabled) {
    color: var(--ink);
    background: var(--surface-2);
    border-color: rgba(255, 255, 255, 0.24);
  }
  .history-item:hover {
    color: var(--ink);
    background: var(--surface-2);
    border-color: rgba(255, 255, 255, 0.22);
    transform: translateX(3px);
  }
  .history-clear:hover {
    color: var(--ink);
    background: var(--surface);
  }
  .site-footer a:hover {
    color: var(--pink-soft);
    border-bottom-color: var(--pink-soft);
  }
}

/* Fingers need more room than the printed buttons give, and there's nothing
   else to hit on the chassis, so the targets grow on touch. */
@media (pointer: coarse) {
  .pad-hit[data-pad="dpad"] { left: 15.0%; top: 55.0%; width: 28.6%; height: 22.3%; }
  .pad-hit[data-pad="face"] { left: 50.6%; top: 49.9%; width: 34.8%; height: 28.0%; }
  .pad-hit[data-pad="meta"] { left: 37.4%; top: 81.2%; width: 25.8%; height: 10.5%; }
}

@media (max-width: 400px) {
  .segmented-option { font-size: 0.85rem; padding: 0 0.85em; }
  .generate { font-size: 1rem; padding: 0 1em; }
  .ghost { padding: 0 1em; }
}

/* Short viewports — small phones — buy back vertical room */
@media (max-height: 700px) {
  .shell { padding-top: 1.5rem; gap: 1.1rem; }
  .tagline, .eyebrow { display: none; }
  /* Floor is deliberately high: below ~220px the screen is too small to show a
     long name at a readable size. */
  .console { width: clamp(220px, 36vh, 250px); }
}

/* Phone landscape. Stacking the console above the dock cannot fit in ~360px of
   height at a legible size, so the two sit side by side instead and the dock
   stops being sticky — everything is on screen at once. */
@media (max-height: 520px) and (min-width: 600px) {
  .shell { padding-top: 0.9rem; gap: 0.7rem; }
  .eyebrow, .kbd-hint { display: none; }
  .title { font-size: clamp(1.2rem, 3.2vw, 1.7rem); }

  .stage {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 1.5rem;
  }
  .console-wrap { order: 1; }
  .dock {
    order: 2;
    position: static;
    flex: 1 1 20rem;
    max-width: 26rem;
  }
  .history { order: 3; width: 100%; }
  .console { width: clamp(170px, 50vh, 205px); }
}

/* Very short and narrow (landscape on a small phone): just tighten up */
@media (max-height: 520px) and (max-width: 599px) {
  .shell { padding-top: 0.9rem; gap: 0.7rem; }
  .eyebrow, .kbd-hint { display: none; }
  .dock { padding: 0.5rem; gap: 0.45rem; }
  .segmented-option { min-height: 38px; }
  .generate, .ghost { min-height: 44px; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .console-wrap:hover .console { transform: none; }
}
