/* =====================================================================
   Valorafy — studio chrome, shared by BOTH studios

     /widget   widget.html   + estudio/widget-studio.js
     /informe  informe.html  + estudio/informe-studio.css + informe-studio.js

   App chrome for the demo pages. Loads AFTER styles.css and borrows its
   tokens (navy, green, Manrope, radii) so a studio reads as Valorafy —
   but it is a full-height, non-scrolling app layout, not a marketing
   page, so it overrides body's document behaviour deliberately.

   This was `widget-studio.css` at the repo root until 2026-09-20. Both
   studios now wear the same header, rail, controls and drawer, and a
   visitor switches between them from the header — two hand-kept copies of
   that chrome would have drifted within a session, and the drift would
   have shown, because the switch puts the two headers one click apart.

   The one part that is NOT shared is the stage: from `.stage-frame` down
   to the end of that section everything belongs to /widget alone (the
   browser-window mock, the device sizes, the iframe backdrop, the
   can't-frame-your-site strip). /informe loads it and matches none of it.
   Its own stage — three A4 sheets on a desk — is in informe-studio.css.
   Splitting those ~140 lines into a third file was considered and not
   done: they are inert, they are already fenced off by their section
   header, and one file that both pages load cannot fall out of step with
   itself.

   Everything here styles the STUDIO, never the thing on show. The widget
   is inside a shadow root and the report is inside an iframe, so neither
   is reachable from this file — that is the point, and it is also the
   honest demonstration: nothing on either page can accidentally make the
   product look better than it will on a stranger's site. The report's own
   re-skin lives in estudio/informe-theme.css and is injected INTO the
   iframe, which is a different mechanism for the same reason.
   ===================================================================== */

/* ---------------------------------------------------------------- shell */
html, body { height: 100%; }

body.studio-body {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  overflow: hidden;                 /* the rail and the stage scroll, not the page */
  background:
    radial-gradient(1100px 620px at 78% -8%, rgba(0, 153, 51, .16), transparent 62%),
    radial-gradient(760px 520px at 4% 108%, rgba(0, 153, 51, .09), transparent 60%),
    var(--color-navy-base);
}

/* --------------------------------------------------------------- header */
.studio-header {
  flex: 0 0 auto;
  border-bottom: 1px solid var(--color-divider);
  background: rgba(0, 0, 51, .72);
  backdrop-filter: blur(18px) saturate(130%);
  z-index: 40;
}

.studio-header-inner {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: .85rem clamp(1rem, 3vw, 1.75rem);
  max-width: none;
}

.studio-brand { display: flex; align-items: center; gap: .85rem; flex: 0 0 auto; }
.studio-brand img { height: 26px; width: auto; }
/* The two studios, as one control. This was a single static
   `.studio-brand-tag` pill until /informe existed; making it a pair of
   links rather than a label is what lets someone on a sales call move
   between the widget and the report without going back to a URL bar. The
   current one keeps exactly the pill's old treatment — it is still the
   "you are here" badge, it just has a sibling now. Both pages render this
   markup identically and differ only in which link carries
   aria-current="page"; that attribute is the single source of the
   selected state, so there is no class to forget on one of the two. */
.studio-switch { display: flex; gap: .35rem; flex: 0 0 auto; }
.studio-tab {
  font-size: .7rem; font-weight: 800; letter-spacing: .14em; text-transform: uppercase;
  padding: .3rem .6rem; border-radius: 999px; white-space: nowrap;
  text-decoration: none;
  color: var(--color-text-secondary);
  border: 1px solid transparent;
  transition: color .15s ease, border-color .15s ease, background .15s ease;
}
.studio-tab:hover { color: #fff; border-color: rgba(255, 255, 255, .18); }
.studio-tab[aria-current="page"] {
  color: var(--color-green-bright);
  border-color: rgba(62, 210, 122, .35);
  background: rgba(0, 153, 51, .12);
}
.studio-tab[aria-current="page"]:hover { color: var(--color-green-bright); }

.studio-header-spacer { flex: 1 1 auto; }

/* ------------------------------------------------------- segmented set */
/* Used for device sizes and for Demo/Tu web. Tinted-fill + border for the
   selected state, never a solid green fill — same rule as the rest of the
   site (see CLAUDE.md: a solid fill reads as a second, brighter green). */
.seg {
  display: inline-flex; gap: 2px; padding: 3px;
  background: rgba(255, 255, 255, .05);
  border: 1px solid var(--color-divider);
  border-radius: 999px;
}
.seg button {
  display: inline-flex; align-items: center; gap: .4rem;
  padding: .42rem .8rem; border-radius: 999px;
  font-size: .78rem; font-weight: 700; color: var(--color-text-secondary);
  transition: color .14s ease, background .14s ease;
  white-space: nowrap;
}
.seg button:hover { color: #fff; }
.seg button[aria-pressed="true"] {
  background: rgba(0, 153, 51, .16);
  color: var(--color-green-bright);
  box-shadow: inset 0 0 0 1px var(--color-green-primary);
}
.seg .ico { width: 15px; height: 15px; }
.seg--icons button { padding: .42rem .62rem; }

/* ----------------------------------------------------------- ghost btns */
.studio-btn {
  display: inline-flex; align-items: center; gap: .45rem;
  padding: .5rem .85rem; border-radius: var(--radius-field);
  border: 1px solid var(--color-divider);
  background: rgba(255, 255, 255, .04);
  font-size: .8rem; font-weight: 700; color: var(--color-text-secondary);
  transition: border-color .14s ease, color .14s ease, background .14s ease;
  white-space: nowrap;
}
.studio-btn:hover { color: #fff; border-color: rgba(255, 255, 255, .22); }
.studio-btn .ico { width: 15px; height: 15px; }
.studio-btn--go {
  border-color: var(--color-green-primary);
  background: rgba(0, 153, 51, .16);
  color: var(--color-green-bright);
}
.studio-btn--go:hover { background: rgba(0, 153, 51, .24); color: #fff; }

/* ----------------------------------------------------------------- body */
/* flex, not grid: the drawer is now a third flex child (see .drawer below)
   whose WIDTH animates from 0 — a flex sibling that grows naturally takes
   its space FROM the stage (flex:1, min-width:0), so the preview shrinks
   to stay fully visible instead of being covered by a fixed overlay. Grid
   would need grid-template-columns itself animated, which has patchier
   support than a plain width transition. */
.studio-main {
  flex: 1 1 auto;
  display: flex;
  min-height: 0;
  /* The drawer's open width, declared ONCE. It used to be written out four
     times — .drawer.is-open and .drawer-inner, then again in each of the two
     responsive overrides — and widget-studio.js needs the same number to
     decide whether a device preview still fits beside an open drawer
     (makeRoomForDevice). Five hand-reconciled copies of one measurement is
     this project's recurring bug shape, so there is one.
     In px, not rem, specifically so the JS can parseFloat() it: a custom
     property's computed value is the specified string, and "21rem" would
     have to be unit-converted by hand on the JS side. 336px == 21rem at the
     default root size. */
  --drawer-w: 336px;
}

/* ----------------------------------------------------------------- rail */
.studio-rail {
  flex: 0 0 335px;
  min-height: 0;
  border-right: 1px solid var(--color-divider);
  background: rgba(10, 10, 61, .45);
  overflow-y: auto;
  padding: 1.1rem 1.1rem 2.5rem;
  display: flex; flex-direction: column; gap: 1rem;
  scrollbar-width: thin;
}
.studio-rail::-webkit-scrollbar { width: 9px; }
.studio-rail::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, .14); border-radius: 99px;
}

.rail-card {
  border: 1px solid var(--color-divider);
  background: rgba(255, 255, 255, .035);
  border-radius: var(--radius-card);
  padding: 1rem;
}
.rail-card-head {
  display: flex; align-items: center; gap: .55rem; margin-bottom: .9rem;
}
.rail-card-head .ico { width: 16px; height: 16px; color: var(--color-green-bright); }
.rail-card-head h2 {
  font-size: .82rem; font-weight: 800; letter-spacing: .02em; margin: 0;
}
/* A rail card that folds (<details>), e.g. «Animación del botón». */
.rail-fold > summary { list-style: none; cursor: pointer; margin-bottom: 0; user-select: none; }
.rail-fold > summary::-webkit-details-marker { display: none; }
.rail-fold[open] > summary { margin-bottom: .9rem; }
.rail-fold-note { margin-left: auto; font-size: .72rem; font-weight: 700; color: var(--color-text-muted); }
.rail-fold-note.is-on { color: var(--color-green-bright); }
.rail-fold > summary::after {
  content: ""; width: 7px; height: 7px; flex: 0 0 auto; margin-left: .35rem;
  border-right: 2px solid var(--color-text-muted); border-bottom: 2px solid var(--color-text-muted);
  transform: rotate(-45deg); transition: transform .18s ease;
}
.rail-fold[open] > summary::after { transform: rotate(45deg); }
.ctl-select:disabled { opacity: .45; cursor: not-allowed; }

/* switch row */
.switch-row {
  display: flex; align-items: center; gap: .75rem; cursor: pointer;
  font-size: .84rem; font-weight: 700;
}
.switch-row input { position: absolute; opacity: 0; width: 0; height: 0; }
.switch {
  flex: 0 0 auto; width: 40px; height: 23px; border-radius: 999px;
  background: rgba(255, 255, 255, .12);
  border: 1px solid var(--color-divider);
  position: relative; transition: background .18s ease, border-color .18s ease;
}
.switch::after {
  content: ""; position: absolute; top: 2px; left: 2px;
  width: 17px; height: 17px; border-radius: 50%;
  background: var(--color-text-secondary);
  transition: transform .18s cubic-bezier(.2, .7, .3, 1), background .18s ease;
}
/* Scoped to .switch itself, not to .switch-row: the drawer's .toggle-row
   uses the same input+span pairing, and a row-scoped selector silently
   left every toggle in there painted as "off" while its checkbox was
   really on — the control said one thing and the widget did another. */
input:checked + .switch {
  background: rgba(0, 153, 51, .28); border-color: var(--color-green-primary);
}
input:checked + .switch::after {
  transform: translateX(17px); background: var(--color-green-bright);
}
input:focus-visible + .switch { box-shadow: 0 0 0 3px var(--color-green-glow); }
.switch-note {
  margin: .6rem 0 0; font-size: .72rem; font-weight: 500;
  color: var(--color-text-muted); line-height: 1.45;
}

/* the collapsible "which site" block under the switch */
.site-block { margin-top: .85rem; display: grid; gap: .6rem; }
.site-block[hidden] { display: none; }

/* ------------------------------------------------------------- controls */
.ctl { display: block; }
.ctl + .ctl { margin-top: .85rem; }
.ctl-label {
  display: flex; align-items: baseline; justify-content: space-between; gap: .5rem;
  font-size: .73rem; font-weight: 700; color: var(--color-text-secondary);
  margin-bottom: .35rem; letter-spacing: .01em;
}
.ctl-value { font-size: .72rem; font-weight: 700; color: var(--color-green-bright); }
/* Two sliders under one label (launcher size: Ordenador / Móvil). */
.ctl-sub { display: block; }
.ctl-sub + .ctl-sub { margin-top: .35rem; }
.ctl-sub-label {
  display: flex; align-items: center; gap: .4rem;
  font-size: .72rem; font-weight: 600; color: var(--color-text-muted);
}
.ctl-sub-label .ico { width: 14px; height: 14px; }
.ctl-sub-label .ctl-value { margin-left: auto; }

.ctl-input,
.ctl-select {
  width: 100%;
  background: rgba(255, 255, 255, .05);
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-field);
  padding: .55rem .7rem;
  font-size: .82rem; font-weight: 600; color: #fff;
  outline: none;
  transition: border-color .14s ease, box-shadow .14s ease;
}
.ctl-input::placeholder { color: var(--color-text-muted); }
.ctl-input:focus,
.ctl-select:focus {
  border-color: var(--color-green-primary);
  box-shadow: 0 0 0 3px rgba(0, 153, 51, .18);
}
.ctl-select {
  appearance: none; -webkit-appearance: none; cursor: pointer;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none' stroke='%239CA6BF' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'><path d='M1 1.5 6 6.5l5-5'/></svg>");
  background-repeat: no-repeat; background-position: right .7rem center;
  padding-right: 2rem;
}
.ctl-select option { background: #0A0A3D; color: #fff; }

/* colour row */
.color-row { display: flex; align-items: center; gap: .55rem; }
.color-chip {
  flex: 0 0 auto; width: 38px; height: 38px; padding: 0;
  border-radius: 11px; overflow: hidden; cursor: pointer;
  border: 1px solid rgba(255, 255, 255, .22);
  background: none;
}
.color-chip::-webkit-color-swatch-wrapper { padding: 2px; }
.color-chip::-webkit-color-swatch { border: none; border-radius: 9px; }
.color-chip::-moz-color-swatch { border: none; border-radius: 9px; }
.color-row .ctl-input { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.eyedropper-btn {
  flex: 0 0 auto; width: 38px; height: 38px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 11px; cursor: pointer;
  border: 1px solid var(--color-divider);
  background: rgba(255, 255, 255, .05);
  color: var(--color-text-secondary);
  transition: background .14s ease, color .14s ease, border-color .14s ease;
}
.eyedropper-btn:hover { background: rgba(0, 153, 51, .18); color: #fff; border-color: var(--color-green-primary); }
.eyedropper-btn .ico { width: 16px; height: 16px; }
.eyedropper-btn[hidden] { display: none; }

/* range */
.ctl-range { width: 100%; appearance: none; background: none; height: 20px; cursor: pointer; }
.ctl-range::-webkit-slider-runnable-track {
  height: 4px; border-radius: 99px; background: rgba(255, 255, 255, .14);
}
.ctl-range::-moz-range-track {
  height: 4px; border-radius: 99px; background: rgba(255, 255, 255, .14);
}
.ctl-range::-webkit-slider-thumb {
  appearance: none; width: 16px; height: 16px; margin-top: -6px;
  border-radius: 50%; background: var(--color-green-bright);
  border: 2px solid #06122a; box-shadow: 0 0 0 3px rgba(0, 153, 51, .25);
}
.ctl-range::-moz-range-thumb {
  width: 16px; height: 16px; border-radius: 50%;
  background: var(--color-green-bright);
  border: 2px solid #06122a; box-shadow: 0 0 0 3px rgba(0, 153, 51, .25);
}

/* presets */
.presets { display: grid; grid-template-columns: repeat(8, 1fr); gap: .35rem; }
.preset {
  width: 100%; aspect-ratio: 1; border-radius: 8px;
  border: 1px solid rgba(255, 255, 255, .18);
  transition: transform .14s ease, box-shadow .14s ease;
}
.preset:hover { transform: translateY(-2px); }
.preset[aria-pressed="true"] { box-shadow: 0 0 0 2px var(--color-green-bright); }

/* full-width rail button */
.rail-btn {
  width: 100%;
  display: inline-flex; align-items: center; justify-content: center; gap: .45rem;
  padding: .7rem .9rem; border-radius: var(--radius-field);
  font-size: .82rem; font-weight: 800;
  border: 1px solid var(--color-green-primary);
  background: rgba(0, 153, 51, .14);
  color: var(--color-green-bright);
  transition: background .14s ease, color .14s ease;
}
.rail-btn:hover { background: rgba(0, 153, 51, .24); color: #fff; }
.rail-btn .ico { width: 15px; height: 15px; }
.rail-btn--quiet {
  border-color: var(--color-divider);
  background: rgba(255, 255, 255, .04);
  color: var(--color-text-secondary);
  font-weight: 700;
}
.rail-btn--quiet:hover { color: #fff; border-color: rgba(255, 255, 255, .22); }

/* ---------------------------------------------------------------- stage */
.studio-stage {
  flex: 1 1 auto;
  min-width: 0; min-height: 0;
  display: flex; flex-direction: column;
  padding: clamp(.9rem, 2.2vw, 1.6rem);
  gap: .75rem;
}

.stage-bar {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: .75rem; flex-wrap: wrap;
}
.stage-title {
  display: flex; align-items: center; gap: .5rem;
  font-size: .78rem; font-weight: 700; color: var(--color-text-secondary);
}
.stage-title .ico { width: 15px; height: 15px; color: var(--color-green-bright); }
.stage-bar-spacer { flex: 1 1 auto; }

.stage-frame {
  flex: 1 1 auto; min-height: 0;
  display: flex; align-items: stretch; justify-content: center;
}

/* ─── /widget only, from here to the end of this section ──────────────
   The browser-window mock, the three device widths, the iframe backdrop
   and the frame-warning strip. /informe loads this file for the chrome
   above and matches none of what follows; its stage is in
   informe-studio.css. Anything added below that a report studio would
   also want belongs ABOVE this line, not copied across. */

/* the browser-window mock that holds the preview */
.viewport {
  position: relative;
  /* The widget ships a z-index in the 2-billion range so it wins on a
     stranger's page. Without a stacking context here it wins on THIS page
     too, and floats over the settings drawer. Isolating the preview is
     the fix; never lower the widget's own z-index to work around it. */
  isolation: isolate; z-index: 0;
  /* The per-device width is set by widget-studio.js as --viewport-max
     rather than living in a .viewport--tablet/--mobile rule here. Those
     numbers have to be known to the JS too (it checks whether the chosen
     device still fits beside an open drawer), and a hardcoded copy in each
     file reconciled by hand is this project's recurring bug shape. One
     source, in DEVICE_MAX; this just consumes it. */
  width: 100%; max-width: var(--viewport-max, 100%);
  display: flex; flex-direction: column;
  background: #fff;
  border-radius: 16px;
  overflow: hidden;
  box-shadow: 0 34px 80px -24px rgba(0, 0, 0, .75), 0 0 0 1px rgba(255, 255, 255, .09);
  transition: max-width .35s cubic-bezier(.2, .7, .3, 1);
}
.viewport--mobile { border-radius: 30px; }

.viewport-chrome {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: .6rem;
  padding: .5rem .8rem;
  background: #EDEFF3;
  border-bottom: 1px solid #DDE1E8;
}
.viewport--mobile .viewport-chrome { justify-content: center; padding: .55rem .8rem; }
.viewport--mobile .dots { display: none; }
.dots { display: flex; gap: 5px; flex: 0 0 auto; }
.dots i { width: 10px; height: 10px; border-radius: 50%; background: #C9CFD9; }
.dots i:nth-child(1) { background: #F0625B; }
.dots i:nth-child(2) { background: #F5BE4F; }
.dots i:nth-child(3) { background: #62C554; }
.viewport-url {
  flex: 1 1 auto; min-width: 0;
  background: #fff; border: 1px solid #DDE1E8; border-radius: 999px;
  padding: .28rem .8rem;
  font-size: .72rem; font-weight: 600; color: #6A7383;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.viewport--mobile .viewport-url { flex: 0 1 auto; max-width: 70%; text-align: center; }

/* where the iframe + the widget layer live, stacked */
.canvas {
  position: relative;
  flex: 1 1 auto; min-height: 0;
  background: #fff;
  overflow: hidden;
}
.canvas iframe {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  border: 0; background: #fff;
}

/* draft canvas: no site, just a surface for the panel to sit on */
.canvas--draft {
  background:
    radial-gradient(900px 500px at 50% -10%, #EFF2F7, transparent 70%),
    repeating-linear-gradient(45deg, #F6F8FB 0 12px, #F2F5F9 12px 24px);
}
/* The layer the widget mounts into — must not eat the iframe's own events.
   ⚠️ `isolation: isolate` is load-bearing, for the same reason .viewport
   carries it (see above) but one level further in. The widget ships
   `z-index: 2147483000` on its launcher so it wins on a stranger's page.
   Without a stacking context HERE, that number competes directly with
   .canvas's own children and beats everything the studio puts beside the
   widget — which is exactly what it did to .frame-warn's buttons: the
   launcher sat on top of "Usar la web de demostración" / "Se ve bien,
   gracias" and swallowed the clicks in 6 of the 9 device x
   launcherPosition combinations (confirmed with elementFromPoint, which
   returned the widget host, not the button). Isolating the layer contains
   that z-index so the three siblings below can be ordered in plain
   single digits. Never fix this class of thing by lowering the widget's
   own z-index — it is correct for the real world, and the studio is the
   thing that has to accommodate it. */
.widget-layer {
  position: absolute; inset: 0; pointer-events: none;
  isolation: isolate; z-index: 2;
}

/* framing-blocked notice. A strip along the bottom, never a modal over the
   middle: this cannot know whether the site actually loaded (see
   widget-studio.js's header), so it must not hide a site that did.
   z-index 3 — above the widget layer, so its buttons stay clickable
   wherever the launcher happens to be docked. */
.frame-warn {
  position: absolute; left: 50%; bottom: 1rem; transform: translateX(-50%);
  width: min(38rem, calc(100% - 2rem));
  display: flex; align-items: center; gap: 1rem; flex-wrap: wrap;
  background: #101223; color: #E7EAF2;
  border: 1px solid rgba(255, 255, 255, .14); border-radius: 14px;
  padding: .85rem 1rem;
  box-shadow: 0 24px 60px -18px rgba(10, 14, 24, .55);
  z-index: 3;
}
.frame-warn p { margin: 0; flex: 1 1 16rem; font-size: .78rem; line-height: 1.5; color: #B9C1D4; }
.frame-warn strong { color: #fff; font-weight: 800; }
.frame-warn-actions { display: flex; gap: .45rem; flex: 0 0 auto; }

/* Shown the instant a real-site load starts, gone the moment the frame
   fires 'load' (or the next repaint tears it down). A blocked frame and a
   slow one look identical for the first second or two — this just says
   "something is happening" rather than leaving a blank white box that
   reads as frozen. */
.frame-loading {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  display: flex; align-items: center; gap: .55rem;
  font-size: .8rem; font-weight: 700; color: #6A7383;
  z-index: 1; pointer-events: none;   /* under the widget layer (2), over the iframe */
}
.frame-loading::before {
  content: ""; width: 15px; height: 15px; border-radius: 50%;
  border: 2px solid #DDE1E8; border-top-color: #6A7383;
  animation: frame-loading-spin .7s linear infinite;
}
@keyframes frame-loading-spin { to { transform: rotate(360deg); } }

/* stage hint strip under the viewport */
.stage-hint {
  flex: 0 0 auto;
  display: flex; align-items: center; justify-content: center; gap: .5rem;
  font-size: .73rem; font-weight: 600; color: var(--color-text-muted);
  text-align: center;
}
.stage-hint .ico { width: 14px; height: 14px; }

/* ---------------------------------------------------------------- drawer */
/* A flex sibling of the rail and the stage (see .studio-main), not a
   fixed overlay — PUSHES the stage narrower as it opens instead of
   covering it. `hidden` is never toggled on this element any more (that
   would set display:none, which cannot transition); `.is-open` is, and
   width/border animate together. `overflow:hidden` while closed is what
   makes width:0 actually hide the content rather than just clipping a
   giant box; `.drawer-inner` below is a fixed-width child so the content
   itself never squashes mid-animation — the reveal looks like uncovering
   a properly-laid-out panel, not un-squishing one. */
.drawer {
  flex: 0 0 auto;
  width: 0;
  /* A flex row item's default min-height is `auto`, which for a block
     with overflowing content means "at least as tall as that content" —
     overflow:hidden does NOT override this, it only clips once the size
     is decided. Without this, the drawer's real content height (drawer
     body full of controls) forced .studio-main itself taller than the
     viewport even while width:0/closed — found live: the whole stage
     landed ~1200px down the page, well outside the visible viewport,
     because the flex row had grown to fit an invisible sibling. */
  min-height: 0;
  overflow: hidden;
  background: #06062B;
  border-left: 0 solid var(--color-divider);
  position: relative; z-index: 5;
  transition: width .3s cubic-bezier(.2, .7, .3, 1),
              border-left-width .3s cubic-bezier(.2, .7, .3, 1);
}
.drawer.is-open {
  width: min(var(--drawer-w), 100%);
  border-left-width: 1px;
}
.drawer-inner {
  width: var(--drawer-w); max-width: 100%; height: 100%; min-height: 0;
  display: flex; flex-direction: column;
}

.drawer-head {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: .75rem;
  padding: 1.1rem 1.1rem;
  border-bottom: 1px solid var(--color-divider);
}
.drawer-head h2 { margin: 0; font-size: 1rem; font-weight: 800; flex: 1 1 auto; }
.drawer-close {
  width: 32px; height: 32px; border-radius: 10px; flex: 0 0 auto;
  display: grid; place-items: center; color: var(--color-text-secondary);
  transition: background .14s ease, color .14s ease;
}
.drawer-close:hover { background: rgba(255, 255, 255, .08); color: #fff; }
.drawer-close .ico { width: 16px; height: 16px; }

.drawer-body {
  flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden;
  padding: 1.1rem 1.1rem 2rem;
  display: flex; flex-direction: column; gap: 1.25rem;
  scrollbar-width: thin;
}
.drawer-body::-webkit-scrollbar { width: 9px; }
.drawer-body::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, .14); border-radius: 99px; }

.drawer-group > h3 {
  margin: 0 0 .75rem;
  font-size: .7rem; font-weight: 800; letter-spacing: .14em; text-transform: uppercase;
  color: var(--color-green-bright);
}
/* Single column, not two across. Was 1fr 1fr with a couple of controls
   spanning both (.ctl--wide) — stacking every control keeps the drawer
   narrow (21rem instead of the 30rem the two-across layout needed to
   stay legible) at no real cost, since none of these pairs read as one
   idea that benefits from sitting side by side. */
.drawer-grid { display: grid; grid-template-columns: 1fr; gap: .7rem; }
.drawer-grid .ctl + .ctl { margin-top: 0; }

.toggle-list { display: grid; gap: .5rem; }
.toggle-row {
  display: flex; align-items: center; gap: .75rem; cursor: pointer;
  padding: .6rem .75rem;
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-field);
  background: rgba(255, 255, 255, .035);
  font-size: .8rem; font-weight: 700;
  transition: border-color .14s ease, background .14s ease;
}
.toggle-row:hover { border-color: rgba(255, 255, 255, .2); }
.toggle-row input { position: absolute; opacity: 0; width: 0; height: 0; }
/* :not(.switch) — a bare `.toggle-row span` also matches the .switch
   handle itself (it's a span too), and since `.toggle-row span` (0,1,1)
   outranks `.switch`'s own `flex: 0 0 auto` (0,1,0), every switch in this
   panel was stretching to fill the row's leftover width — worse on rows
   with a short label, which left more space to stretch into. Found live,
   screenshot showed "Preguntar características" as a long pill next to
   three normal-sized switches on the very same panel. */
.toggle-row span:not(.switch) { flex: 1 1 auto; }
.toggle-row small {
  display: block; font-size: .72rem; font-weight: 500;
  color: var(--color-text-muted); margin-top: .1rem;
}
.toggle-row:has(input:checked) {
  border-color: var(--color-green-primary);
  background: rgba(0, 153, 51, .1);
}

.drawer-foot {
  flex: 0 0 auto;
  padding: .9rem 1.1rem;
  border-top: 1px solid var(--color-divider);
  display: flex; gap: .6rem;
  background: rgba(0, 0, 30, .6);
}
.drawer-foot .rail-btn { flex: 1 1 auto; }

/* ------------------------------------------------------------ responsive */
@media (max-width: 1080px) {
  .studio-rail { flex-basis: 296px; }
  .studio-main { --drawer-w: 304px; }   /* 19rem */
}

/* Under a tablet the two-pane layout stops working: the rail eats the
   stage. Stack them and let the page scroll normally — the studio is a
   desktop tool and this is the graceful version of saying so. */
@media (max-width: 900px) {
  body.studio-body { overflow: auto; }
  .studio-main { flex-direction: column; }
  .studio-rail {
    flex-basis: auto;
    border-right: 0; border-bottom: 1px solid var(--color-divider);
    overflow: visible; padding-bottom: 1.25rem;
  }
  .studio-stage { padding-bottom: 2rem; }
  .stage-frame { min-height: 70vh; }
  .studio-header-inner { flex-wrap: wrap; }

  /* A push-panel makes no sense once the rail and stage are already
     stacked in one column — there is no "narrower but still usable"
     stage to push into. Falls back to the old overlay behaviour here
     only: fixed, full-height, slides in over the stage. */
  .drawer {
    position: fixed; top: 0; right: 0; bottom: 0; z-index: 61;
    width: 0; border-left-width: 0;
    box-shadow: -30px 0 70px -20px rgba(0, 0, 0, .7);
    transition: width .3s cubic-bezier(.2, .7, .3, 1);
  }
  .studio-main { --drawer-w: 384px; }   /* 24rem */
  .drawer.is-open { border-left-width: 1px; }
}

@media (prefers-reduced-motion: reduce) {
  .viewport, .switch, .switch::after, .preset, .drawer,
  .studio-tab, .sheet-stack { transition: none; }
}
