/* ================================================================
   webOS Hub — single-page app
   Super vanilla: plain HTML + CSS + JS, no build step.
   Class names: kebab-case throughout (block-element).
   ================================================================ */

/* ── LG EI brand font (bundled locally for offline use) ───────── */
@font-face {
   font-family: "LG EI";
   font-display: block;
   font-weight: 400;
   font-style: normal;
   src:
      local("LGEI Text Regular"),
      local("LGEIText-Regular"),
      url("../assets/fonts/LG_EI_Text_Regular.woff")
         format("woff");
}
@font-face {
   font-family: "LG EI";
   font-display: block;
   font-weight: 550;
   font-style: normal;
   src:
      local("☺"),
      url("../assets/fonts/LG_EI_Headline_Semibold.woff")
         format("woff");
}
@font-face {
   font-family: "LG EI";
   font-display: block;
   font-weight: 600;
   font-style: normal;
   src:
      local("LGEI Text Semibold"),
      local("LGEIText-Semibold"),
      url("../assets/fonts/LG_EI_Text_SemiBold.woff")
         format("woff");
}
@font-face {
   font-family: "LG EI";
   font-display: block;
   font-weight: 700;
   font-style: normal;
   src:
      local("LGEI Headline Bold"),
      local("LGEIHeadline-Bold"),
      url("../assets/fonts/LG_EI_Headline_Bold.woff")
         format("woff");
}

:root {
   /* Stage never grows past --stage-max. Below that it scales to FIT the
     viewport (16:9 contain), so the whole canvas — including the specs
     buttons — is always visible, even on a mobile browser in landscape,
     with no scroll. (No lower floor: a hard min would overflow small
     screens, which is exactly the "can't reach the buttons" bug.) */
   --stage-max: 1920px;

   /* Background cross-fade duration (room image swaps). Slower = gentler
      image change between categories (avoids the "jumpy" fast swap). */
   --bg-fade: 700ms;

   /* INTERACT zoom clip fade-out: how gently the video melts into the
      front close-up when it ends. Keep playTransition's safety timeout
      (in main.js) longer than this. */
   --clip-fade: 700ms;

   /* Screen geometry — center (x, y) and size (w, h) as % of the stage.
      Single source of truth: each screen's indicator AND its category
      menu derive their position from these. */
   /* Seed = the default room (oled-...-light-on-tv-off). At runtime
      applyGeometry() overrides these on <html> per active background. */
   --tv-x: 27.6%;
   --tv-y: 35.6%;
   --tv-w: 22%;
   --tv-h: 33.5%;
   --tv-rot: 0deg;

   --monitor-x: 84.7%;
   --monitor-y: 40%;
   --monitor-w: 9.6%;
   --monitor-h: 9.5%;
   --monitor-rot: 0deg;
}

/* ── Reset ──────────────────────────────────────────────────── */
*,
*::before,
*::after {
   box-sizing: border-box;
   margin: 0;
   padding: 0;
}

html,
body {
   height: 100%;
   width: 100%;
   overflow: hidden;
   background: #000;
   font-family: "LG EI", "Helvetica Neue", Helvetica, Arial, sans-serif;
}

img {
   user-select: none;
   -webkit-user-drag: none;
}

/* ── App root ───────────────────────────────────────────────── */
.app {
   position: relative;
   width: 100%;
   height: 100%;
}

/* ── Stage ──────────────────────────────────────────────────────
   A centered 16:9 canvas sized to *contain* the whole image: it
   fits entirely inside the viewport and is never cropped (so the
   logo never gets cut off). On non-16:9 screens you simply get
   black bars around it.

     width  = the contain size — min(full width, full height × 16/9),
              capped at --stage-max (no lower floor, so it always fits)
     height = derived from the 16:9 aspect-ratio

   Because the ratio is fixed, any child positioned with left/top in
   % stays anchored to the exact same point of the image everywhere.
   ─────────────────────────────────────────────────────────────── */
.stage {
   position: absolute;
   top: 50%;
   left: 50%;
   transform: translate(-50%, -50%);
   /* Contain-fit the 16:9 canvas, capped at --stage-max. svh = the
      viewport height WITH the mobile browser chrome shown, so the stage
      fits even when the URL bar is visible; the vh line is the fallback
      for browsers without svh. */
   width: min(100vw, 177.7778vh, var(--stage-max));
   width: min(100vw, 177.7778svh, var(--stage-max));
   aspect-ratio: 16 / 9;
   overflow: hidden;
   background: #000;
   /* Query container so elements can size with the stage width (cqw):
      1cqw = 1% of the stage's width. */
   container-type: inline-size;
}

/* Two stacked layers, cross-faded by js/main.js (bgFader). Layers rest
   at opacity 0; the visible one is opacity 1. The incoming image always
   sits fully opaque under the outgoing one while it fades, so a swap
   never reveals the (#000) stage behind — no white/black flash. */
.stage-bg {
   position: absolute;
   inset: 0;
   width: 100%;
   height: 100%;
   object-fit: cover; /* image is 16:9, so this fits exactly — no distortion */
   pointer-events: none;
   opacity: 0;
   z-index: 0;
   transition: opacity var(--bg-fade) ease;
}
/* The layer painted on first load, before main.js takes over. */
.stage-bg--current {
   opacity: 1;
   z-index: 1;
}

/* INTERACT zoom-in clip. Sits above the bg layers + room UI but below the
   specs drawer (z 15), so the drawer can slide in over it as it fades. It
   turns ON instantly (no transition → frame 0 lands exactly on the room bg
   already showing, no flash), and only the fade-OUT is animated, revealing
   the front image set underneath. main.js toggles the classes. */
.stage-video {
   position: absolute;
   inset: 0;
   width: 100%;
   height: 100%;
   object-fit: cover; /* 16:9 clip in a 16:9 stage → exact, no distortion */
   pointer-events: none;
   opacity: 0;
   z-index: 13;
}
.stage-video.is-playing {
   opacity: 1;
}
.stage-video.is-fading {
   opacity: 0;
   transition: opacity var(--clip-fade, 700ms) ease;
}

/* Overlay shares the stage's 0–100% coordinate space, so hotspots
   line up perfectly with the image. */
.stage-overlay {
   position: absolute;
   inset: 0;
}

/* Logo anchored to the image's bottom-right corner (scales with it). */
.stage-logo {
   position: absolute;
   right: 2.2%;
   bottom: 3.2%;
   width: 11%;
   height: auto;
   z-index: 10;
   pointer-events: none;
}

/* ── Indicator (pulsing frame over a clickable screen) ─────────
   Anchored over a screen, in % of the stage so it stays locked to the
   image and scales with it. Each one is its SVG (assets/*-indicator.svg)
   stretched to the screen's box — the box matches the SVG's aspect, so
   the corners + connecting lines land on the screen with no distortion.
   The whole frame pulses as a "click here" cue.
   ─────────────────────────────────────────────────────────────── */
.indicator {
   position: absolute;
   /* --rot lets a screen tilt its frame to match the TV's wall angle
      (set per screen below; driven per-bg by applyGeometry in JS). */
   transform: translate(-50%, -50%) rotate(var(--rot, 0deg));
   padding: 0;
   border: none;
   background: none;
   cursor: pointer;
   z-index: 5;
   filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.55));
   transition: opacity 220ms ease;
}

/* One rule per screen: center (left/top) + size (width/height) + tilt.
   The geometry vars are rewritten per active background by JS. */
.indicator--tv {
   left: var(--tv-x);
   top: var(--tv-y);
   width: var(--tv-w);
   height: var(--tv-h);
   --rot: var(--tv-rot, 0deg);
}
.indicator--monitor {
   left: var(--monitor-x);
   top: var(--monitor-y);
   width: var(--monitor-w);
   height: var(--monitor-h);
   --rot: var(--monitor-rot, 0deg);
}

.indicator-frame {
   display: block;
   width: 100%;
   height: 100%;
   object-fit: fill; /* stretch the SVG to the box (aspects match) */
   transform-origin: center;
   animation: indicator-pulse 1.8s ease-in-out infinite;
}

@keyframes indicator-pulse {
   0%,
   100% {
      transform: scale(1);
      opacity: 0.6;
   }
   50% {
      transform: scale(1.1);
      opacity: 1;
   }
}

@media (prefers-reduced-motion: reduce) {
   .indicator-frame {
      animation: none;
   }
}

/* Indicator fades out while its menu is open / on the specs screen
   (the mockups show the menu without the brackets). Keep pointer-events
   enabled so the hover-to-open flow doesn't flicker: with the menu open
   the indicator is invisible but the cursor still resting on its box
   keeps firing mouseenter, which cancels the soft-close timer. Killing
   pointer-events here would cycle mouseleave → close → restore →
   mouseenter → open ad infinitum while the cursor stays put. */
.indicator--off {
   opacity: 0;
}

/* While the welcome overlay is up, the indicators shouldn't pulse behind
   it. The overlay toggles the `hidden` attribute, so hide the indicators
   whenever a visible .welcome exists. They fade back in (the .indicator
   opacity transition) when the overlay is dismissed. */
.app:has(.welcome:not([hidden])) .indicator {
   opacity: 0;
}

/* Pre-paint guard against the "flash of room UI" when the user deep-links
   to /emulator/emulator-INT/tv/ or /emulator/emulator-INT/monitor/. The inline <head> script sets
   `route-specs` on <html> before the first paint; until main.js runs and
   applies its own classes, indicators / on-screen CTA / logo would all
   render briefly. Hiding them here keeps the boot quiet — main.js doesn't
   need to touch any of these (its own indicator--off / hidden flags take
   over for the rest of the specs session). */
html.route-specs .indicator,
html.route-specs .ind-frame,
html.route-specs .stage-logo,
html.route-specs .screen-cta {
   visibility: hidden;
}
/* The welcome now starts visible in the HTML (so the room indicators are
   hidden from the first paint — no flash). On a specs deep-link there's
   no gate, so drop it pre-paint via the route class set in <head>. */
html.route-specs .welcome {
   display: none;
}

/* ── Indicator frames (SVG, drawn from 4 corner points) ────────
   The .indicator buttons above are the (invisible) hit areas; these
   SVG frames are the visible brackets + outline, drawn by main.js from
   each screen's corner points so they match the tilted screen exactly.
   pointer-events:none so they never block the buttons. Their visibility
   mirrors the buttons' (menu open / welcome up / specs route). */
.indicator-frames {
   position: absolute;
   inset: 0;
   width: 100%;
   height: 100%;
   pointer-events: none;
   z-index: 5;
   overflow: visible;
}
.ind-frame {
   filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.55));
   transition: opacity 220ms ease;
}
.ind-frame-outline {
   fill: none;
   stroke: rgba(255, 255, 255, 0.85);
   stroke-width: 1;
}
.ind-frame-bracket {
   fill: none;
   stroke: #fff;
   stroke-width: 3;
   stroke-linecap: butt;
   stroke-linejoin: miter;
}
.ind-frame-pulse {
   transform-box: fill-box;
   transform-origin: center;
   animation: indicator-pulse 1.8s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) {
   .ind-frame-pulse {
      animation: none;
   }
}
/* Mirror the buttons' hide states onto the matching frames. */
#indicators:has(.indicator--tv.indicator--off) .ind-frame--tv,
#indicators:has(.indicator--monitor.indicator--off) .ind-frame--monitor {
   opacity: 0;
}
.app:has(.welcome:not([hidden])) .ind-frame {
   opacity: 0;
}
/* Debug: while guides are on, keep frames visible everywhere so any room
   can be tuned (overrides the welcome / menu / specs hide rules). */
.indicator-frames[data-guides] .ind-frame {
   opacity: 1 !important;
   visibility: visible !important;
}
/* ...and freeze the pulse so the frame sits exactly on the corners. */
.indicator-frames[data-guides] .ind-frame-pulse {
   animation: none;
}

/* Debug toolbar to switch backgrounds while tuning (shown with guides). */
.geo-toolbar {
   position: fixed;
   top: 8px;
   left: 50%;
   transform: translateX(-50%);
   z-index: 9999;
   display: flex;
   flex-wrap: wrap;
   gap: 6px;
   max-width: 96vw;
   padding: 6px 8px;
   background: rgba(0, 0, 0, 0.72);
   border-radius: 8px;
   font-family: monospace;
}
.geo-toolbar[hidden] {
   display: none;
}
.geo-toolbar button {
   padding: 4px 8px;
   border: 1px solid #555;
   border-radius: 5px;
   background: #222;
   color: #fff;
   cursor: pointer;
   font: inherit;
   font-size: 12px;
}
.geo-toolbar button:hover {
   background: #444;
}
.geo-toolbar button.is-active {
   background: #91025b;
   border-color: #c2185b;
}

/* Live readout for emulator placement tuning (emulatorTune()). */
.emu-tune-readout {
   position: fixed;
   top: 8px;
   left: 8px;
   z-index: 10000;
   padding: 6px 10px;
   background: rgba(0, 0, 0, 0.78);
   color: #36e07f;
   border-radius: 8px;
   font-family: monospace;
   font-size: 13px;
   letter-spacing: 0.02em;
   pointer-events: none;
   white-space: nowrap;
}
.emu-tune-readout[hidden] {
   display: none;
}

/* Draggable corner guides (debug: ?guides / toggleIndicatorGuides()). */
.ind-guide {
   fill: rgba(255, 64, 64, 0.9);
   stroke: #fff;
   stroke-width: 2;
   pointer-events: auto;
   cursor: grab;
}
.ind-guide:active {
   cursor: grabbing;
}

/* ── Category menus (revealed on indicator click) ──────────────
   A stack of pills positioned next to a screen. On open they scale up
   from the screen side (transform-origin) while fading in — so they
   look like they grow out of the TV / monitor.
   ─────────────────────────────────────────────────────────────── */
.categories {
   position: absolute;
   z-index: 6;
   display: flex;
   flex-direction: column;
   align-items: flex-start;
   gap: 0.6em;
   opacity: 0;
   visibility: hidden;
   /* translateY(-50%) keeps the stack vertically centered on the screen
      (top is set to the screen's center y); scale drives the animation. */
   transform: translateY(-50%) scale(0.35);
   transition:
      opacity 280ms ease,
      transform 340ms cubic-bezier(0.2, 0.85, 0.25, 1),
      visibility 0s linear 340ms;
}
.categories.is-open {
   opacity: 1;
   visibility: visible;
   transform: translateY(-50%) scale(1);
   transition:
      opacity 280ms ease,
      transform 340ms cubic-bezier(0.2, 0.85, 0.25, 1);
}
/* On a category switch the menu's anchor (--tv-* / --monitor-*) jumps to
   the new room's screen geometry. To avoid the teleport, main.js fades
   the open menu out (this class), lets it reposition while invisible,
   then fades it back in — same idea as the INTERACT button. Stays
   hoverable (no pointer-events change) so it doesn't auto-close. */
.categories.is-open.is-repositioning {
   opacity: 0;
}

/* TV menu sits just to the right of the TV (derived from --tv-* vars),
   vertically centered on it, and grows out of its left side.
   left = TV right edge (--tv-x + --tv-w/2) + a small gap. */
.categories--tv {
   left: calc(var(--tv-x) + var(--tv-w) / 2 + 1%);
   top: var(--tv-y);
   transform-origin: left center;
}
/* Monitor menu sits just to the left of the monitor, grows out of its
   right side. right = stage right − monitor left edge + gap. */
.categories--monitor {
   right: calc(100% - var(--monitor-x) + var(--monitor-w) / 2 + 1%);
   top: var(--monitor-y);
   transform-origin: right center;
}

.category {
   display: flex;
   justify-content: center;
   align-items: center;
   gap: 0.417cqw; /* 8px @ 1920 stage */
   align-self: stretch; /* all pills take the width of the widest one */
   padding: 0.45cqw 1.25cqw; /* ~8.6px 24px @ 1920 stage — sits a bit taller than the 42px INTERACT btn */
   border: 1px solid #8e0058;
   border-radius: 99px;
   background: rgba(55, 0, 34, 0.6);
   box-shadow: 0 8px 24px 0 rgba(255, 0, 158, 0.05);
   -webkit-backdrop-filter: blur(2px);
   backdrop-filter: blur(2px);
   color: #fff;
   leading-trim: both;
   text-edge: cap;
   font-family: "LG EI", sans-serif;
   font-size: 1.667cqw; /* 32px @ 1920 stage; scales with the stage */
   font-style: normal;
   font-weight: 700;
   line-height: normal;
   white-space: nowrap;
   cursor: pointer;
   transition:
      background-color 160ms ease,
      border-color 160ms ease;
}
.category:hover,
.category:focus-visible,
.category.is-selected {
   background: #91025b;
   outline: none;
}

/* CTA centered on the active screen (reuses .cta-button). Shown by JS
   once a category is chosen; .on-tv / .on-monitor place it over the
   right screen using the shared --tv-* / --monitor-* vars. */
.screen-cta {
   position: absolute;
   transform: translate(-50%, -50%);
   z-index: 7;
   /* Fades in only after the "TV on" room image has landed (main.js adds
      .is-revealed on a timer matched to --bg-fade), and fades out when
      the selection clears. */
   opacity: 0;
}
.screen-cta.is-revealed {
   opacity: 1;
}
/* Pulsing glow to draw the eye once the CTA lands on the screen. The
   expanding rings ride the button's pill radius (box-shadow follows
   border-radius). Spread is in cqw so it scales with the room like the
   rest of the CTA (px equivalents at the 1920 stage noted inline).
   Two saved variants — pick one by putting the matching class on the
   button in index.html (cta-pulse--white is active today):
      cta-pulse--white → neutral white halo
      cta-pulse--red   → light-red halo (rgba(255,105,105)), the button's
                         own red lightened so it reads apart from the fill */
.screen-cta.is-revealed.cta-pulse--white {
   animation: cta-pulse-white 2s infinite;
}
.screen-cta.is-revealed.cta-pulse--red {
   animation: cta-pulse-red 2s infinite;
}
@keyframes cta-pulse-white {
   0% {
      box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.85);
   }
   70% {
      box-shadow: 0 0 0 0.9375cqw rgba(255, 255, 255, 0); /* 18px */
   }
   100% {
      box-shadow: 0 0 0 3.6458cqw rgba(255, 255, 255, 0); /* 70px */
   }
}
@keyframes cta-pulse-red {
   0% {
      box-shadow: 0 0 0 0 rgba(255, 105, 105, 0.85);
   }
   70% {
      box-shadow: 0 0 0 0.9375cqw rgba(255, 105, 105, 0); /* 18px */
   }
   100% {
      box-shadow: 0 0 0 3.6458cqw rgba(255, 105, 105, 0); /* 70px */
   }
}
/* The CTA never glides between screens — on a category change it fades
   out, the bg swaps, and it fades back in at the new screen's center
   (main.js repositions it while it's invisible). So only opacity (+ the
   hover bg/color) animates; left/top jump instantly while hidden. */
.cta-button.screen-cta {
   /* In-stage CTA → cqw so it scales with the room instead of staying a
      fixed 42px (which looks huge once the stage scales down on mobile).
      Resolves to the original 42/24/32/16px at the 1920 stage. */
   height: 2.1875cqw; /* 42px */
   padding: 0 1.25cqw; /* 24px */
   border-radius: 1.667cqw; /* 32px */
   font-size: 0.8333cqw; /* 16px */
   transition:
      opacity 300ms ease,
      background-color 160ms ease,
      color 160ms ease;
}
.screen-cta.on-tv {
   left: var(--tv-x);
   top: var(--tv-y);
}
.screen-cta.on-monitor {
   left: var(--monitor-x);
   top: var(--monitor-y);
   /* The monitor is small, so shrink the CTA (overrides .cta-button). */
   height: 1.4583cqw; /* 28px */
   padding: 0 0.7292cqw; /* 14px */
   font-size: 0.5729cqw; /* 11px */
}
/* .cta-button sets display:inline-flex, which would override the UA
   [hidden] rule — restore it so the button can be hidden. */
.screen-cta[hidden] {
   display: none;
}

/* ── Back button (top-left of the stage / room image) ─────────── */
.back-btn {
   position: absolute;
   top: 1.667cqw; /* 32px @ 1920 stage */
   left: 1.667cqw;
   width: 2.188cqw; /* 42px @ 1920 stage */
   height: 2.188cqw;
   padding: 0;
   border: none;
   background: none;
   cursor: pointer;
   /* Above the drawer (z 30) and the emulator mount (z 20) so the back
      button stays clickable in every view, including in-place emulator. */
   z-index: 35;
   transition: opacity 160ms ease;
}
.back-btn[hidden] {
   display: none;
}
.back-btn img {
   display: block;
   width: 100%;
   height: 100%;
}
.back-btn:hover,
.back-btn:focus-visible {
   opacity: 0.8;
   outline: none;
}

/* ── Specs drawer (slides in from the right on the specs view) ──
   Sizes scale with the stage (cqw). Body is rendered from CONFIG.
   ─────────────────────────────────────────────────────────────── */
.specs {
   position: absolute;
   top: 0;
   right: 0;
   height: 100%;
   width: 31.25cqw; /* 600px @ 1920 */
   max-width: 600px;
   /* Drawer sits OVER the in-place emulator (z 20) so the slide-out
      reveals the emulator that was pre-mounted underneath when the
      user entered the specs view. See css/emulator.css for the stack. */
   z-index: 30;
   transform: translateX(100%);
   visibility: hidden;
   transition:
      transform 380ms cubic-bezier(0.2, 0.85, 0.25, 1),
      visibility 0s linear 380ms;
   border-radius: 32px 0 0 32px;
   border: 1px solid rgba(255, 255, 255, 0.4);
   background: rgba(41, 41, 41, 0.8);
   box-shadow: 0 0.501px 12.022px -0.501px rgba(0, 0, 0, 0.18);
   -webkit-backdrop-filter: blur(50px);
   backdrop-filter: blur(50px);
}
.specs.is-open {
   transform: translateX(0);
   visibility: visible;
   transition: transform 380ms cubic-bezier(0.2, 0.85, 0.25, 1);
}

.specs-body {
   height: 100%;
   overflow-y: auto;
   scrollbar-width: none; /* Firefox: hide the scrollbar (still scrolls) */
   display: flex;
   flex-direction: column;
   align-items: stretch;
   gap: 1.667cqw; /* 32px */
   padding: 3cqw 1.667cqw; /* ~58px 32px */
}
/* Hide the scrollbar in WebKit/Blink too (scroll still works). */
.specs-body::-webkit-scrollbar {
   display: none;
}

.specs-title {
   color: #f33;
   text-align: center;
   font-family: "LG EI";
   font-size: 1.667cqw; /* 32px */
   font-style: normal;
   font-weight: 700;
   line-height: normal;
   font-feature-settings:
      "liga" off,
      "clig" off;
   /* leading-trim / text-edge aren't supported by browsers yet — kept for
      parity with the design spec; ignored at runtime. */
   leading-trim: both;
   text-edge: cap;
}
.specs-copy {
   color: #fff;
   font-size: 1.042cqw; /* 20px */
   font-weight: 400;
   line-height: normal;
}

/* UHD only: the version badge + tier table share one dark card, split by a
   horizontal rule (.specs-rule). Other categories just render .specs-badges. */
.specs-spec-card {
   display: flex;
   flex-direction: column;
   gap: 1.25cqw; /* 24px */
   padding: 1.25cqw; /* 24px */
   border-radius: 0.833cqw; /* 16px */
   background: rgba(20, 20, 20, 0.55);
}
/* Inside the card the version is just centered text — the card supplies the
   dark background, so the inner badge drops its own pill styling. */
.specs-spec-card .specs-badge {
   background: transparent;
   padding: 0;
}

/* Badges under the title: one column per SKU. The platform version sits in
   a dark rounded pill; its GB/Hz spec is centered directly BELOW the pill.
   Columns sit side by side. */
.specs-badges {
   display: flex;
   flex-wrap: nowrap;
   align-items: stretch;
   width: 100%;
   gap: 0.833cqw; /* 16px between columns */
}
.specs-badge {
   /* The whole badge is the dark pill now — version + GB/Hz stacked inside it.
      flex:1 so a single badge fills the row and two badges split it evenly,
      each taking half the full width. */
   flex: 1;
   display: flex;
   flex-direction: column;
   align-items: center;
   justify-content: center;
   gap: max(0.4167cqw, 8px); /* >= 8px between the version line and the spec line */
   padding: max(0.833cqw, 16px) 1.042cqw; /* >=16px top/bottom, 20px sides */
   border-radius: 0.833cqw; /* 16px */
   background: rgba(20, 20, 20, 0.55);
}
.specs-badge-version {
   color: #ece7dd;
   font-family: "LG EI";
   font-size: 1.0417cqw; /* 20px @ 1920 stage */
   font-weight: 700;
   font-feature-settings: "liga" off, "clig" off;
   line-height: normal;
   white-space: nowrap;
}
.specs-badge-spec {
   color: #fff;
   font-family: "LG EI";
   font-size: 1.0417cqw; /* 20px @ 1920 stage */
   font-feature-settings: "liga" off, "clig" off;
   line-height: normal;
   white-space: nowrap;
   text-align: center;
}

/* Tier table (UHD TV only): 3 columns split by vertical dividers. Each
   column = a purple name pill, a memory/refresh value, and 0+ image
   badges (MEMC / Dolby). */
.specs-tiers {
   display: flex;
   align-items: stretch;
   gap: 0.885cqw; /* 17px */
}
.specs-tier {
   flex: 1;
   display: flex;
   flex-direction: column;
   align-items: flex-start;
   gap: 0.885cqw; /* 17px */
}
.specs-tier-name {
   align-self: center; /* center the pill horizontally in its column */
   display: inline-flex;
   align-items: center;
   justify-content: center;
   /* All-caps text sits high in its line box (the empty descender space
      is below the caps), so line-height:1 alone reads as "pushed up".
      The top padding is ~2px more than the bottom to nudge the caps to
      the optical center. Total vertical padding ≈ the intended 8px. */
   padding: 0.52cqw 0.8333cqw 0.3125cqw; /* 10px / 16px / 6px */
   border-radius: 99px;
   font-size: 1.0417cqw; /* 20px */
   font-weight: 700;
   line-height: 1;
   color: #fff;
   background: #9577cf;
}
.specs-tier-value {
   color: #fff;
   font-size: 1.0417cqw; /* 20px */
   font-weight: 600;
}
.specs-tier-badges {
   align-self: center; /* logos centered in the column */
   display: flex;
   align-items: center;
   gap: 0.469cqw; /* 9px between logos */
   min-height: 1.25cqw; /* keep rows aligned even when a tier has no badges */
}
.specs-tier-badge {
   width: auto;
   height: auto;
   display: block;
}
.specs-tier-badge[src*="memc"] {
   max-width: 2.292cqw; /* 44px */
}
.specs-tier-badge[src*="dolby"] {
   max-width: 2.76cqw; /* 53px */
}
.specs-divider {
   width: 1px;
   align-self: stretch;
   background: rgba(255, 255, 255, 0.25);
}
/* Horizontal rule separating the version/tier section from Features. */
.specs-rule {
   /* Never let the scrolling flex column shrink the 1px line to 0. */
   flex-shrink: 0;
   height: 1px;
   background: rgba(255, 255, 255, 0.16);
}

/* Features: label + wrapping pills. */
.specs-features {
   display: flex;
   flex-direction: column;
   gap: 0.83cqw;
}
.specs-features-label {
   border-radius: 0.833cqw; /* 16px */
   background: #ece7dd;
   padding: 0.833cqw 1.042cqw; /* 16px 20px */
   color: #000;
   text-align: center;
   font-family: "LG EI";
   font-size: 1.0417cqw; /* 20px */
   font-style: normal;
   font-weight: 700;
   font-feature-settings:
      "liga" off,
      "clig" off;
   line-height: normal;
}
.specs-feature-list {
   display: flex;
   flex-wrap: wrap;
   gap: 0.42cqw;
}
.specs-feature {
   /* Content-sized pills: each is only as wide as its text + padding — they no
      longer grow to fill the row (rows still wrap naturally by content length).
      Re-enable the flex below to make each row stretch full-width again. */
   /* flex: 1 1 auto; */
   display: flex;
   height: 3.8cqw; /* ~73px */
   padding: 0 1.4cqw; /* ~27px horizontal; height handles the vertical */
   justify-content: center;
   align-items: center;
   gap: 0.417cqw;
   border-radius: 0.833cqw; /* 16px */
   background: rgba(255, 255, 255, 0.2);
   background-blend-mode: luminosity;
   color: #fff;
   font-size: 0.9375cqw; /* 18px */
   font-weight: 600;
   line-height: normal;
   cursor: default; /* not the text I-beam */
   user-select: none;
   transition:
      background-color 160ms ease,
      box-shadow 160ms ease;
}
.specs-feature:hover {
   background: rgba(255, 255, 255, 0.28);
   box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}

/* Feature pills that deep-link into the v3 simulator topic are rendered
   as <button> (see renderSpecs). Strip the native button chrome so they
   match the plain <span> pills, then swap the default cursor for a
   pointer + a stronger hover so they read as clickable links. */
button.specs-feature {
   box-sizing: border-box;
   border: 0;
   margin: 0;
   font-family: inherit;
   appearance: none;
   -webkit-appearance: none;
}
.specs-feature--link {
   cursor: pointer;
}
.specs-feature--link:hover {
   background: rgba(255, 255, 255, 0.34);
   box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
}
.specs-feature--link:focus-visible {
   outline: 0.1042cqw solid #f33; /* 2px @ 1920 stage — matches the red accent */
   outline-offset: 0.1042cqw;
}

.specs-actions {
   display: flex;
   flex-wrap: wrap; /* never overflow the drawer — stack if too narrow */
   gap: 0.83cqw;
}
/* EMULATOR / SIMULATOR live INSIDE the stage (a cqw query container), so
   size them in cqw to scale with the drawer — the base .cta-button px
   would stay fixed and blow out / overflow when the stage scales down
   (mobile). At the 1920 stage these resolve to the original 42/24/32/16px. */
.cta-button.specs-action {
   height: 2.1875cqw; /* 42px */
   padding: 0 1.25cqw; /* 24px */
   border-radius: 1.667cqw; /* 32px */
   font-size: 0.8333cqw; /* 16px */
}

/* ── Views layer (JS-mounted panels / modals) ─────────────────── */
.views {
   position: absolute;
   inset: 0;
   z-index: 20;
   pointer-events: none; /* re-enabled by individual views when shown */
}
.views:empty {
   display: none;
}

/* ── Welcome overlay (shown on every load) ─────────────────────
   Centers a frosted-glass panel over the welcome background image
   (lights off, TV on) — the bg itself is already dark enough, so no
   extra backdrop dim.
   ─────────────────────────────────────────────────────────────── */
.welcome {
   position: fixed;
   inset: 0;
   z-index: 100;
   display: flex;
   align-items: center;
   justify-content: center;
   padding: 48px;
}
.welcome[hidden] {
   display: none;
}

.welcome-panel {
   display: flex;
   flex-direction: column;
   align-items: center;
   gap: 32px;
   padding: 40px;
   width: min(550px, 100%);
   max-height: 100%;
   border-radius: 32px;
   border: 1px solid rgba(255, 255, 255, 0.1);
   background: rgba(128, 128, 128, 0.3);
   background-blend-mode: luminosity;
   box-shadow: 0 0.501px 12.022px -0.501px rgba(0, 0, 0, 0.18);
   -webkit-backdrop-filter: blur(50px);
   backdrop-filter: blur(50px);
}

/* Reserve the logo's rendered height (logo is 397×66 → ×66/397) so the
   panel doesn't shift when the image loads slowly. Tracks the img width
   clamp below. */
.welcome-logo {
   min-height: clamp(19.95px, 2.328vw, 29.93px);
}
.welcome-logo img {
   display: block;
   width: clamp(120px, 14vw, 180px);
   height: auto;
}

.welcome-copy p {
   margin: 0;
   max-width: 46ch;
   text-align: center;
   color: rgba(255, 255, 255, 0.92);
   font-size: clamp(15px, 1.1vw, 18px);
   line-height: 1.6;
}

/* ── CTA button (reusable LG button) ───────────────────────────
   Default: red fill, white text. Hover/focus: inverts to white
   fill, red text. Use .cta-button on any <button>/<a>.
   (leading-trim / text-edge aren't supported by browsers yet —
   kept for parity with the design spec; they're ignored.)
   ─────────────────────────────────────────────────────────────── */
.cta-button {
   /* Height is fixed at 42px (with flex centering) instead of relying
      on 16px vertical padding: browsers lack leading-trim/text-edge,
      so the full line-height would make it ~50px. Horizontal padding
      (24px) is kept. */
   display: inline-flex;
   align-items: center;
   justify-content: center;
   height: 42px;
   padding: 0 24px;
   border: none;
   border-radius: 32px;
   background: #f33;
   color: #fff;
   text-align: center;
   leading-trim: both;
   text-edge: cap;
   font-feature-settings:
      "liga" off,
      "clig" off;
   font-family: "LG EI", sans-serif;
   font-size: 16px;
   font-style: normal;
   font-weight: 700;
   line-height: normal;
   letter-spacing: 0.08em;
   cursor: pointer;
   transition:
      background-color 160ms ease,
      color 160ms ease;
}
/* Hover inverts to white fill + red text. */
.cta-button:hover {
   background: #fff;
   color: #f33;
}
/* Keyboard focus keeps the red fill and shows a focus ring. */
.cta-button:focus-visible {
   outline: 3px solid #fff;
   outline-offset: 3px;
}
